summaryrefslogtreecommitdiff
path: root/chromium/content
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-07-31 15:50:41 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 12:35:23 +0000
commit7b2ffa587235a47d4094787d72f38102089f402a (patch)
tree30e82af9cbab08a7fa028bb18f4f2987a3f74dfa /chromium/content
parentd94af01c90575348c4e81a418257f254b6f8d225 (diff)
downloadqtwebengine-chromium-7b2ffa587235a47d4094787d72f38102089f402a.tar.gz
BASELINE: Update Chromium to 76.0.3809.94
Change-Id: I321c3f5f929c105aec0f98c5091ef6108822e647 Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/content')
-rw-r--r--chromium/content/BUILD.gn3
-rw-r--r--chromium/content/OWNERS1
-rw-r--r--chromium/content/app/BUILD.gn1
-rw-r--r--chromium/content/app/DEPS1
-rw-r--r--chromium/content/app/android/content_child_process_service_delegate.cc38
-rw-r--r--chromium/content/app/android/content_main.cc5
-rw-r--r--chromium/content/app/android/library_loader_hooks.cc3
-rw-r--r--chromium/content/app/content_main_runner_impl.cc38
-rw-r--r--chromium/content/app/content_main_runner_impl.h2
-rw-r--r--chromium/content/app/strings/content_strings.grd20
-rw-r--r--chromium/content/app/strings/content_strings_grd/IDS_MEDIA_SESSION_FILE_SOURCE.png.sha11
-rw-r--r--chromium/content/app/strings/translations/content_strings_am.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_ar.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_bg.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_bn.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_ca.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_cs.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_da.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_de.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_el.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_en-GB.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_es-419.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_es.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_et.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_fa.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_fi.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_fil.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_fr.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_gu.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_hi.xtb12
-rw-r--r--chromium/content/app/strings/translations/content_strings_hr.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_hu.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_id.xtb8
-rw-r--r--chromium/content/app/strings/translations/content_strings_it.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_iw.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_ja.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_kn.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_ko.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_lt.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_lv.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_ml.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_mr.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_ms.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_nl.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_no.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_pl.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_pt-BR.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_pt-PT.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_ro.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_ru.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_sk.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_sl.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_sr.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_sv.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_sw.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_ta.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_te.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_th.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_tr.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_uk.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_vi.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_zh-CN.xtb6
-rw-r--r--chromium/content/app/strings/translations/content_strings_zh-TW.xtb6
-rw-r--r--chromium/content/app_shim_remote_cocoa/DEPS35
-rw-r--r--chromium/content/app_shim_remote_cocoa/ns_view_bridge_factory_impl.mm (renamed from chromium/content/browser/ns_view_bridge_factory_impl.mm)46
-rw-r--r--chromium/content/app_shim_remote_cocoa/popup_window_mac.h (renamed from chromium/content/browser/renderer_host/popup_window_mac.h)6
-rw-r--r--chromium/content/app_shim_remote_cocoa/popup_window_mac.mm (renamed from chromium/content/browser/renderer_host/popup_window_mac.mm)4
-rw-r--r--chromium/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge_local.h (renamed from chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h)10
-rw-r--r--chromium/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge_local.mm (renamed from chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm)8
-rw-r--r--chromium/content/app_shim_remote_cocoa/render_widget_host_ns_view_client_helper.h (renamed from chromium/content/browser/renderer_host/render_widget_host_ns_view_client_helper.h)6
-rw-r--r--chromium/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h (renamed from chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h)15
-rw-r--r--chromium/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm (renamed from chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm)90
-rw-r--r--chromium/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.h (renamed from chromium/content/browser/web_contents/web_contents_ns_view_bridge.h)12
-rw-r--r--chromium/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.mm (renamed from chromium/content/browser/web_contents/web_contents_ns_view_bridge.mm)15
-rw-r--r--chromium/content/app_shim_remote_cocoa/web_contents_view_cocoa.h (renamed from chromium/content/browser/web_contents/web_contents_view_cocoa.h)6
-rw-r--r--chromium/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm (renamed from chromium/content/browser/web_contents/web_contents_view_cocoa.mm)6
-rw-r--r--chromium/content/app_shim_remote_cocoa/web_drag_source_mac.h (renamed from chromium/content/browser/web_contents/web_drag_source_mac.h)6
-rw-r--r--chromium/content/app_shim_remote_cocoa/web_drag_source_mac.mm (renamed from chromium/content/browser/web_contents/web_drag_source_mac.mm)9
-rw-r--r--chromium/content/browser/BUILD.gn225
-rw-r--r--chromium/content/browser/DEPS10
-rw-r--r--chromium/content/browser/OWNERS6
-rw-r--r--chromium/content/browser/accessibility/OWNERS8
-rw-r--r--chromium/content/browser/accessibility/accessibility_action_browsertest.cc3
-rw-r--r--chromium/content/browser/accessibility/accessibility_auralinux_browsertest.cc440
-rw-r--r--chromium/content/browser/accessibility/accessibility_browsertest.cc19
-rw-r--r--chromium/content/browser/accessibility/accessibility_browsertest.h2
-rw-r--r--chromium/content/browser/accessibility/accessibility_content_browsertest.cc130
-rw-r--r--chromium/content/browser/accessibility/accessibility_content_browsertest.h53
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc33
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder_uia_win.cc15
-rw-r--r--chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc20
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc2
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc3
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm10
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc2
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc7
-rw-r--r--chromium/content/browser/accessibility/accessibility_win_browsertest.cc203
-rw-r--r--chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc2
-rw-r--r--chromium/content/browser/accessibility/aom_browsertest.cc3
-rw-r--r--chromium/content/browser/accessibility/ax_platform_node_textprovider_win_browsertest.cc190
-rw-r--r--chromium/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc888
-rw-r--r--chromium/content/browser/accessibility/ax_platform_node_win_browsertest.cc187
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc397
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.h64
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.cc26
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.h6
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_auralinux.cc14
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_auralinux.h1
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm80
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm126
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_com_win.cc58
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_com_win.h3
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm40
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc337
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h70
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.cc22
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc26
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm17
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc110
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.cc123
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.h29
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_position.cc17
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_position.h3
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.cc2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm36
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc3
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_unittest.cc428
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.cc6
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.h1
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc10
-rw-r--r--chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc102
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc55
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h15
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc95
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc8
-rw-r--r--chromium/content/browser/accessibility/snapshot_ax_tree_browsertest.cc8
-rw-r--r--chromium/content/browser/accessibility/test_browser_accessibility_delegate.cc2
-rw-r--r--chromium/content/browser/accessibility/test_browser_accessibility_delegate.h2
-rw-r--r--chromium/content/browser/accessibility/web_contents_accessibility_android.cc24
-rw-r--r--chromium/content/browser/after_startup_task_utils.cc2
-rw-r--r--chromium/content/browser/android/app_web_message_port.cc5
-rw-r--r--chromium/content/browser/android/content_feature_list.cc4
-rw-r--r--chromium/content/browser/android/content_feature_list.h1
-rw-r--r--chromium/content/browser/android/date_time_chooser_android.cc93
-rw-r--r--chromium/content/browser/android/date_time_chooser_android.h47
-rw-r--r--chromium/content/browser/android/dialog_overlay_impl.cc9
-rw-r--r--chromium/content/browser/android/gpu_process_callback.cc8
-rw-r--r--chromium/content/browser/android/ime_adapter_android.cc6
-rw-r--r--chromium/content/browser/android/java/gin_java_bound_object.cc12
-rw-r--r--chromium/content/browser/android/render_widget_host_connector.cc25
-rw-r--r--chromium/content/browser/android/render_widget_host_connector.h2
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.cc14
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.h8
-rw-r--r--chromium/content/browser/android/web_contents_observer_proxy.cc3
-rw-r--r--chromium/content/browser/appcache/appcache_backend_impl.cc43
-rw-r--r--chromium/content/browser/appcache/appcache_backend_impl.h14
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.cc8
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.h5
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache_unittest.cc8
-rw-r--r--chromium/content/browser/appcache/appcache_fuzzer.cc13
-rw-r--r--chromium/content/browser/appcache/appcache_group_unittest.cc27
-rw-r--r--chromium/content/browser/appcache/appcache_host.cc27
-rw-r--r--chromium/content/browser/appcache/appcache_host.h28
-rw-r--r--chromium/content/browser/appcache/appcache_host_unittest.cc8
-rw-r--r--chromium/content/browser/appcache/appcache_interceptor.cc20
-rw-r--r--chromium/content/browser/appcache/appcache_interceptor.h4
-rw-r--r--chromium/content/browser/appcache/appcache_internals_ui.cc1
-rw-r--r--chromium/content/browser/appcache/appcache_navigation_handle.cc8
-rw-r--r--chromium/content/browser/appcache/appcache_navigation_handle.h7
-rw-r--r--chromium/content/browser/appcache/appcache_navigation_handle_core.cc7
-rw-r--r--chromium/content/browser/appcache/appcache_navigation_handle_core.h8
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler_unittest.cc33
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.cc58
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.h28
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl.cc41
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl.h6
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl_unittest.cc45
-rw-r--r--chromium/content/browser/appcache/appcache_subresource_url_factory.cc13
-rw-r--r--chromium/content/browser/appcache/appcache_unittest.cc6
-rw-r--r--chromium/content/browser/appcache/appcache_update_job.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_update_job_unittest.cc213
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_loader_request.cc3
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_loader_request.h2
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_context.cc2
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_context.h6
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager.cc2
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc1
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc43
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h8
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler.cc40
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler.h15
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_unittest.cc2
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_base.cc2
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_base.h4
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_data_manager.cc6
-rw-r--r--chromium/content/browser/background_fetch/storage/create_metadata_task.cc1
-rw-r--r--chromium/content/browser/background_fetch/storage/database_task.cc1
-rw-r--r--chromium/content/browser/background_fetch/storage/delete_registration_task.cc1
-rw-r--r--chromium/content/browser/background_fetch/storage/get_request_blob_task.cc1
-rw-r--r--chromium/content/browser/background_fetch/storage/get_request_blob_task.h1
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc1
-rw-r--r--chromium/content/browser/background_fetch/storage/match_requests_task.cc1
-rw-r--r--chromium/content/browser/background_fetch/storage/match_requests_task.h2
-rw-r--r--chromium/content/browser/background_sync/background_sync.proto1
-rw-r--r--chromium/content/browser/background_sync/background_sync_browsertest.cc6
-rw-r--r--chromium/content/browser/background_sync/background_sync_context_impl.cc7
-rw-r--r--chromium/content/browser/background_sync/background_sync_context_impl.h7
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.cc287
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.h47
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager_unittest.cc517
-rw-r--r--chromium/content/browser/background_sync/background_sync_metrics.cc9
-rw-r--r--chromium/content/browser/background_sync/background_sync_metrics.h4
-rw-r--r--chromium/content/browser/background_sync/background_sync_registration.h3
-rw-r--r--chromium/content/browser/background_sync/background_sync_service_impl.cc8
-rw-r--r--chromium/content/browser/background_sync/background_sync_service_impl.h7
-rw-r--r--chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc6
-rw-r--r--chromium/content/browser/bad_message.h3
-rw-r--r--chromium/content/browser/blob_storage/chrome_blob_storage_context.cc7
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_allowed_devices.h2
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_blocklist.h2
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h2
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.cc61
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.h66
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_metrics.h2
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_util.cc45
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_util.h18
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_util_unittest.cc158
-rw-r--r--chromium/content/browser/bluetooth/frame_connected_bluetooth_devices.h2
-rw-r--r--chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc225
-rw-r--r--chromium/content/browser/bluetooth/web_bluetooth_service_impl.h63
-rw-r--r--chromium/content/browser/browser_context.cc66
-rw-r--r--chromium/content/browser/browser_main_loop.cc207
-rw-r--r--chromium/content/browser/browser_main_loop.h21
-rw-r--r--chromium/content/browser/browser_main_loop_unittest.cc91
-rw-r--r--chromium/content/browser/browser_main_runner_impl.cc17
-rw-r--r--chromium/content/browser/browser_main_runner_impl.h2
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.cc100
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.h14
-rw-r--r--chromium/content/browser/browser_process_sub_thread.cc18
-rw-r--r--chromium/content/browser/browser_process_sub_thread.h4
-rw-r--r--chromium/content/browser/browser_thread_browsertest.cc32
-rw-r--r--chromium/content/browser/browser_thread_impl.cc11
-rw-r--r--chromium/content/browser/browser_thread_unittest.cc120
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.cc17
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.h20
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl.cc41
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl.h2
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc324
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc39
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_throttle.cc2
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_throttle.h2
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_throttle_unittest.cc4
-rw-r--r--chromium/content/browser/browsing_instance.cc30
-rw-r--r--chromium/content/browser/browsing_instance.h5
-rw-r--r--chromium/content/browser/builtin_service_manifests.cc115
-rw-r--r--chromium/content/browser/builtin_service_manifests.h20
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc2
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h8
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc50
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache_entry_handler.h3
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc109
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_context_impl.cc140
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_context_impl.h27
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc55
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h38
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.cc467
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.h165
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc196
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_operation.cc2
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_operation.h13
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_scheduler.cc22
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_scheduler.h10
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_scheduler_unittest.cc4
-rw-r--r--chromium/content/browser/cache_storage/legacy/legacy_cache_storage.cc49
-rw-r--r--chromium/content/browser/cache_storage/legacy/legacy_cache_storage.h7
-rw-r--r--chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc160
-rw-r--r--chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h19
-rw-r--r--chromium/content/browser/cache_storage/legacy/legacy_cache_storage_manager.cc479
-rw-r--r--chromium/content/browser/cache_storage/legacy/legacy_cache_storage_manager.h170
-rw-r--r--chromium/content/browser/cache_storage/scoped_writable_entry.h49
-rw-r--r--chromium/content/browser/child_process_launcher.cc4
-rw-r--r--chromium/content/browser/child_process_launcher_helper_android.cc4
-rw-r--r--chromium/content/browser/child_process_launcher_helper_mac.cc77
-rw-r--r--chromium/content/browser/child_process_security_policy_unittest.cc21
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache.cc6
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache.h3
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache_unittest.cc16
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.cc37
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.h31
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc7
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h6
-rw-r--r--chromium/content/browser/compositor/gpu_output_surface_mac.cc32
-rw-r--r--chromium/content/browser/compositor/gpu_output_surface_mac.h32
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.cc199
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.h9
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc7
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h4
-rw-r--r--chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc7
-rw-r--r--chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h4
-rw-r--r--chromium/content/browser/compositor/reflector_impl.cc18
-rw-r--r--chromium/content/browser/compositor/reflector_impl.h8
-rw-r--r--chromium/content/browser/compositor/reflector_impl_unittest.cc50
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface.cc23
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface.h18
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc168
-rw-r--r--chromium/content/browser/compositor/viz_process_transport_factory.cc17
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc13
-rw-r--r--chromium/content/browser/device_sensors/device_sensor_browsertest.cc5
-rw-r--r--chromium/content/browser/devtools/BUILD.gn2
-rw-r--r--chromium/content/browser/devtools/OWNERS3
-rw-r--r--chromium/content/browser/devtools/browser_devtools_agent_host.cc4
-rw-r--r--chromium/content/browser/devtools/devtools_background_services.proto6
-rw-r--r--chromium/content/browser/devtools/devtools_background_services_context_impl.cc (renamed from chromium/content/browser/devtools/devtools_background_services_context.cc)119
-rw-r--r--chromium/content/browser/devtools/devtools_background_services_context_impl.h (renamed from chromium/content/browser/devtools/devtools_background_services_context.h)67
-rw-r--r--chromium/content/browser/devtools/devtools_background_services_context_impl_unittest.cc (renamed from chromium/content/browser/devtools/devtools_background_services_context_unittest.cc)46
-rw-r--r--chromium/content/browser/devtools/devtools_frame_metadata.cc45
-rw-r--r--chromium/content/browser/devtools/devtools_frame_metadata.h38
-rw-r--r--chromium/content/browser/devtools/devtools_frame_trace_recorder.cc13
-rw-r--r--chromium/content/browser/devtools/devtools_frame_trace_recorder.h13
-rw-r--r--chromium/content/browser/devtools/devtools_frontend_host_impl.cc2
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler.cc4
-rw-r--r--chromium/content/browser/devtools/devtools_instrumentation.cc44
-rw-r--r--chromium/content/browser/devtools/devtools_instrumentation.h8
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding.cc48
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding.h32
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer.cc26
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor1bin0 -> 11 bytes
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor10bin0 -> 345 bytes
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor2bin0 -> 38 bytes
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor3bin0 -> 597 bytes
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor4bin0 -> 48 bytes
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor5bin0 -> 31 bytes
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor6bin0 -> 21 bytes
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor7bin0 -> 18 bytes
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor8bin0 -> 353 bytes
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor9bin0 -> 188 bytes
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_encoding_json_fuzzer.cc20
-rw-r--r--chromium/content/browser/devtools/devtools_session.cc147
-rw-r--r--chromium/content/browser/devtools/devtools_session.h5
-rw-r--r--chromium/content/browser/devtools/devtools_session_encoding.cc72
-rw-r--r--chromium/content/browser/devtools/devtools_session_encoding.h25
-rw-r--r--chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc16
-rw-r--r--chromium/content/browser/devtools/devtools_url_interceptor_request_job.h4
-rw-r--r--chromium/content/browser/devtools/devtools_url_loader_interceptor.cc28
-rw-r--r--chromium/content/browser/devtools/devtools_video_consumer.cc2
-rw-r--r--chromium/content/browser/devtools/inspector_fuzzer.cc33
-rw-r--r--chromium/content/browser/devtools/protocol/background_service_handler.cc18
-rw-r--r--chromium/content/browser/devtools/protocol/background_service_handler.h6
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.cc6
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc15
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc2
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h2
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.cc24
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.cc39
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.h12
-rw-r--r--chromium/content/browser/devtools/protocol/service_worker_handler.cc7
-rw-r--r--chromium/content/browser/devtools/protocol/service_worker_handler.h1
-rw-r--r--chromium/content/browser/devtools/protocol/storage_handler.cc51
-rw-r--r--chromium/content/browser/devtools/protocol/system_info_handler.cc6
-rw-r--r--chromium/content/browser/devtools/protocol/target_auto_attacher.cc42
-rw-r--r--chromium/content/browser/devtools/protocol/target_auto_attacher.h1
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.cc8
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.h3
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.cc152
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.h4
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc2
-rw-r--r--chromium/content/browser/devtools/protocol/webauthn_handler.cc40
-rw-r--r--chromium/content/browser/devtools/protocol/webauthn_handler.h37
-rw-r--r--chromium/content/browser/devtools/protocol_config.json11
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.cc19
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.h11
-rw-r--r--chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc7
-rw-r--r--chromium/content/browser/dom_storage/session_storage_context_mojo_unittest.cc6
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl.cc4
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl.h4
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc4
-rw-r--r--chromium/content/browser/download/download_browsertest.cc115
-rw-r--r--chromium/content/browser/download/download_manager_impl.cc91
-rw-r--r--chromium/content/browser/download/download_manager_impl.h22
-rw-r--r--chromium/content/browser/download/download_manager_impl_unittest.cc15
-rw-r--r--chromium/content/browser/download/download_request_core.cc20
-rw-r--r--chromium/content/browser/download/mhtml_generation_browsertest.cc12
-rw-r--r--chromium/content/browser/download/save_file_manager.cc7
-rw-r--r--chromium/content/browser/download/save_types.h6
-rw-r--r--chromium/content/browser/download/url_downloader_factory.cc2
-rw-r--r--chromium/content/browser/download/url_downloader_factory.h1
-rw-r--r--chromium/content/browser/file_url_loader_factory.cc22
-rw-r--r--chromium/content/browser/fileapi/README.md4
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper.cc20
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper_unittest.cc3
-rw-r--r--chromium/content/browser/fileapi/file_system_manager_impl.cc51
-rw-r--r--chromium/content/browser/fileapi/file_system_manager_impl.h9
-rw-r--r--chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc2
-rw-r--r--chromium/content/browser/fileapi/file_system_url_loader_factory.cc17
-rw-r--r--chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc399
-rw-r--r--chromium/content/browser/find_request_manager.cc58
-rw-r--r--chromium/content/browser/font_unique_name_lookup/font_unique_name_browsertest.cc2
-rw-r--r--chromium/content/browser/frame_host/DEPS3
-rw-r--r--chromium/content/browser/frame_host/back_forward_cache_metrics_browsertest.cc40
-rw-r--r--chromium/content/browser/frame_host/back_forward_cache_metrics_unittest.cc5
-rw-r--r--chromium/content/browser/frame_host/blocked_scheme_navigation_browsertest.cc2
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.cc26
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.h4
-rw-r--r--chromium/content/browser/frame_host/debug_urls.cc8
-rw-r--r--chromium/content/browser/frame_host/frame_tree.cc9
-rw-r--r--chromium/content/browser/frame_host/frame_tree.h4
-rw-r--r--chromium/content/browser/frame_host/frame_tree_browsertest.cc69
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.cc6
-rw-r--r--chromium/content/browser/frame_host/frame_tree_unittest.cc4
-rw-r--r--chromium/content/browser/frame_host/input/OWNERS1
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.cc4
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.h4
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc4
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.cc12
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.h3
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.cc30
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.h32
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc37
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc394
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.cc10
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.h1
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.cc193
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.h66
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc2
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc2
-rw-r--r--chromium/content/browser/frame_host/navigation_request.cc422
-rw-r--r--chromium/content/browser/frame_host/navigation_request.h154
-rw-r--r--chromium/content/browser/frame_host/navigator.cc8
-rw-r--r--chromium/content/browser/frame_host/navigator.h14
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.cc64
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.h13
-rw-r--r--chromium/content/browser/frame_host/origin_policy_throttle.cc225
-rw-r--r--chromium/content/browser/frame_host/origin_policy_throttle.h64
-rw-r--r--chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc120
-rw-r--r--chromium/content/browser/frame_host/popup_menu_helper_mac.mm2
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.cc11
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.h19
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.cc988
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.h186
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc137
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.cc94
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.h37
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc307
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc91
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.cc137
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc24
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.cc45
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.h9
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.cc33
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.h11
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc46
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc4
-rw-r--r--chromium/content/browser/gpu/chromeos/delegate_to_browser_gpu_service_accelerator_factory.cc (renamed from chromium/content/browser/gpu/delegate_to_browser_gpu_service_accelerator_factory.cc)6
-rw-r--r--chromium/content/browser/gpu/chromeos/video_capture_dependencies.cc (renamed from chromium/content/browser/gpu/video_capture_dependencies.cc)14
-rw-r--r--chromium/content/browser/gpu/chromeos/video_capture_dependencies.h (renamed from chromium/content/browser/gpu/video_capture_dependencies.h)12
-rw-r--r--chromium/content/browser/gpu/compositor_util.cc23
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.cc11
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.h6
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.cc39
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.h6
-rw-r--r--chromium/content/browser/gpu/gpu_internals_ui.cc36
-rw-r--r--chromium/content/browser/gpu/gpu_ipc_browsertests.cc3
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc39
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.h6
-rw-r--r--chromium/content/browser/histograms_internals_ui.cc1
-rw-r--r--chromium/content/browser/idle/idle_browsertest.cc107
-rw-r--r--chromium/content/browser/idle/idle_manager.cc3
-rw-r--r--chromium/content/browser/idle/idle_manager.h4
-rw-r--r--chromium/content/browser/idle/idle_manager_unittest.cc43
-rw-r--r--chromium/content/browser/indexed_db/database_impl.cc52
-rw-r--r--chromium/content/browser/indexed_db/database_impl.h2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc11
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.cc111
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.h60
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc371
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_browsertest.cc26
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callback_helpers.h118
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.cc48
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.h4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_class_factory.cc22
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_class_factory.h18
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc8
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_connection.cc59
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_connection.h36
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.cc40
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.h21
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cursor.cc133
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cursor.h3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.cc610
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.h131
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_unittest.cc204
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory.h36
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.cc814
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.h130
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc1326
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc6
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h8
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.cc1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_origin_state.cc341
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_origin_state.h192
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_origin_state_handle.cc36
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_origin_state_handle.h53
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pending_connection.h2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.h2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction.cc84
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction.h20
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc98
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_unittest.cc4
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.h8
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.cc5
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.h6
-rw-r--r--chromium/content/browser/indexed_db/list_set.h5
-rw-r--r--chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc38
-rw-r--r--chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h9
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_callbacks.cc18
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h15
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc5
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h4
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_factory.cc4
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_factory.h21
-rw-r--r--chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h7
-rw-r--r--chromium/content/browser/indexed_db/ownership_graph.dot113
-rw-r--r--chromium/content/browser/indexed_db/scopes/README.md124
-rw-r--r--chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.cc109
-rw-r--r--chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.h13
-rw-r--r--chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager_unittest.cc126
-rw-r--r--chromium/content/browser/indexed_db/scopes/leveldb_scope.cc513
-rw-r--r--chromium/content/browser/indexed_db/scopes/leveldb_scope.h208
-rw-r--r--chromium/content/browser/indexed_db/scopes/leveldb_scope_deletion_mode.h26
-rw-r--r--chromium/content/browser/indexed_db/scopes/leveldb_scope_unittest.cc665
-rw-r--r--chromium/content/browser/indexed_db/scopes/leveldb_scopes.cc290
-rw-r--r--chromium/content/browser/indexed_db/scopes/leveldb_scopes.h133
-rw-r--r--chromium/content/browser/indexed_db/scopes/leveldb_scopes_factory.cc32
-rw-r--r--chromium/content/browser/indexed_db/scopes/leveldb_scopes_factory.h59
-rw-r--r--chromium/content/browser/indexed_db/scopes/leveldb_scopes_unittest.cc154
-rw-r--r--chromium/content/browser/indexed_db/scopes/scopes_lock_manager.cc3
-rw-r--r--chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h25
-rw-r--r--chromium/content/browser/indexed_db/transaction_impl.cc2
-rw-r--r--chromium/content/browser/isolated_origin_browsertest.cc144
-rw-r--r--chromium/content/browser/isolation_context.h4
-rw-r--r--chromium/content/browser/keyboard_lock_browsertest.cc4
-rw-r--r--chromium/content/browser/loader/cross_origin_read_blocking_checker.cc122
-rw-r--r--chromium/content/browser/loader/cross_origin_read_blocking_checker.h74
-rw-r--r--chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc266
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler.cc21
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc8
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.cc3
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.h1
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc11
-rw-r--r--chromium/content/browser/loader/navigation_loader_interceptor.cc2
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.cc6
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.h3
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.cc63
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.h3
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc8
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_unittest.cc45
-rw-r--r--chromium/content/browser/loader/prefetch_browsertest.cc246
-rw-r--r--chromium/content/browser/loader/prefetch_browsertest_base.cc154
-rw-r--r--chromium/content/browser/loader/prefetch_browsertest_base.h84
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader.cc84
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader.h26
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader_service.cc40
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader_service.h18
-rw-r--r--chromium/content/browser/loader/prefetched_signed_exchange_cache.cc571
-rw-r--r--chromium/content/browser/loader/prefetched_signed_exchange_cache.h123
-rw-r--r--chromium/content/browser/loader/prefetched_signed_exchange_cache_adapter.cc116
-rw-r--r--chromium/content/browser/loader/prefetched_signed_exchange_cache_adapter.h77
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc100
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h19
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc23
-rw-r--r--chromium/content/browser/loader/resource_loader.cc10
-rw-r--r--chromium/content/browser/loader/resource_loader.h1
-rw-r--r--chromium/content/browser/loader/resource_loader_unittest.cc33
-rw-r--r--chromium/content/browser/loader/resource_message_filter.cc3
-rw-r--r--chromium/content/browser/loader/resource_message_filter.h6
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc9
-rw-r--r--chromium/content/browser/loader/resource_requester_info.cc53
-rw-r--r--chromium/content/browser/loader/resource_requester_info.h23
-rw-r--r--chromium/content/browser/loader/sec_fetch_site_resource_handler.cc68
-rw-r--r--chromium/content/browser/loader/sec_fetch_site_resource_handler.h52
-rw-r--r--chromium/content/browser/loader/stream_writer.cc5
-rw-r--r--chromium/content/browser/loader/throttling_resource_handler_unittest.cc2
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl.cc1
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl_unittest.cc4
-rw-r--r--chromium/content/browser/log_console_message.cc5
-rw-r--r--chromium/content/browser/log_console_message.h3
-rw-r--r--chromium/content/browser/manifest/manifest_browsertest.cc7
-rw-r--r--chromium/content/browser/manifest/manifest_manager_host.h8
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker.cc44
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker.h16
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker_unittest.cc27
-rw-r--r--chromium/content/browser/media/audio_loopback_stream_broker.cc5
-rw-r--r--chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc21
-rw-r--r--chromium/content/browser/media/audio_muting_session.cc4
-rw-r--r--chromium/content/browser/media/audio_muting_session.h3
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker.cc33
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker.h12
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker_unittest.cc15
-rw-r--r--chromium/content/browser/media/capture/aura_window_video_capture_device_browsertest.cc16
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device.cc10
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_unittest.cc19
-rw-r--r--chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc3
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_muter.cc1
-rw-r--r--chromium/content/browser/media/flinging_renderer.cc17
-rw-r--r--chromium/content/browser/media/flinging_renderer.h11
-rw-r--r--chromium/content/browser/media/flinging_renderer_unittest.cc3
-rw-r--r--chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc42
-rw-r--r--chromium/content/browser/media/hardware_key_media_controller.cc9
-rw-r--r--chromium/content/browser/media/key_system_support_impl.cc8
-rw-r--r--chromium/content/browser/media/media_experiment_manager.cc89
-rw-r--r--chromium/content/browser/media/media_experiment_manager.h112
-rw-r--r--chromium/content/browser/media/media_experiment_manager_unittest.cc152
-rw-r--r--chromium/content/browser/media/media_interface_proxy.cc10
-rw-r--r--chromium/content/browser/media/media_interface_proxy.h6
-rw-r--r--chromium/content/browser/media/media_internals_ui.cc1
-rw-r--r--chromium/content/browser/media/media_keys_listener_manager_impl.cc14
-rw-r--r--chromium/content/browser/media/media_keys_listener_manager_impl.h8
-rw-r--r--chromium/content/browser/media/media_keys_listener_manager_impl_browsertest.cc14
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.cc2
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_android.cc4
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_android.h1
-rw-r--r--chromium/content/browser/media/session/media_session_browsertest.cc8
-rw-r--r--chromium/content/browser/media/session/media_session_impl.cc12
-rw-r--r--chromium/content/browser/media/session/media_session_impl_browsertest.cc11
-rw-r--r--chromium/content/browser/media/session/media_session_impl_unittest.cc6
-rw-r--r--chromium/content/browser/media/system_media_controls_notifier.cc167
-rw-r--r--chromium/content/browser/media/system_media_controls_notifier.h39
-rw-r--r--chromium/content/browser/media/system_media_controls_notifier_unittest.cc151
-rw-r--r--chromium/content/browser/media/url_provision_fetcher.cc29
-rw-r--r--chromium/content/browser/media/video_decoder_proxy.cc1
-rw-r--r--chromium/content/browser/media/video_decoder_proxy.h6
-rw-r--r--chromium/content/browser/native_file_system/OWNERS5
-rw-r--r--chromium/content/browser/native_file_system/README.md15
-rw-r--r--chromium/content/browser/native_file_system/file_system_chooser.cc (renamed from chromium/content/browser/fileapi/file_system_chooser.cc)74
-rw-r--r--chromium/content/browser/native_file_system/file_system_chooser.h (renamed from chromium/content/browser/fileapi/file_system_chooser.h)18
-rw-r--r--chromium/content/browser/native_file_system/file_system_chooser_browsertest.cc (renamed from chromium/content/browser/fileapi/file_system_chooser_browsertest.cc)8
-rw-r--r--chromium/content/browser/native_file_system/file_system_chooser_test_helpers.cc (renamed from chromium/content/browser/fileapi/file_system_chooser_test_helpers.cc)4
-rw-r--r--chromium/content/browser/native_file_system/file_system_chooser_test_helpers.h (renamed from chromium/content/browser/fileapi/file_system_chooser_test_helpers.h)8
-rw-r--r--chromium/content/browser/native_file_system/file_system_chooser_unittest.cc (renamed from chromium/content/browser/fileapi/file_system_chooser_unittest.cc)11
-rw-r--r--chromium/content/browser/native_file_system/native_file_system_directory_handle_impl.cc300
-rw-r--r--chromium/content/browser/native_file_system/native_file_system_directory_handle_impl.h98
-rw-r--r--chromium/content/browser/native_file_system/native_file_system_file_handle_impl.cc240
-rw-r--r--chromium/content/browser/native_file_system/native_file_system_file_handle_impl.h91
-rw-r--r--chromium/content/browser/native_file_system/native_file_system_file_handle_impl_unittest.cc294
-rw-r--r--chromium/content/browser/native_file_system/native_file_system_handle_base.cc26
-rw-r--r--chromium/content/browser/native_file_system/native_file_system_handle_base.h73
-rw-r--r--chromium/content/browser/native_file_system/native_file_system_manager_impl.cc299
-rw-r--r--chromium/content/browser/native_file_system/native_file_system_manager_impl.h191
-rw-r--r--chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.cc27
-rw-r--r--chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.h47
-rw-r--r--chromium/content/browser/navigation_browsertest.cc185
-rw-r--r--chromium/content/browser/navigation_subresource_loader_params.cc (renamed from chromium/content/common/navigation_subresource_loader_params.cc)3
-rw-r--r--chromium/content/browser/navigation_subresource_loader_params.h (renamed from chromium/content/common/navigation_subresource_loader_params.h)15
-rw-r--r--chromium/content/browser/net/accept_header_browsertest.cc9
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store.cc6
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store_unittest.cc2
-rw-r--r--chromium/content/browser/net/reporting_service_proxy.cc46
-rw-r--r--chromium/content/browser/network_service_browsertest.cc7
-rw-r--r--chromium/content/browser/network_service_client.cc339
-rw-r--r--chromium/content/browser/network_service_client.h27
-rw-r--r--chromium/content/browser/network_service_instance_impl.cc (renamed from chromium/content/browser/network_service_instance.cc)57
-rw-r--r--chromium/content/browser/network_service_instance_impl.h31
-rw-r--r--chromium/content/browser/network_service_restart_browsertest.cc1
-rw-r--r--chromium/content/browser/notifications/OWNERS1
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl.cc9
-rw-r--r--chromium/content/browser/notifications/devtools_event_logging.cc144
-rw-r--r--chromium/content/browser/notifications/devtools_event_logging.h47
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl.cc141
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_impl.cc96
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_impl.h5
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_trigger_unittest.cc2
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_unittest.cc112
-rw-r--r--chromium/content/browser/notifications/platform_notification_service_proxy.cc56
-rw-r--r--chromium/content/browser/notifications/platform_notification_service_proxy.h30
-rw-r--r--chromium/content/browser/ns_view_bridge_factory_host.mm51
-rw-r--r--chromium/content/browser/oop_browsertest.cc6
-rw-r--r--chromium/content/browser/origin_trials/OWNERS1
-rw-r--r--chromium/content/browser/origin_trials/origin_trials_browsertest.cc129
-rw-r--r--chromium/content/browser/payments/payment_app_info_fetcher.cc39
-rw-r--r--chromium/content/browser/payments/payment_instrument_icon_fetcher.cc26
-rw-r--r--chromium/content/browser/permissions/permission_controller_impl.cc60
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.cc3
-rw-r--r--chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc63
-rw-r--r--chromium/content/browser/picture_in_picture/overlay_surface_embedder.h47
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_service_impl.cc101
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_service_impl.h47
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc39
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_session.cc117
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_session.h92
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc83
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h28
-rw-r--r--chromium/content/browser/pointer_lock_browsertest.cc4
-rw-r--r--chromium/content/browser/portal/portal.cc113
-rw-r--r--chromium/content/browser/portal/portal.h35
-rw-r--r--chromium/content/browser/portal/portal_browsertest.cc117
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.cc29
-rw-r--r--chromium/content/browser/presentation/presentation_browsertest.cc53
-rw-r--r--chromium/content/browser/process_internals/process_internals_handler_impl.cc2
-rw-r--r--chromium/content/browser/process_internals/process_internals_ui.cc2
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_manager.cc285
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_manager.h36
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_router.cc99
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_router.h35
-rw-r--r--chromium/content/browser/renderer_host/DEPS8
-rw-r--r--chromium/content/browser/renderer_host/OWNERS1
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.mm3
-rw-r--r--chromium/content/browser/renderer_host/clipboard_host_impl.cc16
-rw-r--r--chromium/content/browser/renderer_host/clipboard_host_impl.h18
-rw-r--r--chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/code_cache_host_impl.cc15
-rw-r--r--chromium/content/browser/renderer_host/code_cache_host_impl.h7
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc149
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h18
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc56
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.cc20
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.h4
-rw-r--r--chromium/content/browser/renderer_host/direct_manipulation_helper_win.cc9
-rw-r--r--chromium/content/browser/renderer_host/direct_manipulation_win_browsertest.cc4
-rw-r--r--chromium/content/browser/renderer_host/direct_manipulation_win_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/display_util.cc1
-rw-r--r--chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc199
-rw-r--r--chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h66
-rw-r--r--chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win_unittest.cc42
-rw-r--r--chromium/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc10
-rw-r--r--chromium/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc59
-rw-r--r--chromium/content/browser/renderer_host/frame_connector_delegate.cc3
-rw-r--r--chromium/content/browser/renderer_host/frame_connector_delegate.h11
-rw-r--r--chromium/content/browser/renderer_host/input/OWNERS1
-rw-r--r--chromium/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/fling_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller.cc25
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller_unittest.cc18
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc6
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc26
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc113
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc58
-rw-r--r--chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc145
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.mm2
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h6
-rw-r--r--chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc8
-rw-r--r--chromium/content/browser/renderer_host/legacy_render_widget_host_win.h5
-rw-r--r--chromium/content/browser/renderer_host/media/OWNERS2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_delegate_impl.cc5
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_delegate_impl.h1
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc1
-rw-r--r--chromium/content/browser/renderer_host/media/audio_service_listener.cc9
-rw-r--r--chromium/content/browser/renderer_host/media/fake_video_capture_device_launcher.cc19
-rw-r--r--chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc6
-rw-r--r--chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc24
-rw-r--r--chromium/content/browser/renderer_host/media/in_process_video_capture_provider.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc11
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc40
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.h5
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc3
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory_unittest.cc1
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc14
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc14
-rw-r--r--chromium/content/browser/renderer_host/media/service_launched_video_capture_device.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.cc8
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider.cc44
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider.h10
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc16
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc81
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_provider_switcher.cc5
-rw-r--r--chromium/content/browser/renderer_host/overscroll_configuration.cc54
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.cc38
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc21
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font.h57
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc153
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.h72
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc158
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list.h36
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc113
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h28
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_mac.mm83
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_ozone.cc20
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_pango.cc65
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc91
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_mac.mm415
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_win.cc241
-rw-r--r--chromium/content/browser/renderer_host/plugin_registry_impl.cc8
-rw-r--r--chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.cc29
-rw-r--r--chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h12
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc129
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h3
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_unittest.cc256
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.cc5
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.cc6
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.h7
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_unittest.cc29
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.h6
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_factory.cc6
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_factory.h14
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc159
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h24
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc15
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc8
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc47
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc164
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h33
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc132
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h23
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc183
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc132
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h85
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc67
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h9
-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_event_handler.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h1
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.h29
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm69
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_browsertest.mm20
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm44
-rw-r--r--chromium/content/browser/renderer_host/render_widget_targeter.cc4
-rw-r--r--chromium/content/browser/renderer_interface_binders.cc40
-rw-r--r--chromium/content/browser/resources/.eslintrc.js (renamed from chromium/content/browser/resources/process/.eslintrc.js)7
-rw-r--r--chromium/content/browser/resources/appcache/appcache_internals.js144
-rw-r--r--chromium/content/browser/resources/gpu/browser_bridge.js10
-rw-r--r--chromium/content/browser/resources/gpu/browser_bridge_tests.js18
-rw-r--r--chromium/content/browser/resources/gpu/gpu_internals.js2
-rw-r--r--chromium/content/browser/resources/gpu/info_view.js95
-rw-r--r--chromium/content/browser/resources/indexed_db/indexeddb_internals.js28
-rw-r--r--chromium/content/browser/resources/media/.eslintrc.js10
-rw-r--r--chromium/content/browser/resources/media/peer_connection_update_table.js2
-rw-r--r--chromium/content/browser/resources/media/stats_graph_helper.js16
-rw-r--r--chromium/content/browser/resources/media/stats_rates_calculator.js33
-rw-r--r--chromium/content/browser/resources/media/webrtc_internals.css1
-rw-r--r--chromium/content/browser/resources/media/webrtc_internals.html4
-rw-r--r--chromium/content/browser/resources/net/network_errors_listing.js18
-rw-r--r--chromium/content/browser/resources/process/process_internals.html5
-rw-r--r--chromium/content/browser/resources/service_worker/serviceworker_internals.js60
-rw-r--r--chromium/content/browser/sandbox_mac_unittest.mm99
-rw-r--r--chromium/content/browser/sandbox_parameters_mac.h23
-rw-r--r--chromium/content/browser/sandbox_parameters_mac.mm37
-rw-r--r--chromium/content/browser/scheduler/browser_io_task_environment.cc57
-rw-r--r--chromium/content/browser/scheduler/browser_io_task_environment.h73
-rw-r--r--chromium/content/browser/scheduler/browser_io_task_environment_unittest.cc56
-rw-r--r--chromium/content/browser/scheduler/browser_task_executor.cc368
-rw-r--r--chromium/content/browser/scheduler/browser_task_executor.h87
-rw-r--r--chromium/content/browser/scheduler/browser_task_executor_unittest.cc156
-rw-r--r--chromium/content/browser/scheduler/browser_task_queues.cc274
-rw-r--r--chromium/content/browser/scheduler/browser_task_queues.h187
-rw-r--r--chromium/content/browser/scheduler/browser_task_queues_unittest.cc275
-rw-r--r--chromium/content/browser/scheduler/browser_ui_thread_scheduler.cc122
-rw-r--r--chromium/content/browser/scheduler/browser_ui_thread_scheduler.h53
-rw-r--r--chromium/content/browser/scheduler/browser_ui_thread_scheduler_unittest.cc150
-rw-r--r--chromium/content/browser/scheduler/browser_ui_thread_task_queue.cc42
-rw-r--r--chromium/content/browser/scheduler/browser_ui_thread_task_queue.h76
-rw-r--r--chromium/content/browser/scheduler/responsiveness/watcher.cc26
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc19
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_provider.cc3
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc72
-rw-r--r--chromium/content/browser/serial/serial_browsertest.cc24
-rw-r--r--chromium/content/browser/serial/serial_service.cc5
-rw-r--r--chromium/content/browser/serial/serial_test_utils.h1
-rw-r--r--chromium/content/browser/serial/serial_unittest.cc4
-rw-r--r--chromium/content/browser/service_manager/common_browser_interfaces.cc35
-rw-r--r--chromium/content/browser/service_manager/service_manager_context.cc561
-rw-r--r--chromium/content/browser/service_manager/service_manager_context.h12
-rw-r--r--chromium/content/browser/service_manager/service_manager_context_browsertest.cc2
-rw-r--r--chromium/content/browser/service_worker/README.md2
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.cc132
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.h9
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.cc50
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.h6
-rw-r--r--chromium/content/browser/service_worker/fake_embedded_worker_instance_client.cc10
-rw-r--r--chromium/content/browser/service_worker/fake_service_worker.cc7
-rw-r--r--chromium/content/browser/service_worker/fake_service_worker.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_browsertest.cc378
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_writer.cc11
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_writer.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_client_utils.cc4
-rw-r--r--chromium/content/browser/service_worker/service_worker_clients_api_browsertest.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.cc82
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core_unittest.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_unittest.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.cc1
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc8
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc88
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.cc15
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_database_unittest.cc58
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc4
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_script_loader.cc8
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc22
-rw-r--r--chromium/content/browser/service_worker/service_worker_internals_ui.cc1
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_unittest.cc20
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.cc32
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.h15
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader.cc58
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader_unittest.cc25
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager.cc23
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.cc78
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.h30
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.cc186
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.h26
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.cc127
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.h38
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_object_host.cc38
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_unittest.cc32
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.cc26
-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.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_cache_map.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_loader_factory.cc15
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc164
-rw-r--r--chromium/content/browser/service_worker/service_worker_single_script_update_checker.cc18
-rw-r--r--chromium/content/browser/service_worker/service_worker_single_script_update_checker.h12
-rw-r--r--chromium/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc233
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.cc89
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.h27
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage_unittest.cc110
-rw-r--r--chromium/content/browser/service_worker/service_worker_test_utils.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_tls_browsertest.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_update_checker.cc14
-rw-r--r--chromium/content/browser/service_worker/service_worker_update_checker.h15
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.cc44
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.h10
-rw-r--r--chromium/content/browser/service_worker/service_worker_version_unittest.cc25
-rw-r--r--chromium/content/browser/site_instance_impl.cc266
-rw-r--r--chromium/content/browser/site_instance_impl.h63
-rw-r--r--chromium/content/browser/site_instance_impl_unittest.cc90
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc192
-rw-r--r--chromium/content/browser/site_per_process_hit_test_browsertest.cc68
-rw-r--r--chromium/content/browser/site_per_process_unload_browsertest.cc496
-rw-r--r--chromium/content/browser/sms/OWNERS5
-rw-r--r--chromium/content/browser/sms/sms_browsertest.cc79
-rw-r--r--chromium/content/browser/sms/sms_manager_impl.cc73
-rw-r--r--chromium/content/browser/sms/sms_manager_impl.h54
-rw-r--r--chromium/content/browser/sms/sms_parser.cc38
-rw-r--r--chromium/content/browser/sms/sms_parser.h27
-rw-r--r--chromium/content/browser/sms/sms_parser_unittest.cc106
-rw-r--r--chromium/content/browser/sms/sms_provider.cc65
-rw-r--r--chromium/content/browser/sms/sms_provider.h57
-rw-r--r--chromium/content/browser/sms/sms_provider_android.cc54
-rw-r--r--chromium/content/browser/sms/sms_provider_android.h37
-rw-r--r--chromium/content/browser/sms/sms_provider_desktop.cc14
-rw-r--r--chromium/content/browser/sms/sms_provider_desktop.h21
-rw-r--r--chromium/content/browser/sms/sms_service_impl.cc41
-rw-r--r--chromium/content/browser/sms/sms_service_impl.h53
-rw-r--r--chromium/content/browser/sms/sms_service_impl_unittest.cc358
-rw-r--r--chromium/content/browser/speech/audio_encoder_fuzzer.cc43
-rw-r--r--chromium/content/browser/speech/mock_tts_controller.cc4
-rw-r--r--chromium/content/browser/speech/speech_recognition_engine.cc8
-rw-r--r--chromium/content/browser/speech/speech_recognition_engine_unittest.cc8
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.cc7
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_unittest.cc2
-rw-r--r--chromium/content/browser/speech/tts_android.cc35
-rw-r--r--chromium/content/browser/speech/tts_android.h14
-rw-r--r--chromium/content/browser/speech/tts_controller_impl.cc128
-rw-r--r--chromium/content/browser/speech/tts_controller_impl.h17
-rw-r--r--chromium/content/browser/speech/tts_controller_unittest.cc7
-rw-r--r--chromium/content/browser/speech/tts_linux.cc56
-rw-r--r--chromium/content/browser/speech/tts_mac.mm47
-rw-r--r--chromium/content/browser/speech/tts_platform_fuzzer.cc6
-rw-r--r--chromium/content/browser/speech/tts_ssml_browsertest.cc96
-rw-r--r--chromium/content/browser/speech/tts_win.cc71
-rw-r--r--chromium/content/browser/ssl/ssl_error_handler.cc7
-rw-r--r--chromium/content/browser/ssl/ssl_error_handler.h11
-rw-r--r--chromium/content/browser/ssl/ssl_manager.cc32
-rw-r--r--chromium/content/browser/ssl/ssl_manager.h7
-rw-r--r--chromium/content/browser/startup_data_impl.h5
-rw-r--r--chromium/content/browser/startup_helper.cc67
-rw-r--r--chromium/content/browser/storage_partition_impl.cc207
-rw-r--r--chromium/content/browser/storage_partition_impl.h28
-rw-r--r--chromium/content/browser/storage_partition_impl_map.cc18
-rw-r--r--chromium/content/browser/storage_partition_impl_unittest.cc51
-rw-r--r--chromium/content/browser/tracing/background_tracing_active_scenario.cc415
-rw-r--r--chromium/content/browser/tracing/background_tracing_active_scenario.h30
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_impl.cc4
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_impl.h2
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_unittest.cc2
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_browsertest.cc159
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.cc40
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.h10
-rw-r--r--chromium/content/browser/tracing/cast_tracing_agent.cc26
-rw-r--r--chromium/content/browser/tracing/cros_tracing_agent.cc37
-rw-r--r--chromium/content/browser/tracing/memory_tracing_browsertest.cc2
-rw-r--r--chromium/content/browser/tracing/perfetto_file_tracer.cc62
-rw-r--r--chromium/content/browser/tracing/perfetto_file_tracer.h12
-rw-r--r--chromium/content/browser/tracing/startup_tracing_browsertest.cc139
-rw-r--r--chromium/content/browser/tracing/tracing_controller_browsertest.cc6
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.cc4
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.h4
-rw-r--r--chromium/content/browser/tracing/tracing_ui.cc6
-rw-r--r--chromium/content/browser/url_loader_factory_getter.cc6
-rw-r--r--chromium/content/browser/utility_process_host.cc3
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_browsertest.cc401
-rw-r--r--chromium/content/browser/web_contents/DEPS6
-rw-r--r--chromium/content/browser/web_contents/aura/gesture_nav_simple.cc14
-rw-r--r--chromium/content/browser/web_contents/frame_tree_node_id_registry.cc45
-rw-r--r--chromium/content/browser/web_contents/frame_tree_node_id_registry.h63
-rw-r--r--chromium/content/browser/web_contents/javascript_dialog_navigation_deferrer.cc69
-rw-r--r--chromium/content/browser/web_contents/javascript_dialog_navigation_deferrer.h64
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.cc30
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.h26
-rw-r--r--chromium/content/browser/web_contents/web_contents_getter_registry.cc51
-rw-r--r--chromium/content/browser/web_contents/web_contents_getter_registry.h49
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc152
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h46
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_browsertest.cc11
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_unittest.cc84
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.cc371
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.h55
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc7
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc422
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_guest.cc10
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.h3
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.mm47
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac_unittest.mm2
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_mac.mm2
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm2
-rw-r--r--chromium/content/browser/web_contents_binding_set_browsertest.cc11
-rw-r--r--chromium/content/browser/web_package/mock_signed_exchange_handler.cc14
-rw-r--r--chromium/content/browser/web_package/mock_signed_exchange_handler.h21
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc30
-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_unittest.cc63
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain.cc73
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain.h42
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc35
-rw-r--r--chromium/content/browser/web_package/signed_exchange_envelope.cc13
-rw-r--r--chromium/content/browser/web_package/signed_exchange_envelope.h4
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler.cc20
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler.h8
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler_unittest.cc85
-rw-r--r--chromium/content/browser/web_package/signed_exchange_loader.cc126
-rw-r--r--chromium/content/browser/web_package/signed_exchange_loader.h13
-rw-r--r--chromium/content/browser/web_package/signed_exchange_loader_unittest.cc9
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc9
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prefetch_handler.h9
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc78
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_matcher.cc2
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier.cc61
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier.h26
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc124
-rw-r--r--chromium/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc1724
-rw-r--r--chromium/content/browser/web_package/signed_exchange_test_utils.h17
-rw-r--r--chromium/content/browser/web_package/signed_exchange_utils.cc57
-rw-r--r--chromium/content/browser/web_package/signed_exchange_utils.h16
-rw-r--r--chromium/content/browser/web_package/signed_exchange_validity_pinger.cc2
-rw-r--r--chromium/content/browser/web_package/signed_exchange_validity_pinger.h2
-rw-r--r--chromium/content/browser/webauth/DEPS8
-rw-r--r--chromium/content/browser/webauth/authenticator_common.cc226
-rw-r--r--chromium/content/browser/webauth/authenticator_common.h9
-rw-r--r--chromium/content/browser/webauth/authenticator_environment_impl.cc99
-rw-r--r--chromium/content/browser/webauth/authenticator_environment_impl.h87
-rw-r--r--chromium/content/browser/webauth/authenticator_impl.cc4
-rw-r--r--chromium/content/browser/webauth/authenticator_impl.h3
-rw-r--r--chromium/content/browser/webauth/authenticator_impl_unittest.cc985
-rw-r--r--chromium/content/browser/webauth/authenticator_type_converters.cc23
-rw-r--r--chromium/content/browser/webauth/authenticator_type_converters.h8
-rw-r--r--chromium/content/browser/webauth/virtual_authenticator.cc32
-rw-r--r--chromium/content/browser/webauth/virtual_authenticator.h17
-rw-r--r--chromium/content/browser/webauth/virtual_discovery.cc11
-rw-r--r--chromium/content/browser/webauth/virtual_discovery.h14
-rw-r--r--chromium/content/browser/webauth/virtual_fido_discovery_factory.cc (renamed from chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc)103
-rw-r--r--chromium/content/browser/webauth/virtual_fido_discovery_factory.h (renamed from chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h)58
-rw-r--r--chromium/content/browser/webauth/webauth_browsertest.cc382
-rw-r--r--chromium/content/browser/webkit_browsertest.cc4
-rw-r--r--chromium/content/browser/webrtc/OWNERS2
-rw-r--r--chromium/content/browser/webrtc/webrtc_audio_browsertest.cc53
-rw-r--r--chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc12
-rw-r--r--chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc5
-rw-r--r--chromium/content/browser/webrtc/webrtc_image_capture_browsertest.cc48
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals_ui.cc1
-rw-r--r--chromium/content/browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc190
-rw-r--r--chromium/content/browser/websockets/websocket_handshake_request_info_impl.cc6
-rw-r--r--chromium/content/browser/websockets/websocket_handshake_request_info_impl.h4
-rw-r--r--chromium/content/browser/websockets/websocket_manager.cc3
-rw-r--r--chromium/content/browser/webui/shared_resources_data_source.cc140
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend_unittest.cc20
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.cc41
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.h10
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_unittest.cc61
-rw-r--r--chromium/content/browser/webui/web_ui_mojo_browsertest.cc9
-rw-r--r--chromium/content/browser/worker_host/dedicated_worker_host.cc23
-rw-r--r--chromium/content/browser/worker_host/mock_shared_worker.cc5
-rw-r--r--chromium/content/browser/worker_host/mock_shared_worker.h5
-rw-r--r--chromium/content/browser/worker_host/shared_worker_connector_impl.cc2
-rw-r--r--chromium/content/browser/worker_host/shared_worker_host.cc8
-rw-r--r--chromium/content/browser/worker_host/shared_worker_host.h3
-rw-r--r--chromium/content/browser/worker_host/shared_worker_host_unittest.cc19
-rw-r--r--chromium/content/browser/worker_host/shared_worker_service_impl.cc14
-rw-r--r--chromium/content/browser/worker_host/shared_worker_service_impl.h12
-rw-r--r--chromium/content/browser/worker_host/shared_worker_service_impl_unittest.cc180
-rw-r--r--chromium/content/browser/worker_host/worker_browsertest.cc76
-rw-r--r--chromium/content/browser/worker_host/worker_script_fetch_initiator.cc37
-rw-r--r--chromium/content/browser/worker_host/worker_script_fetch_initiator.h9
-rw-r--r--chromium/content/browser/worker_host/worker_script_fetcher.cc9
-rw-r--r--chromium/content/browser/worker_host/worker_script_fetcher.h4
-rw-r--r--chromium/content/browser/worker_host/worker_script_loader.cc5
-rw-r--r--chromium/content/browser/worker_host/worker_script_loader.h4
-rw-r--r--chromium/content/browser/worker_host/worker_script_loader_factory.h2
-rw-r--r--chromium/content/browser/worker_host/worker_script_loader_factory_unittest.cc58
-rw-r--r--chromium/content/child/BUILD.gn12
-rw-r--r--chromium/content/child/blink_platform_impl.cc83
-rw-r--r--chromium/content/child/blink_platform_impl.h16
-rw-r--r--chromium/content/child/child_process.cc29
-rw-r--r--chromium/content/child/child_process.h6
-rw-r--r--chromium/content/child/child_process_sandbox_support_impl_mac.cc2
-rw-r--r--chromium/content/child/child_thread_impl.cc8
-rw-r--r--chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_impl_win.cc4
-rw-r--r--chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc4
-rw-r--r--chromium/content/child/font_warmup_win.cc2
-rw-r--r--chromium/content/child/font_warmup_win_unittest.cc24
-rw-r--r--chromium/content/child/runtime_features.cc109
-rw-r--r--chromium/content/child/webthemeengine_impl_android.cc8
-rw-r--r--chromium/content/child/webthemeengine_impl_android.h3
-rw-r--r--chromium/content/child/webthemeengine_impl_default.cc16
-rw-r--r--chromium/content/child/webthemeengine_impl_default.h3
-rw-r--r--chromium/content/child/webthemeengine_impl_mac.h4
-rw-r--r--chromium/content/common/BUILD.gn67
-rw-r--r--chromium/content/common/DEPS2
-rw-r--r--chromium/content/common/android/surface_wrapper.cc30
-rw-r--r--chromium/content/common/android/surface_wrapper.h27
-rw-r--r--chromium/content/common/bluetooth/OWNERS3
-rw-r--r--chromium/content/common/bluetooth/web_bluetooth_device_id.typemap3
-rw-r--r--chromium/content/common/bluetooth/web_bluetooth_device_id_struct_traits.h2
-rw-r--r--chromium/content/common/browser_plugin/browser_plugin_messages.h9
-rw-r--r--chromium/content/common/child_process_host_impl.cc31
-rw-r--r--chromium/content/common/common_param_traits_unittest.cc16
-rw-r--r--chromium/content/common/content_param_traits.cc98
-rw-r--r--chromium/content/common/content_param_traits.h34
-rw-r--r--chromium/content/common/content_param_traits_macros.h3
-rw-r--r--chromium/content/common/content_security_policy/csp_source_list_unittest.cc11
-rw-r--r--chromium/content/common/cursors/OWNERS1
-rw-r--r--chromium/content/common/cursors/webcursor.cc88
-rw-r--r--chromium/content/common/cursors/webcursor.h15
-rw-r--r--chromium/content/common/cursors/webcursor_aurawin.cc3
-rw-r--r--chromium/content/common/cursors/webcursor_mac.mm8
-rw-r--r--chromium/content/common/cursors/webcursor_ozone.cc4
-rw-r--r--chromium/content/common/cursors/webcursor_unittest.cc112
-rw-r--r--chromium/content/common/date_time_suggestion.h31
-rw-r--r--chromium/content/common/fetch/fetch_request_type_converters.cc1
-rw-r--r--chromium/content/common/font_list.h5
-rw-r--r--chromium/content/common/font_list_unittest.cc77
-rw-r--r--chromium/content/common/font_list_win.cc80
-rw-r--r--chromium/content/common/frame.mojom60
-rw-r--r--chromium/content/common/frame_message_structs.h4
-rw-r--r--chromium/content/common/frame_messages.h73
-rw-r--r--chromium/content/common/input/OWNERS1
-rw-r--r--chromium/content/common/input/input_handler.mojom2
-rw-r--r--chromium/content/common/input_messages.h7
-rw-r--r--chromium/content/common/manifest_observer.mojom11
-rw-r--r--chromium/content/common/media/media_player_delegate_messages.h4
-rw-r--r--chromium/content/common/mime_sniffing_url_loader.cc5
-rw-r--r--chromium/content/common/mime_sniffing_url_loader.h2
-rw-r--r--chromium/content/common/native_types.mojom2
-rw-r--r--chromium/content/common/native_types.typemap2
-rw-r--r--chromium/content/common/navigation_params.cc83
-rw-r--r--chromium/content/common/navigation_params.h103
-rw-r--r--chromium/content/common/navigation_params.mojom3
-rw-r--r--chromium/content/common/prefetched_signed_exchange_info.cc25
-rw-r--r--chromium/content/common/prefetched_signed_exchange_info.h40
-rw-r--r--chromium/content/common/push_messaging.mojom53
-rw-r--r--chromium/content/common/push_messaging.typemap23
-rw-r--r--chromium/content/common/push_messaging_param_traits.cc91
-rw-r--r--chromium/content/common/push_messaging_param_traits.h41
-rw-r--r--chromium/content/common/render_frame_metadata.mojom21
-rw-r--r--chromium/content/common/render_widget_window_tree_client_factory.mojom27
-rw-r--r--chromium/content/common/sandbox_init_mac.cc4
-rw-r--r--chromium/content/common/service_manager/OWNERS1
-rw-r--r--chromium/content/common/service_manager/child_connection.cc24
-rw-r--r--chromium/content/common/service_manager/service_manager_connection_impl.cc3
-rw-r--r--chromium/content/common/service_manager/service_manager_connection_impl_unittest.cc25
-rw-r--r--chromium/content/common/service_worker/service_worker_loader_helpers.cc4
-rw-r--r--chromium/content/common/service_worker/service_worker_types.h2
-rw-r--r--chromium/content/common/service_worker/service_worker_utils.cc36
-rw-r--r--chromium/content/common/service_worker/service_worker_utils.h31
-rw-r--r--chromium/content/common/swapped_out_messages.cc2
-rw-r--r--chromium/content/common/tab_switch_time_recorder.cc159
-rw-r--r--chromium/content/common/tab_switch_time_recorder.h65
-rw-r--r--chromium/content/common/tab_switch_time_recorder_unittest.cc356
-rw-r--r--chromium/content/common/text_input_state.cc1
-rw-r--r--chromium/content/common/text_input_state.h4
-rw-r--r--chromium/content/common/throttling_url_loader.cc86
-rw-r--r--chromium/content/common/throttling_url_loader.h2
-rw-r--r--chromium/content/common/throttling_url_loader_unittest.cc2
-rw-r--r--chromium/content/common/typemaps.gni1
-rw-r--r--chromium/content/common/user_agent.cc8
-rw-r--r--chromium/content/common/view_messages.h31
-rw-r--r--chromium/content/common/web_contents_ns_view_bridge.mojom (renamed from chromium/content/public/common/web_contents_ns_view_bridge.mojom)0
-rw-r--r--chromium/content/common/widget_messages.h17
-rw-r--r--chromium/content/content_resources.grd11
-rw-r--r--chromium/content/gpu/DEPS1
-rw-r--r--chromium/content/gpu/gpu_child_thread.cc4
-rw-r--r--chromium/content/gpu/gpu_main.cc32
-rw-r--r--chromium/content/gpu/gpu_sandbox_hook_linux.cc10
-rw-r--r--chromium/content/ppapi_plugin/ppapi_broker_main.cc4
-rw-r--r--chromium/content/ppapi_plugin/ppapi_plugin_main.cc4
-rw-r--r--chromium/content/ppapi_plugin/ppapi_thread.cc25
-rw-r--r--chromium/content/public/android/BUILD.gn10
-rw-r--r--chromium/content/public/android/junit/src/org/chromium/content/browser/BindingManagerTest.java55
-rw-r--r--chromium/content/public/android/junit/src/org/chromium/content/browser/ChildProcessRankingTest.java141
-rw-r--r--chromium/content/public/android/junit/src/org/chromium/content/browser/ScreenOrientationProviderImplTest.java108
-rw-r--r--chromium/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java15
-rw-r--r--chromium/content/public/android/junit/src/org/chromium/content/browser/input/ThreadedInputConnectionFactoryTest.java4
-rw-r--r--chromium/content/public/android/junit/src/org/chromium/content/browser/picker/DateDialogNormalizerTest.java3
-rw-r--r--chromium/content/public/app/BUILD.gn43
-rw-r--r--chromium/content/public/app/DEPS17
-rw-r--r--chromium/content/public/app/OWNERS5
-rw-r--r--chromium/content/public/app/content_browser_manifest.cc19
-rw-r--r--chromium/content/public/app/content_browser_manifest.h7
-rw-r--r--chromium/content/public/app/content_gpu_manifest.cc8
-rw-r--r--chromium/content/public/app/content_main.h5
-rw-r--r--chromium/content/public/app/content_main_delegate.h5
-rw-r--r--chromium/content/public/app/content_packaged_services_manifest.cc80
-rw-r--r--chromium/content/public/app/content_packaged_services_manifest.h26
-rw-r--r--chromium/content/public/app/content_plugin_manifest.cc10
-rw-r--r--chromium/content/public/app/content_renderer_manifest.cc6
-rw-r--r--chromium/content/public/app/content_utility_manifest.cc8
-rw-r--r--chromium/content/public/app/mac_helpers.gni54
-rw-r--r--chromium/content/public/browser/BUILD.gn19
-rw-r--r--chromium/content/public/browser/DEPS1
-rw-r--r--chromium/content/public/browser/android/compositor.h11
-rw-r--r--chromium/content/public/browser/android/synchronous_compositor.h3
-rw-r--r--chromium/content/public/browser/authenticator_environment.h35
-rw-r--r--chromium/content/public/browser/authenticator_request_client_delegate.h3
-rw-r--r--chromium/content/public/browser/background_sync_parameters.cc3
-rw-r--r--chromium/content/public/browser/background_sync_parameters.h10
-rw-r--r--chromium/content/public/browser/background_tracing_config.h2
-rw-r--r--chromium/content/public/browser/background_tracing_manager.h5
-rw-r--r--chromium/content/public/browser/bluetooth_scanning_prompt.cc13
-rw-r--r--chromium/content/public/browser/bluetooth_scanning_prompt.h53
-rw-r--r--chromium/content/public/browser/browser_accessibility_state.h2
-rw-r--r--chromium/content/public/browser/browser_context.h9
-rw-r--r--chromium/content/public/browser/browser_plugin_guest_delegate.cc5
-rw-r--r--chromium/content/public/browser/browser_plugin_guest_delegate.h4
-rw-r--r--chromium/content/public/browser/browser_thread.h19
-rw-r--r--chromium/content/public/browser/browsing_data_filter_builder.h20
-rw-r--r--chromium/content/public/browser/browsing_data_remover.h3
-rw-r--r--chromium/content/public/browser/browsing_data_remover_delegate.h17
-rw-r--r--chromium/content/public/browser/cache_storage_context.h2
-rw-r--r--chromium/content/public/browser/child_process_termination_info.h6
-rw-r--r--chromium/content/public/browser/chromeos/delegate_to_browser_gpu_service_accelerator_factory.h (renamed from chromium/content/public/browser/delegate_to_browser_gpu_service_accelerator_factory.h)9
-rw-r--r--chromium/content/public/browser/content_browser_client.cc78
-rw-r--r--chromium/content/public/browser/content_browser_client.h146
-rw-r--r--chromium/content/public/browser/cookie_store_factory.h6
-rw-r--r--chromium/content/public/browser/devtools_background_services_context.h60
-rw-r--r--chromium/content/public/browser/devtools_frontend_host.h3
-rw-r--r--chromium/content/public/browser/download_manager.h13
-rw-r--r--chromium/content/public/browser/download_manager_delegate.cc5
-rw-r--r--chromium/content/public/browser/download_manager_delegate.h4
-rw-r--r--chromium/content/public/browser/favicon_status.cc2
-rw-r--r--chromium/content/public/browser/gpu_data_manager.h8
-rw-r--r--chromium/content/public/browser/gpu_utils.cc27
-rw-r--r--chromium/content/public/browser/indexed_db_context.h5
-rw-r--r--chromium/content/public/browser/interstitial_page.h4
-rw-r--r--chromium/content/public/browser/navigation_data.h2
-rw-r--r--chromium/content/public/browser/navigation_handle.h7
-rw-r--r--chromium/content/public/browser/navigation_ui_data.h2
-rw-r--r--chromium/content/public/browser/network_service_instance.h12
-rw-r--r--chromium/content/public/browser/ns_view_bridge_factory_host.h44
-rw-r--r--chromium/content/public/browser/ns_view_bridge_factory_impl.h47
-rw-r--r--chromium/content/public/browser/overlay_window.h16
-rw-r--r--chromium/content/public/browser/overscroll_configuration.h22
-rw-r--r--chromium/content/public/browser/permission_controller_delegate.h9
-rw-r--r--chromium/content/public/browser/permission_type.h1
-rw-r--r--chromium/content/public/browser/picture_in_picture_window_controller.h2
-rw-r--r--chromium/content/public/browser/platform_notification_context.h6
-rw-r--r--chromium/content/public/browser/push_messaging_service.cc16
-rw-r--r--chromium/content/public/browser/push_messaging_service.h51
-rw-r--r--chromium/content/public/browser/remote_cocoa.h29
-rw-r--r--chromium/content/public/browser/render_frame_host.h13
-rw-r--r--chromium/content/public/browser/render_widget_host_view.h4
-rw-r--r--chromium/content/public/browser/resource_dispatcher_host.h4
-rw-r--r--chromium/content/public/browser/resource_throttle.h2
-rw-r--r--chromium/content/public/browser/serial_delegate.h6
-rw-r--r--chromium/content/public/browser/session_storage_namespace.h4
-rw-r--r--chromium/content/public/browser/site_instance.h9
-rw-r--r--chromium/content/public/browser/site_isolation_policy.cc21
-rw-r--r--chromium/content/public/browser/site_isolation_policy.h4
-rw-r--r--chromium/content/public/browser/site_isolation_policy_unittest.cc52
-rw-r--r--chromium/content/public/browser/sms_service.h32
-rw-r--r--chromium/content/public/browser/storage_partition.h3
-rw-r--r--chromium/content/public/browser/tts_controller.h4
-rw-r--r--chromium/content/public/browser/tts_platform.h5
-rw-r--r--chromium/content/public/browser/url_data_source.h4
-rw-r--r--chromium/content/public/browser/web_contents_binding_set.cc23
-rw-r--r--chromium/content/public/browser/web_contents_binding_set.h53
-rw-r--r--chromium/content/public/browser/web_contents_delegate.cc9
-rw-r--r--chromium/content/public/browser/web_contents_delegate.h18
-rw-r--r--chromium/content/public/browser/web_contents_observer.h3
-rw-r--r--chromium/content/public/browser/web_ui_data_source.h8
-rw-r--r--chromium/content/public/browser/websocket_handshake_request_info.h6
-rw-r--r--chromium/content/public/common/BUILD.gn16
-rw-r--r--chromium/content/public/common/DEPS3
-rw-r--r--chromium/content/public/common/child_process_host.h28
-rw-r--r--chromium/content/public/common/common_param_traits_macros.h4
-rw-r--r--chromium/content/public/common/content_client.cc4
-rw-r--r--chromium/content/public/common/content_client.h3
-rw-r--r--chromium/content/public/common/content_features.cc151
-rw-r--r--chromium/content/public/common/content_features.h26
-rw-r--r--chromium/content/public/common/content_switches.cc74
-rw-r--r--chromium/content/public/common/content_switches.h16
-rw-r--r--chromium/content/public/common/navigation_policy.cc78
-rw-r--r--chromium/content/public/common/navigation_policy.h73
-rw-r--r--chromium/content/public/common/ns_view_bridge_factory.mojom36
-rw-r--r--chromium/content/public/common/previews_state.h9
-rw-r--r--chromium/content/public/common/push_messaging_status.mojom244
-rw-r--r--chromium/content/public/common/push_subscription_options.h32
-rw-r--r--chromium/content/public/common/referrer.cc11
-rw-r--r--chromium/content/public/common/screen_info.cc3
-rw-r--r--chromium/content/public/common/screen_info.h4
-rw-r--r--chromium/content/public/common/service_names.mojom11
-rw-r--r--chromium/content/public/common/url_constants.cc2
-rw-r--r--chromium/content/public/common/url_loader_throttle.cc4
-rw-r--r--chromium/content/public/common/url_loader_throttle.h8
-rw-r--r--chromium/content/public/common/url_utils_unittest.cc5
-rw-r--r--chromium/content/public/common/user_agent.h22
-rw-r--r--chromium/content/public/common/web_preferences.cc4
-rw-r--r--chromium/content/public/common/web_preferences.h6
-rw-r--r--chromium/content/public/renderer/BUILD.gn1
-rw-r--r--chromium/content/public/renderer/associated_resource_fetcher.h8
-rw-r--r--chromium/content/public/renderer/content_renderer_client.cc17
-rw-r--r--chromium/content/public/renderer/content_renderer_client.h32
-rw-r--r--chromium/content/public/renderer/media_stream_utils.h36
-rw-r--r--chromium/content/public/renderer/render_frame.h2
-rw-r--r--chromium/content/public/renderer/render_frame_observer.h14
-rw-r--r--chromium/content/public/renderer/render_thread.h6
-rw-r--r--chromium/content/public/renderer/render_view.h4
-rw-r--r--chromium/content/public/renderer/render_view_observer.h10
-rw-r--r--chromium/content/public/renderer/resource_fetcher.h4
-rw-r--r--chromium/content/public/renderer/v8_value_converter.h10
-rw-r--r--chromium/content/public/utility/content_utility_client.h4
-rw-r--r--chromium/content/renderer/BUILD.gn59
-rw-r--r--chromium/content/renderer/DEPS1
-rw-r--r--chromium/content/renderer/accessibility/aom_content_ax_tree.cc18
-rw-r--r--chromium/content/renderer/accessibility/ax_image_annotator.cc11
-rw-r--r--chromium/content/renderer/accessibility/ax_image_annotator.h2
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc5
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_tree_source.cc52
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_tree_source.h19
-rw-r--r--chromium/content/renderer/accessibility/render_accessibility_impl.cc71
-rw-r--r--chromium/content/renderer/accessibility/render_accessibility_impl.h21
-rw-r--r--chromium/content/renderer/android/renderer_date_time_picker.cc116
-rw-r--r--chromium/content/renderer/android/renderer_date_time_picker.h45
-rw-r--r--chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc14
-rw-r--r--chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h2
-rw-r--r--chromium/content/renderer/appcache/OWNERS4
-rw-r--r--chromium/content/renderer/appcache/web_application_cache_host_impl.cc358
-rw-r--r--chromium/content/renderer/appcache/web_application_cache_host_impl.h85
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.cc81
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.h38
-rw-r--r--chromium/content/renderer/browser_render_view_browsertest.cc7
-rw-r--r--chromium/content/renderer/compositor/layer_tree_view.cc11
-rw-r--r--chromium/content/renderer/compositor/layer_tree_view.h6
-rw-r--r--chromium/content/renderer/dom_serializer_browsertest.cc44
-rw-r--r--chromium/content/renderer/dom_storage/dom_storage_cached_area.h2
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_cached_area.h2
-rw-r--r--chromium/content/renderer/fetchers/associated_resource_fetcher_impl.cc16
-rw-r--r--chromium/content/renderer/fetchers/associated_resource_fetcher_impl.h2
-rw-r--r--chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc15
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_browsertest.cc36
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_impl.cc13
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_impl.h2
-rw-r--r--chromium/content/renderer/frame_swap_message_queue.cc11
-rw-r--r--chromium/content/renderer/frame_swap_message_queue.h7
-rw-r--r--chromium/content/renderer/image_capture/DEPS4
-rw-r--r--chromium/content/renderer/image_capture/OWNERS7
-rw-r--r--chromium/content/renderer/image_capture/image_capture_frame_grabber.cc169
-rw-r--r--chromium/content/renderer/image_capture/image_capture_frame_grabber.h64
-rw-r--r--chromium/content/renderer/image_downloader/single_image_downloader.cc42
-rw-r--r--chromium/content/renderer/image_downloader/single_image_downloader.h43
-rw-r--r--chromium/content/renderer/input/frame_input_handler_impl.cc2
-rw-r--r--chromium/content/renderer/input/input_handler_manager_client.h87
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue.cc24
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue.h6
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue_unittest.cc10
-rw-r--r--chromium/content/renderer/input/render_widget_input_handler.cc166
-rw-r--r--chromium/content/renderer/input/render_widget_input_handler.h32
-rw-r--r--chromium/content/renderer/input/widget_input_handler_manager.cc12
-rw-r--r--chromium/content/renderer/installedapp/related_apps_fetcher.cc49
-rw-r--r--chromium/content/renderer/installedapp/related_apps_fetcher.h50
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_object.cc11
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_value_converter.cc3
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_value_converter.h3
-rw-r--r--chromium/content/renderer/loader/child_url_loader_factory_bundle.cc4
-rw-r--r--chromium/content/renderer/loader/code_cache_loader_impl.cc17
-rw-r--r--chromium/content/renderer/loader/code_cache_loader_impl.h7
-rw-r--r--chromium/content/renderer/loader/navigation_body_loader.cc17
-rw-r--r--chromium/content/renderer/loader/navigation_body_loader.h6
-rw-r--r--chromium/content/renderer/loader/request_extra_data.h7
-rw-r--r--chromium/content/renderer/loader/resource_dispatcher.cc13
-rw-r--r--chromium/content/renderer/loader/resource_dispatcher.h3
-rw-r--r--chromium/content/renderer/loader/resource_dispatcher_unittest.cc2
-rw-r--r--chromium/content/renderer/loader/url_loader_client_impl.cc18
-rw-r--r--chromium/content/renderer/loader/url_loader_client_impl.h2
-rw-r--r--chromium/content/renderer/loader/web_data_consumer_handle_impl.cc165
-rw-r--r--chromium/content/renderer/loader/web_data_consumer_handle_impl.h69
-rw-r--r--chromium/content/renderer/loader/web_data_consumer_handle_impl_unittest.cc423
-rw-r--r--chromium/content/renderer/loader/web_url_loader_impl.cc103
-rw-r--r--chromium/content/renderer/loader/web_url_loader_impl.h4
-rw-r--r--chromium/content/renderer/loader/web_url_loader_impl_unittest.cc1
-rw-r--r--chromium/content/renderer/loader/web_url_request_util.cc1
-rw-r--r--chromium/content/renderer/loader/web_url_request_util.h1
-rw-r--r--chromium/content/renderer/loader/web_worker_fetch_context_impl.cc3
-rw-r--r--chromium/content/renderer/loader/web_worker_fetch_context_impl.h5
-rw-r--r--chromium/content/renderer/manifest/OWNERS3
-rw-r--r--chromium/content/renderer/manifest/manifest_change_notifier.cc73
-rw-r--r--chromium/content/renderer/manifest/manifest_change_notifier.h37
-rw-r--r--chromium/content/renderer/manifest/manifest_manager.cc219
-rw-r--r--chromium/content/renderer/manifest/manifest_manager.h107
-rw-r--r--chromium/content/renderer/manifest/manifest_uma_util.cc85
-rw-r--r--chromium/content/renderer/manifest/manifest_uma_util.h40
-rw-r--r--chromium/content/renderer/media/OWNERS4
-rw-r--r--chromium/content/renderer/media/android/flinging_renderer_client.cc46
-rw-r--r--chromium/content/renderer/media/android/flinging_renderer_client.h66
-rw-r--r--chromium/content/renderer/media/android/flinging_renderer_client_factory.cc17
-rw-r--r--chromium/content/renderer/media/android/flinging_renderer_client_factory.h7
-rw-r--r--chromium/content/renderer/media/android/media_player_renderer_client.cc5
-rw-r--r--chromium/content/renderer/media/android/media_player_renderer_client_factory.h2
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory.cc2
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory.h4
-rw-r--r--chromium/content/renderer/media/android/stream_texture_wrapper_impl.cc10
-rw-r--r--chromium/content/renderer/media/android/stream_texture_wrapper_impl.h7
-rw-r--r--chromium/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc5
-rw-r--r--chromium/content/renderer/media/audio/mojo_audio_output_ipc.cc16
-rw-r--r--chromium/content/renderer/media/audio/mojo_audio_output_ipc.h1
-rw-r--r--chromium/content/renderer/media/audio/mojo_audio_output_ipc_unittest.cc1
-rw-r--r--chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc54
-rw-r--r--chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h7
-rw-r--r--chromium/content/renderer/media/media_factory.cc13
-rw-r--r--chromium/content/renderer/media/media_interface_factory.cc8
-rw-r--r--chromium/content/renderer/media/media_interface_factory.h6
-rw-r--r--chromium/content/renderer/media/media_permission_dispatcher.cc26
-rw-r--r--chromium/content/renderer/media/media_permission_dispatcher.h9
-rw-r--r--chromium/content/renderer/media/render_media_client.cc8
-rw-r--r--chromium/content/renderer/media/render_media_client.h4
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl.cc18
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl.h12
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc9
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate.h1
-rw-r--r--chromium/content/renderer/media/stream/apply_constraints_processor.cc3
-rw-r--r--chromium/content/renderer/media/stream/local_media_stream_audio_source.cc19
-rw-r--r--chromium/content/renderer/media/stream/local_media_stream_audio_source.h4
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_processor.cc103
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc49
-rw-r--r--chromium/content/renderer/media/stream/media_stream_center.cc15
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_audio.cc12
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h2
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc26
-rw-r--r--chromium/content/renderer/media/stream/media_stream_device_observer.cc2
-rw-r--r--chromium/content/renderer/media/stream/media_stream_device_observer_unittest.cc2
-rw-r--r--chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc3
-rw-r--r--chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.h1
-rw-r--r--chromium/content/renderer/media/stream/media_stream_video_renderer_sink.cc8
-rw-r--r--chromium/content/renderer/media/stream/media_stream_video_renderer_sink.h2
-rw-r--r--chromium/content/renderer/media/stream/media_stream_video_renderer_sink_unittest.cc5
-rw-r--r--chromium/content/renderer/media/stream/media_stream_video_source_unittest.cc28
-rw-r--r--chromium/content/renderer/media/stream/media_stream_video_track_unittest.cc31
-rw-r--r--chromium/content/renderer/media/stream/mock_constraint_factory.cc1
-rw-r--r--chromium/content/renderer/media/stream/mock_media_stream_video_sink.cc4
-rw-r--r--chromium/content/renderer/media/stream/mock_media_stream_video_sink.h4
-rw-r--r--chromium/content/renderer/media/stream/mock_media_stream_video_source.cc5
-rw-r--r--chromium/content/renderer/media/stream/mock_media_stream_video_source.h2
-rw-r--r--chromium/content/renderer/media/stream/processed_local_audio_source.cc6
-rw-r--r--chromium/content/renderer/media/stream/processed_local_audio_source.h4
-rw-r--r--chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc8
-rw-r--r--chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc14
-rw-r--r--chromium/content/renderer/media/stream/user_media_processor.cc40
-rw-r--r--chromium/content/renderer/media/stream/user_media_processor.h2
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms.cc92
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms.h14
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc106
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h28
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc82
-rw-r--r--chromium/content/renderer/media/video_capture/OWNERS1
-rw-r--r--chromium/content/renderer/media/video_capture/local_video_capturer_source.cc11
-rw-r--r--chromium/content/renderer/media/video_capture/local_video_capturer_source.h4
-rw-r--r--chromium/content/renderer/media/video_capture/video_capture_impl.cc16
-rw-r--r--chromium/content/renderer/media/video_capture/video_capture_impl.h10
-rw-r--r--chromium/content/renderer/media/video_capture/video_capture_impl_manager.cc26
-rw-r--r--chromium/content/renderer/media/video_capture/video_capture_impl_manager.h14
-rw-r--r--chromium/content/renderer/media/video_capture/video_capture_impl_manager_unittest.cc53
-rw-r--r--chromium/content/renderer/media/video_capture/video_capture_impl_unittest.cc2
-rw-r--r--chromium/content/renderer/media/webrtc/audio_codec_factory.cc8
-rw-r--r--chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc9
-rw-r--r--chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h4
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc26
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc6
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc13
-rw-r--r--chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h4
-rw-r--r--chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h3
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc31
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_tracker.cc43
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_tracker.h22
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc20
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h4
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc115
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc5
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h2
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc29
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_sender.h8
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_source.cc4
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_source.h1
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.cc9
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.h2
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_stats.cc5
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder.cc944
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder.h321
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc39
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.h4
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter_unittest.cc88
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder_factory.cc121
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder_factory.h1
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc483
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_encoder.cc79
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_encoder.h4
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc75
-rw-r--r--chromium/content/renderer/media/webrtc/track_observer.h4
-rw-r--r--chromium/content/renderer/media/webrtc/transmission_encoding_info_handler_unittest.cc1
-rw-r--r--chromium/content/renderer/media/webrtc/video_codec_factory.cc10
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc18
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc12
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc4
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc62
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.h9
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_track_source.cc35
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_track_source.h2
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_utils.h2
-rw-r--r--chromium/content/renderer/media_capture_from_element/OWNERS3
-rw-r--r--chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc507
-rw-r--r--chromium/content/renderer/media_capture_from_element/canvas_capture_handler.h132
-rw-r--r--chromium/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc249
-rw-r--r--chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc3
-rw-r--r--chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc9
-rw-r--r--chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc213
-rw-r--r--chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source.h98
-rw-r--r--chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc288
-rw-r--r--chromium/content/renderer/media_recorder/OWNERS3
-rw-r--r--chromium/content/renderer/media_recorder/media_recorder_handler.cc2
-rw-r--r--chromium/content/renderer/media_recorder/media_recorder_handler.h2
-rw-r--r--chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc4
-rw-r--r--chromium/content/renderer/media_recorder/vea_encoder.cc1
-rw-r--r--chromium/content/renderer/media_recorder/video_track_recorder.cc26
-rw-r--r--chromium/content/renderer/media_recorder/video_track_recorder.h16
-rw-r--r--chromium/content/renderer/media_recorder/video_track_recorder_unittest.cc8
-rw-r--r--chromium/content/renderer/media_recorder/vpx_encoder.cc13
-rw-r--r--chromium/content/renderer/media_recorder/vpx_encoder.h3
-rw-r--r--chromium/content/renderer/media_stream_utils.cc56
-rw-r--r--chromium/content/renderer/mus/BUILD.gn42
-rw-r--r--chromium/content/renderer/mus/OWNERS6
-rw-r--r--chromium/content/renderer/mus/mus_embedded_frame.cc123
-rw-r--r--chromium/content/renderer/mus/mus_embedded_frame.h88
-rw-r--r--chromium/content/renderer/mus/mus_embedded_frame_delegate.h26
-rw-r--r--chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc92
-rw-r--r--chromium/content/renderer/mus/render_widget_window_tree_client_factory.h17
-rw-r--r--chromium/content/renderer/mus/renderer_window_tree_client.cc392
-rw-r--r--chromium/content/renderer/mus/renderer_window_tree_client.h239
-rw-r--r--chromium/content/renderer/navigation_client.cc4
-rw-r--r--chromium/content/renderer/p2p/filtering_network_manager.cc6
-rw-r--r--chromium/content/renderer/p2p/filtering_network_manager_unittest.cc21
-rw-r--r--chromium/content/renderer/p2p/host_address_request.cc9
-rw-r--r--chromium/content/renderer/p2p/host_address_request.h5
-rw-r--r--chromium/content/renderer/p2p/ipc_socket_factory.cc6
-rw-r--r--chromium/content/renderer/pepper/host_array_buffer_var.cc41
-rw-r--r--chromium/content/renderer/pepper/host_array_buffer_var.h11
-rw-r--r--chromium/content/renderer/pepper/host_var_tracker.cc21
-rw-r--r--chromium/content/renderer/pepper/host_var_tracker.h12
-rw-r--r--chromium/content/renderer/pepper/message_channel.cc19
-rw-r--r--chromium/content/renderer/pepper/message_channel.h2
-rw-r--r--chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc33
-rw-r--r--chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h6
-rw-r--r--chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc4
-rw-r--r--chromium/content/renderer/pepper/pepper_file_chooser_host.cc9
-rw-r--r--chromium/content/renderer/pepper/pepper_graphics_2d_host.cc9
-rw-r--r--chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc7
-rw-r--r--chromium/content/renderer/pepper/pepper_in_process_resource_creation.h3
-rw-r--r--chromium/content/renderer/pepper/pepper_in_process_router.cc12
-rw-r--r--chromium/content/renderer/pepper/pepper_media_device_manager.cc18
-rw-r--r--chromium/content/renderer/pepper/pepper_media_device_manager.h12
-rw-r--r--chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc111
-rw-r--r--chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h2
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_input.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_camera_device.cc15
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_camera_device.h2
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_video_capture.cc33
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_video_capture.h6
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc22
-rw-r--r--chromium/content/renderer/pepper/pepper_video_capture_host.cc27
-rw-r--r--chromium/content/renderer/pepper/pepper_video_capture_host.h2
-rw-r--r--chromium/content/renderer/pepper/pepper_video_decoder_host.cc12
-rw-r--r--chromium/content/renderer/pepper/pepper_video_encoder_host.cc3
-rw-r--r--chromium/content/renderer/pepper/pepper_webplugin_impl.cc6
-rw-r--r--chromium/content/renderer/pepper/plugin_instance_throttler_impl.cc5
-rw-r--r--chromium/content/renderer/pepper/plugin_module.cc1
-rw-r--r--chromium/content/renderer/pepper/plugin_object.cc7
-rw-r--r--chromium/content/renderer/pepper/plugin_power_saver_helper.cc23
-rw-r--r--chromium/content/renderer/pepper/plugin_power_saver_helper.h10
-rw-r--r--chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc7
-rw-r--r--chromium/content/renderer/pepper/ppb_image_data_impl.cc66
-rw-r--r--chromium/content/renderer/pepper/ppb_image_data_impl.h26
-rw-r--r--chromium/content/renderer/pepper/ppb_video_decoder_impl.cc10
-rw-r--r--chromium/content/renderer/pepper/resource_converter.cc13
-rw-r--r--chromium/content/renderer/pepper/resource_converter.h4
-rw-r--r--chromium/content/renderer/pepper/v8_var_converter.cc4
-rw-r--r--chromium/content/renderer/pepper/v8_var_converter.h2
-rw-r--r--chromium/content/renderer/pepper/v8_var_converter_unittest.cc10
-rw-r--r--chromium/content/renderer/pepper/video_decoder_shim.cc47
-rw-r--r--chromium/content/renderer/pepper/video_decoder_shim.h2
-rw-r--r--chromium/content/renderer/pepper/video_encoder_shim.cc37
-rw-r--r--chromium/content/renderer/pepper/video_encoder_shim.h4
-rw-r--r--chromium/content/renderer/push_messaging/push_messaging_client.cc66
-rw-r--r--chromium/content/renderer/push_messaging/push_messaging_client.h24
-rw-r--r--chromium/content/renderer/push_messaging/push_messaging_utils.cc115
-rw-r--r--chromium/content/renderer/push_messaging/push_messaging_utils.h25
-rw-r--r--chromium/content/renderer/push_messaging/push_provider.cc290
-rw-r--r--chromium/content/renderer/push_messaging/push_provider.h99
-rw-r--r--chromium/content/renderer/queue_message_swap_promise.cc33
-rw-r--r--chromium/content/renderer/queue_message_swap_promise.h7
-rw-r--r--chromium/content/renderer/render_frame_impl.cc645
-rw-r--r--chromium/content/renderer/render_frame_impl.h108
-rw-r--r--chromium/content/renderer/render_frame_impl_browsertest.cc244
-rw-r--r--chromium/content/renderer/render_frame_metadata_observer_impl.cc35
-rw-r--r--chromium/content/renderer/render_frame_metadata_observer_impl.h21
-rw-r--r--chromium/content/renderer/render_frame_metadata_observer_impl_unittest.cc85
-rw-r--r--chromium/content/renderer/render_frame_proxy.cc82
-rw-r--r--chromium/content/renderer/render_frame_proxy.h34
-rw-r--r--chromium/content/renderer/render_process.cc3
-rw-r--r--chromium/content/renderer/render_process.h6
-rw-r--r--chromium/content/renderer/render_process_impl.cc74
-rw-r--r--chromium/content/renderer/render_process_impl.h4
-rw-r--r--chromium/content/renderer/render_thread_impl.cc110
-rw-r--r--chromium/content/renderer/render_thread_impl.h7
-rw-r--r--chromium/content/renderer/render_thread_impl_browsertest.cc13
-rw-r--r--chromium/content/renderer/render_thread_impl_discardable_memory_browsertest.cc2
-rw-r--r--chromium/content/renderer/render_view_browsertest.cc243
-rw-r--r--chromium/content/renderer/render_view_impl.cc79
-rw-r--r--chromium/content/renderer/render_view_impl.h33
-rw-r--r--chromium/content/renderer/render_view_win.cc2
-rw-r--r--chromium/content/renderer/render_widget.cc136
-rw-r--r--chromium/content/renderer/render_widget.h30
-rw-r--r--chromium/content/renderer/render_widget_unittest.cc1
-rw-r--r--chromium/content/renderer/renderer_blink_platform_impl.cc96
-rw-r--r--chromium/content/renderer/renderer_blink_platform_impl.h25
-rw-r--r--chromium/content/renderer/renderer_main.cc19
-rw-r--r--chromium/content/renderer/renderer_webapplicationcachehost_impl.cc72
-rw-r--r--chromium/content/renderer/renderer_webapplicationcachehost_impl.h42
-rw-r--r--chromium/content/renderer/savable_resources_browsertest.cc2
-rw-r--r--chromium/content/renderer/service_worker/controller_service_worker_impl.cc39
-rw-r--r--chromium/content/renderer/service_worker/controller_service_worker_impl.h68
-rw-r--r--chromium/content/renderer/service_worker/navigation_preload_request.cc10
-rw-r--r--chromium/content/renderer/service_worker/navigation_preload_request.h12
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.cc1272
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.h205
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client_unittest.cc667
-rw-r--r--chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc2
-rw-r--r--chromium/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc3
-rw-r--r--chromium/content/renderer/service_worker/service_worker_network_provider_for_service_worker.h5
-rw-r--r--chromium/content/renderer/service_worker/service_worker_provider_context.cc6
-rw-r--r--chromium/content/renderer/service_worker/service_worker_subresource_loader.cc44
-rw-r--r--chromium/content/renderer/service_worker/service_worker_subresource_loader.h2
-rw-r--r--chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc121
-rw-r--r--chromium/content/renderer/service_worker/service_worker_timeout_timer.cc217
-rw-r--r--chromium/content/renderer/service_worker/service_worker_timeout_timer.h200
-rw-r--r--chromium/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc419
-rw-r--r--chromium/content/renderer/service_worker/service_worker_type_converters.cc120
-rw-r--r--chromium/content/renderer/service_worker/service_worker_type_converters.h46
-rw-r--r--chromium/content/renderer/service_worker/service_worker_type_util.cc111
-rw-r--r--chromium/content/renderer/service_worker/service_worker_type_util.h28
-rw-r--r--chromium/content/renderer/v8_value_converter_impl.cc32
-rw-r--r--chromium/content/renderer/v8_value_converter_impl_unittest.cc12
-rw-r--r--chromium/content/renderer/visual_state_browsertest.cc22
-rw-r--r--chromium/content/renderer/web_ui_extension.cc6
-rw-r--r--chromium/content/renderer/webgraphicscontext3d_provider_impl.cc78
-rw-r--r--chromium/content/renderer/webgraphicscontext3d_provider_impl.h8
-rw-r--r--chromium/content/renderer/worker/application_cache_host_for_shared_worker.cc43
-rw-r--r--chromium/content/renderer/worker/application_cache_host_for_shared_worker.h45
-rw-r--r--chromium/content/renderer/worker/embedded_shared_worker_stub.cc24
-rw-r--r--chromium/content/renderer/worker/embedded_shared_worker_stub.h15
-rw-r--r--chromium/content/renderer/worker/service_worker_network_provider_for_worker.cc10
-rw-r--r--chromium/content/renderer/worker/service_worker_network_provider_for_worker.h7
-rw-r--r--chromium/content/renderer/worker/shared_worker_factory_impl.cc9
-rw-r--r--chromium/content/renderer/worker/shared_worker_factory_impl.h5
-rw-r--r--chromium/content/renderer/worker/worker_thread_registry.cc3
-rw-r--r--chromium/content/renderer/worker/worker_thread_registry.h2
-rw-r--r--chromium/content/shell/BUILD.gn140
-rw-r--r--chromium/content/shell/common/shell_content_client.cc4
-rw-r--r--chromium/content/shell/common/shell_content_client.h1
-rw-r--r--chromium/content/shell/common/web_test/fake_bluetooth_chooser.mojom32
-rw-r--r--chromium/content/shell/common/web_test/web_test_switches.cc11
-rw-r--r--chromium/content/shell/common/web_test/web_test_switches.h5
-rw-r--r--chromium/content/test/BUILD.gn66
-rw-r--r--chromium/content/test/fuzzer/BUILD.gn54
-rw-r--r--chromium/content/utility/BUILD.gn1
-rw-r--r--chromium/content/utility/utility_main.cc12
-rw-r--r--chromium/content/utility/utility_service_factory.cc10
-rw-r--r--chromium/content/utility/utility_service_factory.h5
1711 files changed, 48716 insertions, 34019 deletions
diff --git a/chromium/content/BUILD.gn b/chromium/content/BUILD.gn
index 594b6d433bb..ee7f2d15daa 100644
--- a/chromium/content/BUILD.gn
+++ b/chromium/content/BUILD.gn
@@ -116,6 +116,8 @@ grit("resources") {
outputs = [
"grit/content_resources.h",
+ "grit/content_resources_map.cc",
+ "grit/content_resources_map.h",
"content_resources.pak",
]
grit_flags = [
@@ -124,6 +126,7 @@ grit("resources") {
]
deps = [
"//content/browser/process_internals:mojo_bindings_js",
+ "//url/mojom:url_mojom_origin_js",
]
}
diff --git a/chromium/content/OWNERS b/chromium/content/OWNERS
index 906c4602a6d..249bacb5ff4 100644
--- a/chromium/content/OWNERS
+++ b/chromium/content/OWNERS
@@ -2,7 +2,6 @@ alexmos@chromium.org
avi@chromium.org
clamy@chromium.org
creis@chromium.org
-darin@chromium.org
dgozman@chromium.org
jam@chromium.org
jochen@chromium.org
diff --git a/chromium/content/app/BUILD.gn b/chromium/content/app/BUILD.gn
index 75a7d9534c6..0cd3c07e6ec 100644
--- a/chromium/content/app/BUILD.gn
+++ b/chromium/content/app/BUILD.gn
@@ -51,7 +51,6 @@ template("implement_content_app") {
"//content/public/android:jni",
"//device/bluetooth",
"//device/gamepad",
- "//device/usb",
"//gpu",
"//media",
"//media/capture",
diff --git a/chromium/content/app/DEPS b/chromium/content/app/DEPS
index dfe3826de62..bd97c0a531f 100644
--- a/chromium/content/app/DEPS
+++ b/chromium/content/app/DEPS
@@ -3,7 +3,6 @@ include_rules = [
"+content",
"+device/bluetooth",
"+device/gamepad",
- "+device/usb",
# For loading V8's initial snapshot from external files.
"+gin/public/isolate_holder.h",
"+gin/public/snapshot_fd_data.h",
diff --git a/chromium/content/app/android/content_child_process_service_delegate.cc b/chromium/content/app/android/content_child_process_service_delegate.cc
index f1488cfa935..cbed8cf7d33 100644
--- a/chromium/content/app/android/content_child_process_service_delegate.cc
+++ b/chromium/content/app/android/content_child_process_service_delegate.cc
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/unguessable_token.h"
#include "content/child/child_thread_impl.h"
+#include "content/common/android/surface_wrapper.h"
#include "content/public/common/content_descriptors.h"
#include "content/public/common/content_switches.h"
#include "gpu/ipc/common/android/scoped_surface_request_conduit.h"
@@ -59,14 +60,19 @@ class ChildProcessSurfaceManager : public gpu::ScopedSurfaceRequestConduit,
}
// Overridden from GpuSurfaceLookup:
- gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) override {
+ gfx::AcceleratedWidget AcquireNativeWidget(
+ int surface_id,
+ bool* can_be_used_with_surface_control) override {
JNIEnv* env = base::android::AttachCurrentThread();
- gl::ScopedJavaSurface surface(
+ base::android::ScopedJavaLocalRef<jobject> surface_wrapper =
content::Java_ContentChildProcessServiceDelegate_getViewSurface(
- env, service_impl_, surface_id));
+ env, service_impl_, surface_id);
+ if (!surface_wrapper)
+ return gfx::kNullAcceleratedWidget;
- if (surface.j_surface().is_null())
- return NULL;
+ gl::ScopedJavaSurface surface(
+ content::JNI_SurfaceWrapper_getSurface(env, surface_wrapper));
+ DCHECK(!surface.j_surface().is_null());
// Note: This ensures that any local references used by
// ANativeWindow_fromSurface are released immediately. This is needed as a
@@ -75,15 +81,31 @@ class ChildProcessSurfaceManager : public gpu::ScopedSurfaceRequestConduit,
ANativeWindow* native_window =
ANativeWindow_fromSurface(env, surface.j_surface().obj());
+ *can_be_used_with_surface_control =
+ content::JNI_SurfaceWrapper_canBeUsedWithSurfaceControl(
+ env, surface_wrapper);
return native_window;
}
// Overridden from GpuSurfaceLookup:
- gl::ScopedJavaSurface AcquireJavaSurface(int surface_id) override {
+ gl::ScopedJavaSurface AcquireJavaSurface(
+ int surface_id,
+ bool* can_be_used_with_surface_control) override {
JNIEnv* env = base::android::AttachCurrentThread();
- return gl::ScopedJavaSurface(
+ base::android::ScopedJavaLocalRef<jobject> surface_wrapper =
content::Java_ContentChildProcessServiceDelegate_getViewSurface(
- env, service_impl_, surface_id));
+ env, service_impl_, surface_id);
+ if (!surface_wrapper)
+ return gl::ScopedJavaSurface();
+
+ gl::ScopedJavaSurface surface(
+ content::JNI_SurfaceWrapper_getSurface(env, surface_wrapper));
+ DCHECK(!surface.j_surface().is_null());
+
+ *can_be_used_with_surface_control =
+ content::JNI_SurfaceWrapper_canBeUsedWithSurfaceControl(
+ env, surface_wrapper);
+ return surface;
}
private:
diff --git a/chromium/content/app/android/content_main.cc b/chromium/content/app/android/content_main.cc
index bb61be3e6d7..2a9c9002ef7 100644
--- a/chromium/content/app/android/content_main.cc
+++ b/chromium/content/app/android/content_main.cc
@@ -57,4 +57,9 @@ void SetContentMainDelegate(ContentMainDelegate* delegate) {
g_content_main_delegate.Get().reset(delegate);
}
+ContentMainDelegate* GetContentMainDelegateForTesting() {
+ DCHECK(g_content_main_delegate.Get().get());
+ return g_content_main_delegate.Get().get();
+}
+
} // namespace content
diff --git a/chromium/content/app/android/library_loader_hooks.cc b/chromium/content/app/android/library_loader_hooks.cc
index 393a41c1a8a..dd6a687b7e7 100644
--- a/chromium/content/app/android/library_loader_hooks.cc
+++ b/chromium/content/app/android/library_loader_hooks.cc
@@ -40,7 +40,8 @@ bool LibraryLoaded(JNIEnv* env,
TRACE_EVENT0("jni", "JNI_OnLoad continuation");
logging::LoggingSettings settings;
- settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
+ settings.logging_dest =
+ logging::LOG_TO_SYSTEM_DEBUG_LOG | logging::LOG_TO_STDERR;
logging::InitLogging(settings);
// To view log output with IDs and timestamps use "adb logcat -v threadtime".
logging::SetLogItems(false, // Process ID
diff --git a/chromium/content/app/content_main_runner_impl.cc b/chromium/content/app/content_main_runner_impl.cc
index 4dc87d822f1..a388e279e9e 100644
--- a/chromium/content/app/content_main_runner_impl.cc
+++ b/chromium/content/app/content_main_runner_impl.cc
@@ -32,6 +32,8 @@
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_base.h"
#include "base/path_service.h"
+#include "base/power_monitor/power_monitor.h"
+#include "base/power_monitor/power_monitor_device_source.h"
#include "base/process/launch.h"
#include "base/process/memory.h"
#include "base/process/process.h"
@@ -86,6 +88,7 @@
#elif defined(OS_MACOSX)
#include "base/mac/mach_port_broker.h"
#include "base/power_monitor/power_monitor_device_source.h"
+#include "sandbox/mac/seatbelt.h"
#include "sandbox/mac/seatbelt_exec.h"
#endif // OS_WIN
@@ -543,17 +546,9 @@ static void RegisterMainThreadFactories() {
int RunBrowserProcessMain(const MainFunctionParams& main_function_params,
ContentMainDelegate* delegate) {
int exit_code = delegate->RunProcess("", main_function_params);
-#if defined(OS_ANDROID)
- // In Android's browser process, the negative exit code doesn't mean the
- // default behavior should be used as the UI message loop is managed by
- // the Java and the browser process's default behavior is always
- // overridden.
- return exit_code;
-#else
if (exit_code >= 0)
return exit_code;
return BrowserMain(main_function_params);
-#endif
}
#endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
@@ -812,19 +807,16 @@ int ContentMainRunnerImpl::Initialize(const ContentMainParams& params) {
params.sandbox_info))
return TerminateForFatalInitializationError();
#elif defined(OS_MACOSX)
- // Do not initialize the sandbox at this point if the V2
- // sandbox is enabled for the process type.
+ // Only the GPU process still runs the V1 sandbox.
bool v2_enabled = base::CommandLine::ForCurrentProcess()->HasSwitch(
sandbox::switches::kSeatbeltClientName);
- if (process_type == switches::kRendererProcess ||
- process_type == switches::kPpapiPluginProcess || v2_enabled ||
- delegate_->DelaySandboxInitialization(process_type)) {
- // On OS X the renderer sandbox needs to be initialized later in the
- // startup sequence in RendererMainPlatformDelegate::EnableSandbox().
- } else {
- if (!InitializeSandbox())
+ if (!v2_enabled && process_type == switches::kGpuProcess) {
+ if (!InitializeSandbox()) {
return TerminateForFatalInitializationError();
+ }
+ } else if (v2_enabled) {
+ CHECK(sandbox::Seatbelt::IsSandboxed());
}
#endif
@@ -898,7 +890,7 @@ int ContentMainRunnerImpl::RunServiceManager(MainFunctionParams& main_params,
if (GetContentClient()->browser()->ShouldCreateThreadPool()) {
// Create and start the ThreadPool early to allow upcoming code to use
// the post_task.h API.
- base::ThreadPool::Create("Browser");
+ base::ThreadPoolInstance::Create("Browser");
}
delegate_->PreCreateMainMessageLoop();
@@ -926,6 +918,8 @@ int ContentMainRunnerImpl::RunServiceManager(MainFunctionParams& main_params,
BrowserTaskExecutor::PostFeatureListSetup();
+ delegate_->PostTaskSchedulerStart();
+
if (!base::FeatureList::IsEnabled(
features::kAllowStartingServiceManagerOnly)) {
should_start_service_manager_only = false;
@@ -957,9 +951,14 @@ int ContentMainRunnerImpl::RunServiceManager(MainFunctionParams& main_params,
}
}
+ // PowerMonitor is needed in reduced mode but is eventually passed on to
+ // BrowserMainLoop.
+ power_monitor_ = std::make_unique<base::PowerMonitor>(
+ std::make_unique<base::PowerMonitorDeviceSource>());
+
// The thread used to start the ServiceManager is handed-off to
// BrowserMain() which may elect to promote it (e.g. to BrowserThread::IO).
- service_manager_thread_ = BrowserProcessSubThread::CreateIOThread();
+ service_manager_thread_ = BrowserTaskExecutor::CreateIOThread();
service_manager_context_.reset(
new ServiceManagerContext(service_manager_thread_->task_runner()));
download::SetIOTaskRunner(service_manager_thread_->task_runner());
@@ -978,6 +977,7 @@ int ContentMainRunnerImpl::RunServiceManager(MainFunctionParams& main_params,
startup_data_ = std::make_unique<StartupDataImpl>();
startup_data_->thread = std::move(service_manager_thread_);
startup_data_->service_manager_context = service_manager_context_.get();
+ startup_data_->power_monitor = std::move(power_monitor_);
main_params.startup_data = startup_data_.get();
return RunBrowserProcessMain(main_params, delegate_);
}
diff --git a/chromium/content/app/content_main_runner_impl.h b/chromium/content/app/content_main_runner_impl.h
index 1e5a57b4a5c..e977ff4be71 100644
--- a/chromium/content/app/content_main_runner_impl.h
+++ b/chromium/content/app/content_main_runner_impl.h
@@ -10,6 +10,7 @@
#include "base/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/field_trial.h"
+#include "base/power_monitor/power_monitor.h"
#include "build/build_config.h"
#include "content/browser/service_manager/service_manager_context.h"
#include "content/browser/startup_data_impl.h"
@@ -57,6 +58,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
std::unique_ptr<base::FieldTrialList> field_trial_list_;
std::unique_ptr<BrowserProcessSubThread> service_manager_thread_;
std::unique_ptr<ServiceManagerContext> service_manager_context_;
+ std::unique_ptr<base::PowerMonitor> power_monitor_;
#endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
// True if the runner has been initialized.
diff --git a/chromium/content/app/strings/content_strings.grd b/chromium/content/app/strings/content_strings.grd
index 438d92fd0b1..17a63d9cd4a 100644
--- a/chromium/content/app/strings/content_strings.grd
+++ b/chromium/content/app/strings/content_strings.grd
@@ -929,6 +929,9 @@ below:
Please lengthen this text to <ph name="MIN_CHARACTERS">$2<ex>101</ex></ph> characters or more (you are currently using <ph name="CURRENT_LENGTH">$1<ex>100</ex></ph> characters).
</message>
+ <message name="IDS_MEDIA_SESSION_FILE_SOURCE" desc="The name of the media session source if the media is a local file.">
+ Local File
+ </message>
<message name="IDS_MEDIA_OVERFLOW_MENU_CLOSED_CAPTIONS" desc="Media controls overflow menu item label for a closed captions button. The text for this overflow menu should be short.">
Captions
</message>
@@ -960,7 +963,7 @@ below:
Download
</message>
<if expr="is_macosx">
- <message name="IDS_MEDIA_OVERFLOW_MENU_ENTER_PICTURE_IN_PICTURE" desc="Media contr ls overflow menu item label for a button to enter Picture-in-Picture.">
+ <message name="IDS_MEDIA_OVERFLOW_MENU_ENTER_PICTURE_IN_PICTURE" desc="Media controls overflow menu item label for a button to enter Picture-in-Picture.">
Picture in Picture
</message>
</if>
@@ -969,11 +972,18 @@ below:
Picture in picture
</message>
</if>
- <message name="IDS_MEDIA_OVERFLOW_MENU_EXIT_PICTURE_IN_PICTURE" desc="Media controls overflow menu item label for a button to exit Picture-in-Picture.">
- Exit picture-in-picture mode
- </message>
+ <if expr="is_macosx">
+ <message name="IDS_MEDIA_OVERFLOW_MENU_EXIT_PICTURE_IN_PICTURE" desc="Media controls overflow menu item label for a button to exit Picture-in-Picture.">
+ Exit Picture-in-Picture
+ </message>
+ </if>
+ <if expr="not is_macosx">
+ <message name="IDS_MEDIA_OVERFLOW_MENU_EXIT_PICTURE_IN_PICTURE" desc="Media controls overflow menu item label for a button to exit Picture-in-Picture.">
+ Exit picture-in-picture
+ </message>
+ </if>
<message name="IDS_MEDIA_PICTURE_IN_PICTURE_INTERSTITIAL_TEXT" desc="Text message shown to user when in picture in picture mode. When a video is in picture in picture mode, an interstitial with this text appears where the video player is positioned. The video continues to play back in another window that gives the experience that the video is 'popped out'.">
- Playing in picture-in-picture mode
+ Playing in picture-in-picture
</message>
<message name="IDS_MEDIA_REMOTING_CAST_TEXT" desc="Text message shown to the user when casting a video to a known remote device.">
Now casting to <ph name="DEVICE_FRIENDLY_NAME">$1<ex>Living Room TV</ex></ph>
diff --git a/chromium/content/app/strings/content_strings_grd/IDS_MEDIA_SESSION_FILE_SOURCE.png.sha1 b/chromium/content/app/strings/content_strings_grd/IDS_MEDIA_SESSION_FILE_SOURCE.png.sha1
new file mode 100644
index 00000000000..7ae1cf665af
--- /dev/null
+++ b/chromium/content/app/strings/content_strings_grd/IDS_MEDIA_SESSION_FILE_SOURCE.png.sha1
@@ -0,0 +1 @@
+53ecf240f59804dfdb53d40001e317cee9284305 \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_am.xtb b/chromium/content/app/strings/translations/content_strings_am.xtb
index 725bb66c9e0..71b12d946de 100644
--- a/chromium/content/app/strings/translations/content_strings_am.xtb
+++ b/chromium/content/app/strings/translations/content_strings_am.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">ተንሸራታች</translation>
<translation id="1211441953136645838">የግርጌ ማስታወሻ</translation>
<translation id="1281252709823657822">መገናኛ</translation>
-<translation id="1289247557029249093">ከሥዕል-ውስጥ-ሥዕል ሁነታ ውጣ</translation>
<translation id="1335095011850992622">ክሬዲቶች</translation>
<translation id="1342835525016946179">ጽሑፍ</translation>
<translation id="1359897965706325498">ሰንደቅ</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">ዛሬ</translation>
<translation id="2158401438286456825">የገጽ ዝርዝር</translation>
<translation id="2226276347425096477">እባክዎ ይህ ጽሑፍ ወደ <ph name="MAX_CHARACTERS" /> ወይም ከዚያ በታች ቁምፊዎች ያሳጥሩት (በአሁኑ ጊዜ <ph name="CURRENT_LENGTH" /> ቁምፊዎችን እየተጠቀሙ ነዎት)።</translation>
+<translation id="2246498165605549352">አካባቢያዊ ፋይል</translation>
<translation id="2247351761944213033">ሳምንት <ph name="WEEKNUMBER" />፣ <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ትራክ <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">አመልካች ሳጥን</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">መሰየሚያ ያልተሰጠው ምስል</translation>
<translation id="3706100364254443312">ቀይር</translation>
<translation id="3732799496749320381">ሚሜ</translation>
+<translation id="3754210790023674521">ከሥዕል-ውስጥ-ሥዕል ውጣ</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> ጊባ</translation>
<translation id="3808586225841795776">የጊዜ ቆይታ</translation>
<translation id="3822383571486410024">እባክዎ ይህን ጽሑፍ ወደ <ph name="MIN_CHARACTERS" /> ቁምፊዎች ወይም ከዚያ በላይ ያራዝሙት (አሁን እየተጠቀሙ ያሉት <ph name="CURRENT_LENGTH" />ቁምፊዎችን ነው)።</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">ዛፍ</translation>
<translation id="4664250907885839816">ከ«<ph name="ATSIGN" />» በኋላ የሚመጣ ክፍል የ«<ph name="INVALIDCHARACTER" />» ምልክት መያዝ የለበትም።</translation>
<translation id="4668956016107839909">ቅጥያዎች</translation>
+<translation id="4718048029184481307">በሥዕል-ውስጥ-ሥዕልን በማጫወት ላይ</translation>
<translation id="4742539557769756338">ሽፋን</translation>
<translation id="4748357248530471599">የተቆረጠው የማሳያ ክፍል ሙሉ ማያ ገጽን ይቀያይሩ</translation>
<translation id="4757246831282535685">የትር ፓነል</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">ድሕረ ቃል</translation>
<translation id="6209276755895393898">ይህ ይመስላል፦ <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">ሙዳየ ቃላት</translation>
-<translation id="628938136236500310">በስዕል-ውስጥ-ስዕል ሁነታ ላይ በማጫወት ላይ</translation>
+<translation id="6310801910862476708">ከስዕል-ውስጥ-ስዕል ውጣ</translation>
<translation id="6398862346408813489">የወር መምረጫ ፓነል አሳይ</translation>
<translation id="6404546809543547843">የኦዲዮ ሰዓት አንፏቃቂ</translation>
<translation id="6443871981718447451">የተዘጉ የመግለጫ ጽሁፎችን ምናሌ አሳይ</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ar.xtb b/chromium/content/app/strings/translations/content_strings_ar.xtb
index 06de53d2e37..e941ecf438a 100644
--- a/chromium/content/app/strings/translations/content_strings_ar.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ar.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">شريط تمرير</translation>
<translation id="1211441953136645838">تعليق ختامي</translation>
<translation id="1281252709823657822">مربع حوار</translation>
-<translation id="1289247557029249093">الخروج من وضع "نافذة ضمن النافذة"</translation>
<translation id="1335095011850992622">إسهامات</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">إعلان بانر</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">اليوم</translation>
<translation id="2158401438286456825">قائمة صفحات</translation>
<translation id="2226276347425096477">يُرجى اختصار هذا النص حتى يصل إلى <ph name="MAX_CHARACTERS" /> من الحروف أو أقل (أنت الآن تستخدم <ph name="CURRENT_LENGTH" /> من الحروف).</translation>
+<translation id="2246498165605549352">ملف محلي</translation>
<translation id="2247351761944213033">الأسبوع <ph name="WEEKNUMBER" />، <ph name="YEAR" /></translation>
<translation id="2277199496770840904">المقطع الصوتي <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">مربع اختيار</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">صورة غير مُصنَّفة</translation>
<translation id="3706100364254443312">تبديل</translation>
<translation id="3732799496749320381">شهر</translation>
+<translation id="3754210790023674521">الخروج من وضع "نافذة ضمن نافذة"</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> غيغابايت</translation>
<translation id="3808586225841795776">عبارة</translation>
<translation id="3822383571486410024">يُرجى إطالة هذا النص إلى <ph name="MIN_CHARACTERS" /> من الحروف أو أكثر (أنت تستخدم حاليًا <ph name="CURRENT_LENGTH" /> من الحروف).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">متفرع</translation>
<translation id="4664250907885839816">يجب ألا يشتمل الجزء الذي يلي العلامة "<ph name="ATSIGN" />" على الرمز "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">ملحق</translation>
+<translation id="4718048029184481307">تشغيل في وضع "نافذة ضمن النافذة"</translation>
<translation id="4742539557769756338">غلاف</translation>
<translation id="4748357248530471599">تبديل صورة مقطوعة للشاشة إلى وضع ملء الشاشة</translation>
<translation id="4757246831282535685">لوحة علامة التبويب</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">كلمة ختامية</translation>
<translation id="6209276755895393898">يبدو أن: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">مسرد مصطلحات</translation>
-<translation id="628938136236500310">التشغيل في وضع "نافذة ضمن النافذة"</translation>
+<translation id="6310801910862476708">الخروج من وضع "نافذة ضمن نافذة"</translation>
<translation id="6398862346408813489">عرض لوحة تحديد الشهر</translation>
<translation id="6404546809543547843">شريط تمرير وقت الصوت</translation>
<translation id="6443871981718447451">عرض قائمة مقاطع الترجمة والشرح</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_bg.xtb b/chromium/content/app/strings/translations/content_strings_bg.xtb
index a8cdc622ec9..e676655745e 100644
--- a/chromium/content/app/strings/translations/content_strings_bg.xtb
+++ b/chromium/content/app/strings/translations/content_strings_bg.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">плъзгач</translation>
<translation id="1211441953136645838">бележка в края</translation>
<translation id="1281252709823657822">диалогов прозорец</translation>
-<translation id="1289247557029249093">Изход от режима „Картина в картината“</translation>
<translation id="1335095011850992622">признания за източника</translation>
<translation id="1342835525016946179">статия</translation>
<translation id="1359897965706325498">банер</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Днес</translation>
<translation id="2158401438286456825">списък със страниците</translation>
<translation id="2226276347425096477">Моля, съкратете този текст до <ph name="MAX_CHARACTERS" /> знака или по-малко (понастоящем използвате <ph name="CURRENT_LENGTH" /> знака).</translation>
+<translation id="2246498165605549352">Локален файл</translation>
<translation id="2247351761944213033">Седмица <ph name="WEEKNUMBER" />, <ph name="YEAR" /> г.</translation>
<translation id="2277199496770840904">Запис <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">квадратче за отметка</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Изображение без етикет</translation>
<translation id="3706100364254443312">превключвател</translation>
<translation id="3732799496749320381">мм</translation>
+<translation id="3754210790023674521">Изход от „Картина в картината“</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> ГБ</translation>
<translation id="3808586225841795776">термин</translation>
<translation id="3822383571486410024">Моля, удължете този текст поне до <ph name="MIN_CHARACTERS" /> знака (понастоящем използвате <ph name="CURRENT_LENGTH" />).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Текстът след „<ph name="ATSIGN" />“ не бива да съдържа символа „<ph name="INVALIDCHARACTER" />“.</translation>
<translation id="4668956016107839909">приложение</translation>
+<translation id="4718048029184481307">Възпроизвежда се в режим „Картина в картината“</translation>
<translation id="4742539557769756338">корица</translation>
<translation id="4748357248530471599">превключване между прорез на екрана и цял екран</translation>
<translation id="4757246831282535685">панел с раздели</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">послеслов</translation>
<translation id="6209276755895393898">Изглежда, че това е: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">терминологичен речник</translation>
-<translation id="628938136236500310">Възпроизвежда се в режим „Картина в картината“</translation>
+<translation id="6310801910862476708">Изход от „Картина в картината“</translation>
<translation id="6398862346408813489">Показване на панела за избиране на месец</translation>
<translation id="6404546809543547843">времеви плъзгач за аудиозаписа</translation>
<translation id="6443871981718447451">показване на менюто за надписи</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_bn.xtb b/chromium/content/app/strings/translations/content_strings_bn.xtb
index 46b6e143138..a714f002b94 100644
--- a/chromium/content/app/strings/translations/content_strings_bn.xtb
+++ b/chromium/content/app/strings/translations/content_strings_bn.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">স্লাইডার</translation>
<translation id="1211441953136645838">এন্ডনোট</translation>
<translation id="1281252709823657822">ডায়ালগ</translation>
-<translation id="1289247557029249093">ছবির-মধ্যে-ছবি মোড থেকে বেরিয়ে আসুন</translation>
<translation id="1335095011850992622">ক্রেডিট</translation>
<translation id="1342835525016946179">নিবন্ধ</translation>
<translation id="1359897965706325498">ব্যানার</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">আজ</translation>
<translation id="2158401438286456825">পৃষ্ঠা তালিকা</translation>
<translation id="2226276347425096477">দয়া করে এই পাঠ্যটি <ph name="MAX_CHARACTERS" />টি অক্ষর বা তার কমে (আপনি বর্তমানে <ph name="CURRENT_LENGTH" />টি অক্ষর ব্যবহার করছেন) সংক্ষিপ্ত করুন৷</translation>
+<translation id="2246498165605549352">স্থানীয় ফাইল</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" /> সপ্তাহ, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ট্র্যাক <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">চেকবাক্স</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">লেবেল ছাড়া ছবি</translation>
<translation id="3706100364254443312">পরিবর্তন করুন</translation>
<translation id="3732799496749320381">মিমি</translation>
+<translation id="3754210790023674521">ছবির-মধ্যে-ছবি মোড থেকে বেরিয়ে আসুন</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> জিবি</translation>
<translation id="3808586225841795776">পদ</translation>
<translation id="3822383571486410024">দয়া করে এই পাঠ্যকে ন্যূনতম <ph name="MIN_CHARACTERS" /> অক্ষরের বা তার বেশি (আপনি বর্তমানে <ph name="CURRENT_LENGTH" />টি অক্ষর ব্যবহার করেছেন) দৈর্ঘের করুন।</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' অনুসরণ করে এমন একটি অংশে '<ph name="INVALIDCHARACTER" />' চিহ্ন থাকা উচিত নয়৷</translation>
<translation id="4668956016107839909">পরিশিষ্ট</translation>
+<translation id="4718048029184481307">ছবির-মধ্যে-ছবি মোডে চলছে</translation>
<translation id="4742539557769756338">কভার</translation>
<translation id="4748357248530471599">ডিসপ্লে কাট-আউট ফুল-স্ক্রিনে টগল করুন</translation>
<translation id="4757246831282535685">ট্যাব প্যানেল</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">পরিশিষ্ট</translation>
<translation id="6209276755895393898">মনে হচ্ছে: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">শব্দকোষ</translation>
-<translation id="628938136236500310">ছবির-মধ্যে-ছবি মোডে চালানো হচ্ছে</translation>
+<translation id="6310801910862476708">ছবির-মধ্যে-ছবি মোড থেকে বেরিয়ে আসুন</translation>
<translation id="6398862346408813489">মাস নির্বাচনের প্যানেল দেখান</translation>
<translation id="6404546809543547843">অডিও সময় স্ক্রাবার</translation>
<translation id="6443871981718447451">ক্লোজড ক্যাপশনের মেনু দেখান</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ca.xtb b/chromium/content/app/strings/translations/content_strings_ca.xtb
index e5dd528c318..c540c205929 100644
--- a/chromium/content/app/strings/translations/content_strings_ca.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ca.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">control lliscant</translation>
<translation id="1211441953136645838">nota final</translation>
<translation id="1281252709823657822">quadre de diàleg</translation>
-<translation id="1289247557029249093">Surt del mode de pantalla en pantalla</translation>
<translation id="1335095011850992622">crèdits</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">bàner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Avui</translation>
<translation id="2158401438286456825">llista de pàgines</translation>
<translation id="2226276347425096477">Escurceu aquest text a un màxim de <ph name="MAX_CHARACTERS" /> caràcters (ara n'esteu utilitzant <ph name="CURRENT_LENGTH" />).</translation>
+<translation id="2246498165605549352">Fitxer local</translation>
<translation id="2247351761944213033">Setmana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Pista <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">casella de selecció</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Imatge sense etiquetar</translation>
<translation id="3706100364254443312">commutador</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Surt del mode de pantalla en pantalla</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">terme</translation>
<translation id="3822383571486410024">Allargueu aquest text fins a un mínim de <ph name="MIN_CHARACTERS" /> caràcters (ara n'utilitzeu <ph name="CURRENT_LENGTH" />).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">arbre</translation>
<translation id="4664250907885839816">Un domini precedit per "<ph name="ATSIGN" />" no pot contenir el símbol "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">apèndix</translation>
+<translation id="4718048029184481307">S'està reproduint en mode de pantalla en pantalla</translation>
<translation id="4742539557769756338">portada</translation>
<translation id="4748357248530471599">activa o desactiva la pantalla completa al retall de pantalla</translation>
<translation id="4757246831282535685">tauler de pestanyes</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">cloenda</translation>
<translation id="6209276755895393898">Sembla el següent: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glossari</translation>
-<translation id="628938136236500310">El vídeo s'està reproduint en mode de pantalla en pantalla</translation>
+<translation id="6310801910862476708">Surt del mode de pantalla en pantalla</translation>
<translation id="6398862346408813489">Mostra el tauler de la selecció de mes</translation>
<translation id="6404546809543547843">barra de moment de l'àudio</translation>
<translation id="6443871981718447451">mostra el menú de subtítols</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_cs.xtb b/chromium/content/app/strings/translations/content_strings_cs.xtb
index 1f7bba3ec14..06545ed03f5 100644
--- a/chromium/content/app/strings/translations/content_strings_cs.xtb
+++ b/chromium/content/app/strings/translations/content_strings_cs.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">posuvník</translation>
<translation id="1211441953136645838">koncová poznámka</translation>
<translation id="1281252709823657822">dialogové okno</translation>
-<translation id="1289247557029249093">Ukončit režim obrazu v obraze</translation>
<translation id="1335095011850992622">poděkování</translation>
<translation id="1342835525016946179">čl</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Dnes</translation>
<translation id="2158401438286456825">seznam stránek</translation>
<translation id="2226276347425096477">Zkraťte prosím tento text na <ph name="MAX_CHARACTERS" /> znaků nebo méně. (Aktuálně má <ph name="CURRENT_LENGTH" /> znaků.)</translation>
+<translation id="2246498165605549352">Místní soubor</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. týden, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Stopa <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">zaškrtávací políčko</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Neoznačený obrázek</translation>
<translation id="3706100364254443312">přepínač</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Ukončit režim obrazu v obraze</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">výraz</translation>
<translation id="3822383571486410024">Prodlužte prosím tento text na <ph name="MIN_CHARACTERS" /> či více znaků. (Aktuálně má <ph name="CURRENT_LENGTH" /> znaků.)</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">strom</translation>
<translation id="4664250907885839816">Část za znakem <ph name="ATSIGN" /> nesmí obsahovat znak <ph name="INVALIDCHARACTER" />.</translation>
<translation id="4668956016107839909">příloha</translation>
+<translation id="4718048029184481307">Video se přehrává v režimu obrazu v obraze</translation>
<translation id="4742539557769756338">titulní strana</translation>
<translation id="4748357248530471599">přepnout výřez displeje na celou obrazovku</translation>
<translation id="4757246831282535685">panel karty</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">doslov</translation>
<translation id="6209276755895393898">Vypadá jako: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glosář</translation>
-<translation id="628938136236500310">Přehrávání v režimu obraz v obraze</translation>
+<translation id="6310801910862476708">Ukončit režim obrazu v obraze</translation>
<translation id="6398862346408813489">Zobrazit panel pro výběr měsíců</translation>
<translation id="6404546809543547843">posuvník času zvuku</translation>
<translation id="6443871981718447451">zobrazit nabídku skrytých titulků</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_da.xtb b/chromium/content/app/strings/translations/content_strings_da.xtb
index 899799c349a..57c0566ff95 100644
--- a/chromium/content/app/strings/translations/content_strings_da.xtb
+++ b/chromium/content/app/strings/translations/content_strings_da.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">skyder</translation>
<translation id="1211441953136645838">slutnote</translation>
<translation id="1281252709823657822">dialogboks</translation>
-<translation id="1289247557029249093">Afslut tilstanden med integreret billede</translation>
<translation id="1335095011850992622">anerkendelser</translation>
<translation id="1342835525016946179">artikel</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">I dag</translation>
<translation id="2158401438286456825">sideliste</translation>
<translation id="2226276347425096477">Forkort denne tekst til <ph name="MAX_CHARACTERS" /> tegn eller færre (du bruger i øjeblikket <ph name="CURRENT_LENGTH" /> tegn).</translation>
+<translation id="2246498165605549352">Lokal fil</translation>
<translation id="2247351761944213033">Uge <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Spor <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">afkrydsningsfelt</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Billedet har ingen etiket</translation>
<translation id="3706100364254443312">kontakt</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Afslut integreret billede</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">term</translation>
<translation id="3822383571486410024">Forlæng denne tekst til <ph name="MIN_CHARACTERS" /> eller flere tegn (du bruger i øjeblikket <ph name="CURRENT_LENGTH" /> tegn).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">træ</translation>
<translation id="4664250907885839816">Den del, der kommer efter "<ph name="ATSIGN" />", må ikke indeholde symbolet "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">bilag</translation>
+<translation id="4718048029184481307">Afspiller i integreret billede</translation>
<translation id="4742539557769756338">forside</translation>
<translation id="4748357248530471599">skift fra skærmhak til fuld skærm</translation>
<translation id="4757246831282535685">fanepanel</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">efterskrift</translation>
<translation id="6209276755895393898">Det lader til at være: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">ordliste</translation>
-<translation id="628938136236500310">Afspiller i tilstanden med integreret billede</translation>
+<translation id="6310801910862476708">Afslut integreret billede</translation>
<translation id="6398862346408813489">Vis panel til valg af måned</translation>
<translation id="6404546809543547843">afspilningsbjælke for lyd</translation>
<translation id="6443871981718447451">vis menuen for undertekster</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_de.xtb b/chromium/content/app/strings/translations/content_strings_de.xtb
index a4eefe2fd23..8f450493972 100644
--- a/chromium/content/app/strings/translations/content_strings_de.xtb
+++ b/chromium/content/app/strings/translations/content_strings_de.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">Schieberegler</translation>
<translation id="1211441953136645838">Endnote</translation>
<translation id="1281252709823657822">Kleines Fenster</translation>
-<translation id="1289247557029249093">Bild-im-Bild-Modus beenden</translation>
<translation id="1335095011850992622">Mitwirkende</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">Banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Heute</translation>
<translation id="2158401438286456825">Seitenliste</translation>
<translation id="2226276347425096477">Kürzen Sie diesen Text auf max. <ph name="MAX_CHARACTERS" /> Zeichen. Zurzeit verwenden Sie <ph name="CURRENT_LENGTH" /> Zeichen.</translation>
+<translation id="2246498165605549352">Lokale Datei</translation>
<translation id="2247351761944213033">Woche <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Titel <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">Kästchen</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Bild ohne Label</translation>
<translation id="3706100364254443312">wechseln</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Bild-im-Bild-Modus beenden</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">Begriff</translation>
<translation id="3822383571486410024">Verlängern Sie diesen Text auf mindestens <ph name="MIN_CHARACTERS" /> Zeichen. Derzeit verwenden Sie <ph name="CURRENT_LENGTH" /> Zeichen.</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Nach dem <ph name="ATSIGN" />-Zeichen darf das Zeichen "<ph name="INVALIDCHARACTER" />" nicht verwendet werden.</translation>
<translation id="4668956016107839909">Anhang</translation>
+<translation id="4718048029184481307">Wird im Bild-im-Bild-Modus abgespielt</translation>
<translation id="4742539557769756338">Titelseite</translation>
<translation id="4748357248530471599">Vollbildmodus mit Display-Aussparung ein-/ausschalten</translation>
<translation id="4757246831282535685">Tabsteuerfeld</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">Nachwort</translation>
<translation id="6209276755895393898">Anscheinend ist es: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">Glossar</translation>
-<translation id="628938136236500310">Bild-im-Bild-Modus aktiv</translation>
+<translation id="6310801910862476708">Bild-im-Bild-Modus beenden</translation>
<translation id="6398862346408813489">Auswahlbereich für Monatsanzeige</translation>
<translation id="6404546809543547843">Audio-Zeitachse</translation>
<translation id="6443871981718447451">Untertitelmenü einblenden</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_el.xtb b/chromium/content/app/strings/translations/content_strings_el.xtb
index b31d720d990..a81bdd43218 100644
--- a/chromium/content/app/strings/translations/content_strings_el.xtb
+++ b/chromium/content/app/strings/translations/content_strings_el.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">ρυθμιστικό</translation>
<translation id="1211441953136645838">σημείωση τέλους</translation>
<translation id="1281252709823657822">παράθυρο διαλόγου</translation>
-<translation id="1289247557029249093">Έξοδος από τη λειτουργία picture-in-picture</translation>
<translation id="1335095011850992622">συντελεστές</translation>
<translation id="1342835525016946179">άρθρο</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Σήμερα</translation>
<translation id="2158401438286456825">λίστα σελίδων</translation>
<translation id="2226276347425096477">Κάντε πιο σύντομο αυτό το κείμενο ώστε να έχει το πολύ <ph name="MAX_CHARACTERS" /> χαρακτήρες (αυτήν τη στιγμή χρησιμοποιείτε <ph name="CURRENT_LENGTH" /> χαρακτήρες).</translation>
+<translation id="2246498165605549352">Τοπικό αρχείο</translation>
<translation id="2247351761944213033">Εβδομάδα <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Κομμάτι <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">πλαίσιο ελέγχου</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Εικόνα χωρίς ετικέτα</translation>
<translation id="3706100364254443312">εναλλαγή</translation>
<translation id="3732799496749320381">μμ</translation>
+<translation id="3754210790023674521">Έξοδος από τη λειτουργία picture-in-picture</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">όρος</translation>
<translation id="3822383571486410024">Αυξήστε την έκταση αυτού του κειμένου στους <ph name="MIN_CHARACTERS" /> χαρακτήρες ή περισσότερο (αυτήν τη στιγμή χρησιμοποιείτε <ph name="CURRENT_LENGTH" /> χαρακτήρες).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">δέντρο</translation>
<translation id="4664250907885839816">Το τμήμα της διεύθυνσης μετά το σύμβολο "<ph name="ATSIGN" />" δεν πρέπει να περιέχει το σύμβολο "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">παράρτημα</translation>
+<translation id="4718048029184481307">Αναπαραγωγή σε λειτουργία picture-in-picture</translation>
<translation id="4742539557769756338">εξώφυλλο</translation>
<translation id="4748357248530471599">εναλλαγή πλήρους οθόνης εγκοπής οθόνης</translation>
<translation id="4757246831282535685">παράθυρο καρτέλας</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">επίλογος</translation>
<translation id="6209276755895393898">Φαίνεται πως είναι: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">γλωσσάρι</translation>
-<translation id="628938136236500310">Αναπαραγωγή στη λειτουργία picture-in-picture</translation>
+<translation id="6310801910862476708">Έξοδος από τη λειτουργία Picture-in-Picture</translation>
<translation id="6398862346408813489">Εμφάνιση παραθύρου επιλογής μήνα</translation>
<translation id="6404546809543547843">δείκτης χρόνου ήχου</translation>
<translation id="6443871981718447451">εμφάνιση μενού υποτίτλων</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_en-GB.xtb b/chromium/content/app/strings/translations/content_strings_en-GB.xtb
index 3d77600b7e8..8592df44ce2 100644
--- a/chromium/content/app/strings/translations/content_strings_en-GB.xtb
+++ b/chromium/content/app/strings/translations/content_strings_en-GB.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">slider</translation>
<translation id="1211441953136645838">endnote</translation>
<translation id="1281252709823657822">dialogue</translation>
-<translation id="1289247557029249093">Exit picture-in-picture mode</translation>
<translation id="1335095011850992622">credits</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Today</translation>
<translation id="2158401438286456825">page list</translation>
<translation id="2226276347425096477">Please shorten this text to <ph name="MAX_CHARACTERS" /> characters or less (you are currently using <ph name="CURRENT_LENGTH" /> characters).</translation>
+<translation id="2246498165605549352">Local file</translation>
<translation id="2247351761944213033">Week <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Track <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">Tick box</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Unlabelled image</translation>
<translation id="3706100364254443312">switch</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Exit picture-in-picture</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">term</translation>
<translation id="3822383571486410024">Please lengthen this text to <ph name="MIN_CHARACTERS" /> characters or more (you are currently using <ph name="CURRENT_LENGTH" /> characters).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">A part following '<ph name="ATSIGN" />' should not contain the symbol '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="4668956016107839909">appendix</translation>
+<translation id="4718048029184481307">Playing in picture-in-picture</translation>
<translation id="4742539557769756338">cover</translation>
<translation id="4748357248530471599">toggle display cutout full screen</translation>
<translation id="4757246831282535685">tab panel</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">afterword</translation>
<translation id="6209276755895393898">Appears to be: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glossary</translation>
-<translation id="628938136236500310">Playing in picture-in-picture mode</translation>
+<translation id="6310801910862476708">Exit picture-in-picture</translation>
<translation id="6398862346408813489">Show month selection panel</translation>
<translation id="6404546809543547843">audio time scrubber</translation>
<translation id="6443871981718447451">show closed captions menu</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_es-419.xtb b/chromium/content/app/strings/translations/content_strings_es-419.xtb
index e5d563eff02..928baeca59b 100644
--- a/chromium/content/app/strings/translations/content_strings_es-419.xtb
+++ b/chromium/content/app/strings/translations/content_strings_es-419.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">control deslizante</translation>
<translation id="1211441953136645838">nota final</translation>
<translation id="1281252709823657822">diálogo</translation>
-<translation id="1289247557029249093">Salir del modo de pantalla en pantalla</translation>
<translation id="1335095011850992622">créditos</translation>
<translation id="1342835525016946179">artículo</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Hoy</translation>
<translation id="2158401438286456825">listado de páginas</translation>
<translation id="2226276347425096477">Acorta este texto a <ph name="MAX_CHARACTERS" /> caracteres o menos (actualmente estás usando <ph name="CURRENT_LENGTH" /> caracteres).</translation>
+<translation id="2246498165605549352">Archivo local</translation>
<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Pista <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">casilla de verificación</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Imagen sin etiquetar</translation>
<translation id="3706100364254443312">cambiar</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Salir del modo de pantalla en pantalla</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">término</translation>
<translation id="3822383571486410024">Alarga el texto a <ph name="MIN_CHARACTERS" /> o más caracteres (actualmente, usas <ph name="CURRENT_LENGTH" /> caracteres).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">El texto después del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">apéndice</translation>
+<translation id="4718048029184481307">Reproduciendo en modo de pantalla en pantalla</translation>
<translation id="4742539557769756338">portada</translation>
<translation id="4748357248530471599">activar o desactivar la pantalla completa en el corte de pantalla</translation>
<translation id="4757246831282535685">panel de pestañas</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">posfacio</translation>
<translation id="6209276755895393898">Parece ser: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glosario</translation>
-<translation id="628938136236500310">Reproduciendo en modo pantalla en pantalla</translation>
+<translation id="6310801910862476708">Salir del modo de pantalla en pantalla</translation>
<translation id="6398862346408813489">Mostrar el panel de selección de meses</translation>
<translation id="6404546809543547843">control deslizante de duración del audio</translation>
<translation id="6443871981718447451">muestra el menú de subtítulos opcionales</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_es.xtb b/chromium/content/app/strings/translations/content_strings_es.xtb
index 6908e9bf0e5..3722b9f56c5 100644
--- a/chromium/content/app/strings/translations/content_strings_es.xtb
+++ b/chromium/content/app/strings/translations/content_strings_es.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">control deslizante</translation>
<translation id="1211441953136645838">nota final</translation>
<translation id="1281252709823657822">cuadro de diálogo</translation>
-<translation id="1289247557029249093">Salir del modo imagen en imagen</translation>
<translation id="1335095011850992622">créditos</translation>
<translation id="1342835525016946179">artículo</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Hoy</translation>
<translation id="2158401438286456825">lista de páginas</translation>
<translation id="2226276347425096477">Reduce la longitud de este texto a <ph name="MAX_CHARACTERS" /> caracteres o menos (actualmente, el texto tiene <ph name="CURRENT_LENGTH" /> caracteres)</translation>
+<translation id="2246498165605549352">Archivo local</translation>
<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Pista <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">casilla de verificación</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Imagen sin descripción</translation>
<translation id="3706100364254443312">interruptor</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Salir del modo imagen en imagen</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">término</translation>
<translation id="3822383571486410024">Aumenta la longitud del texto a <ph name="MIN_CHARACTERS" /> caracteres como mínimo (actualmente, el texto tiene <ph name="CURRENT_LENGTH" /> caracteres).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">El texto detrás del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">apéndice</translation>
+<translation id="4718048029184481307">Reproduciendo en modo imagen en imagen</translation>
<translation id="4742539557769756338">portada</translation>
<translation id="4748357248530471599">activar pantalla completa en el recorte de la pantalla</translation>
<translation id="4757246831282535685">panel de pestaña</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">epílogo</translation>
<translation id="6209276755895393898">Parece que es: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glosario</translation>
-<translation id="628938136236500310">Reproduciendo en modo imagen en imagen</translation>
+<translation id="6310801910862476708">Salir del modo imagen en imagen</translation>
<translation id="6398862346408813489">Mostrar panel para seleccionar el mes</translation>
<translation id="6404546809543547843">control deslizante de duración de audio</translation>
<translation id="6443871981718447451">mostrar menú de subtítulos</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_et.xtb b/chromium/content/app/strings/translations/content_strings_et.xtb
index dbc55f637f1..a9b705f30e4 100644
--- a/chromium/content/app/strings/translations/content_strings_et.xtb
+++ b/chromium/content/app/strings/translations/content_strings_et.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">liugur</translation>
<translation id="1211441953136645838">järelmärkus</translation>
<translation id="1281252709823657822">dialoog</translation>
-<translation id="1289247557029249093">Välju režiimist Pilt pildis</translation>
<translation id="1335095011850992622">tiitrid</translation>
<translation id="1342835525016946179">artikkel</translation>
<translation id="1359897965706325498">bänner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Täna</translation>
<translation id="2158401438286456825">lehtede loend</translation>
<translation id="2226276347425096477">Lühendage seda teksti <ph name="MAX_CHARACTERS" /> tähemärgini või rohkem (praegu kasutate <ph name="CURRENT_LENGTH" /> tähemärki).</translation>
+<translation id="2246498165605549352">Kohalik fail</translation>
<translation id="2247351761944213033">Nädal <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904"><ph name="NUMBER" />. lugu</translation>
<translation id="2291999235780842123">märkeruut</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Sildita pilt</translation>
<translation id="3706100364254443312">lüliti</translation>
<translation id="3732799496749320381">kk</translation>
+<translation id="3754210790023674521">Välju režiimist Pilt pildis</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">termin</translation>
<translation id="3822383571486410024">Pikendage teksti vähemalt <ph name="MIN_CHARACTERS" /> tähemärgini (kasutate praegu <ph name="CURRENT_LENGTH" /> tähemärki).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Märgile „<ph name="ATSIGN" />” järgnev osa ei tohi sisaldada sümbolit „<ph name="INVALIDCHARACTER" />”.</translation>
<translation id="4668956016107839909">lisa</translation>
+<translation id="4718048029184481307">Režiimis Pilt pildis mängimine</translation>
<translation id="4742539557769756338">kaas</translation>
<translation id="4748357248530471599">ekraani väljalõike täisekraanrežiimi sisse-/väljalülitamine</translation>
<translation id="4757246831282535685">vahelehepaneel</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">järelsõna</translation>
<translation id="6209276755895393898">Näib olevat: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">sõnastik</translation>
-<translation id="628938136236500310">Esitatakse režiimis Pilt pildis</translation>
+<translation id="6310801910862476708">Välju režiimist Pilt pildis</translation>
<translation id="6398862346408813489">Kuu valikupaneeli kuvamine</translation>
<translation id="6404546809543547843">heli ajamõõdik</translation>
<translation id="6443871981718447451">kuva subtiitrite menüü</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_fa.xtb b/chromium/content/app/strings/translations/content_strings_fa.xtb
index 10fad531f33..720120a8815 100644
--- a/chromium/content/app/strings/translations/content_strings_fa.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fa.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">لغزنده</translation>
<translation id="1211441953136645838">ته‌نویس</translation>
<translation id="1281252709823657822">کادر گفتگو</translation>
-<translation id="1289247557029249093">خروج از حالت تصویردرتصویر</translation>
<translation id="1335095011850992622">دست‌اندرکاران</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">برنما</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">امروز</translation>
<translation id="2158401438286456825">فهرست صفحه</translation>
<translation id="2226276347425096477">لطفاً این متن را به اندازه <ph name="MAX_CHARACTERS" /> نویسه یا کمتر کوتاه کنید (شما در حال حاضر از <ph name="CURRENT_LENGTH" /> نویسه استفاده می‌کنید).</translation>
+<translation id="2246498165605549352">فایل محلی</translation>
<translation id="2247351761944213033">هفته <ph name="WEEKNUMBER" />، <ph name="YEAR" /></translation>
<translation id="2277199496770840904">آهنگ <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">کادر تأیید</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">تصویر بدون برچسب</translation>
<translation id="3706100364254443312">تعویض</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">خروج از تصویردرتصویر</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> گیگابایت</translation>
<translation id="3808586225841795776">اصطلاح</translation>
<translation id="3822383571486410024">لطفاً این نوشتار را به <ph name="MIN_CHARACTERS" /> نویسه یا بیشتر افزایش دهید (درحال حاضر از <ph name="CURRENT_LENGTH" /> نویسه استفاده می‌کنید).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">درخت</translation>
<translation id="4664250907885839816">قسمت بعد از «<ph name="ATSIGN" />» نباید حاوی نماد «<ph name="INVALIDCHARACTER" />» باشد.</translation>
<translation id="4668956016107839909">ضمیمه</translation>
+<translation id="4718048029184481307">درحال پخش در حالت تصویردرتصویر</translation>
<translation id="4742539557769756338">جلد</translation>
<translation id="4748357248530471599">جابجایی برش نمایشگر تمام‌صفحه</translation>
<translation id="4757246831282535685">پانل برگه</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">سخن پایانی</translation>
<translation id="6209276755895393898">به‌نظر می‌رسد <ph name="DESCRIPTION" /> باشد</translation>
<translation id="6213469881011901533">واژه‌نامه</translation>
-<translation id="628938136236500310">پخش درحالت تصویردرتصویر</translation>
+<translation id="6310801910862476708">خروج از تصویر در تصویر</translation>
<translation id="6398862346408813489">نمایش پانل انتخاب ماه</translation>
<translation id="6404546809543547843">انتخابگر زمان صدا</translation>
<translation id="6443871981718447451">نمایش منوی زیرنویس ناشنوایان</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_fi.xtb b/chromium/content/app/strings/translations/content_strings_fi.xtb
index b9788ae5407..266244b5cea 100644
--- a/chromium/content/app/strings/translations/content_strings_fi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fi.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">liukusäädin</translation>
<translation id="1211441953136645838">loppuhuomautus</translation>
<translation id="1281252709823657822">valintaikkuna</translation>
-<translation id="1289247557029249093">Sulje kuva kuvassa ‑tila</translation>
<translation id="1335095011850992622">tunnustukset</translation>
<translation id="1342835525016946179">artikkeli</translation>
<translation id="1359897965706325498">banneri</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Tänään</translation>
<translation id="2158401438286456825">sivuluettelo</translation>
<translation id="2226276347425096477">Lyhennä tämä teksti alle <ph name="MAX_CHARACTERS" /> merkkiin (tällä hetkellä käytössä <ph name="CURRENT_LENGTH" /> merkkiä).</translation>
+<translation id="2246498165605549352">Paikallinen tiedosto</translation>
<translation id="2247351761944213033">Viikko <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Kappale <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">valintaruutu</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Tunnisteeton kuva</translation>
<translation id="3706100364254443312">vaihto</translation>
<translation id="3732799496749320381">kk</translation>
+<translation id="3754210790023674521">Sulje kuva kuvassa ‑tila</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> Gt</translation>
<translation id="3808586225841795776">termi</translation>
<translation id="3822383571486410024">Pidennä tämä teksti yli <ph name="MIN_CHARACTERS" /> merkkiin (tällä hetkellä käytössä <ph name="CURRENT_LENGTH" /> merkkiä).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816"><ph name="ATSIGN" />-osan jälkeen tulevassa osassa ei pitäisi olla merkkiä <ph name="INVALIDCHARACTER" />.</translation>
<translation id="4668956016107839909">liite</translation>
+<translation id="4718048029184481307">Toistetaan kuva kuvassa ‑tilassa</translation>
<translation id="4742539557769756338">kansi</translation>
<translation id="4748357248530471599">näyttölovi osana koko näytön tilaa päälle/pois</translation>
<translation id="4757246831282535685">välilehtipaneeli</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">jälkipuhe</translation>
<translation id="6209276755895393898">Näkyy olevan: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">sanasto</translation>
-<translation id="628938136236500310">Toistetaan kuva kuvassa ‑tilassa</translation>
+<translation id="6310801910862476708">Sulje kuva kuvassa ‑tila</translation>
<translation id="6398862346408813489">Näytä kuukaudenvalintapaneeli</translation>
<translation id="6404546809543547843">äänen ajan liukusäädin</translation>
<translation id="6443871981718447451">näytä tekstitysvalikko</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_fil.xtb b/chromium/content/app/strings/translations/content_strings_fil.xtb
index 5426ac4dde8..663e71ad53c 100644
--- a/chromium/content/app/strings/translations/content_strings_fil.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fil.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">slider</translation>
<translation id="1211441953136645838">endnote</translation>
<translation id="1281252709823657822">dialog</translation>
-<translation id="1289247557029249093">Lumabas sa picture-in-picture mode</translation>
<translation id="1335095011850992622">mga credit</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Ngayon</translation>
<translation id="2158401438286456825">listahan ng page</translation>
<translation id="2226276347425096477">Mangyaring paikliin ang tekstong ito ng <ph name="MAX_CHARACTERS" /> (na) character o mas mababa (kasalukuyan kang gumagamit ng <ph name="CURRENT_LENGTH" /> (na) character).</translation>
+<translation id="2246498165605549352">Lokal na File</translation>
<translation id="2247351761944213033">Linggo <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Track <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">checkbox</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Walang label na larawan</translation>
<translation id="3706100364254443312">lumipat</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Lumabas sa picture-in-picture</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> (na) GB</translation>
<translation id="3808586225841795776">termino</translation>
<translation id="3822383571486410024">Pakihabaan ang text na ito hanggang <ph name="MIN_CHARACTERS" /> (na) character o higit pa (kasalukuyan kang gumagamit ng <ph name="CURRENT_LENGTH" /> (na) character).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Hindi dapat naglalaman ng simbolong '<ph name="INVALIDCHARACTER" />' ang bahagi pagkatapos ng '<ph name="ATSIGN" />.'</translation>
<translation id="4668956016107839909">appendix</translation>
+<translation id="4718048029184481307">Nagpe-play sa picture-in-picture</translation>
<translation id="4742539557769756338">cover</translation>
<translation id="4748357248530471599">i-toggle ang fullscreen ng cutout ng display</translation>
<translation id="4757246831282535685">panel ng tab</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">afterword</translation>
<translation id="6209276755895393898">Mukhang: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glosaryo</translation>
-<translation id="628938136236500310">Nagpe-play sa picture-in-picture mode</translation>
+<translation id="6310801910862476708">Lumabas sa Picture-in-Picture</translation>
<translation id="6398862346408813489">Ipakita ang panel ng pagpipilian ng buwan</translation>
<translation id="6404546809543547843">scrubber ng oras ng audio</translation>
<translation id="6443871981718447451">Ipakita ang menu ng mga nakasarang caption</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_fr.xtb b/chromium/content/app/strings/translations/content_strings_fr.xtb
index af33fcbc641..cf78dcc090e 100644
--- a/chromium/content/app/strings/translations/content_strings_fr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fr.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">curseur</translation>
<translation id="1211441953136645838">note de fin</translation>
<translation id="1281252709823657822">boîte de dialogue</translation>
-<translation id="1289247557029249093">Quitter le mode PIP</translation>
<translation id="1335095011850992622">crédits</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">bannière</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Aujourd'hui</translation>
<translation id="2158401438286456825">liste des pages</translation>
<translation id="2226276347425096477">Veuillez réduire ce texte à <ph name="MAX_CHARACTERS" /> caractères maximum (il compte actuellement <ph name="CURRENT_LENGTH" /> caractères).</translation>
+<translation id="2246498165605549352">Fichier local</translation>
<translation id="2247351761944213033">Semaine <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Piste <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">case à cocher</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Image sans libellé</translation>
<translation id="3706100364254443312">interrupteur</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Quitter le mode PIP (Picture-in-picture)</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> Go</translation>
<translation id="3808586225841795776">terme</translation>
<translation id="3822383571486410024">Veuillez allonger ce texte pour qu'il comporte au moins <ph name="MIN_CHARACTERS" /> caractères. Il en compte actuellement <ph name="CURRENT_LENGTH" />.</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">La partie précédée du symbole "<ph name="ATSIGN" />" ne doit pas contenir le caractère "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">annexe</translation>
+<translation id="4718048029184481307">Lecture en mode Picture-in-picture</translation>
<translation id="4742539557769756338">couverture</translation>
<translation id="4748357248530471599">activer/désactiver plein écran en encoche</translation>
<translation id="4757246831282535685">panneau des onglets</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">postface</translation>
<translation id="6209276755895393898">L'image représente probablement : <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glossaire</translation>
-<translation id="628938136236500310">Lecture en mode Picture-in-picture</translation>
+<translation id="6310801910862476708">Quitter le mode PIP (Picture-in-picture)</translation>
<translation id="6398862346408813489">Afficher le panneau de sélection du mois</translation>
<translation id="6404546809543547843">curseur durée audio</translation>
<translation id="6443871981718447451">afficher le menu des sous-titres</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_gu.xtb b/chromium/content/app/strings/translations/content_strings_gu.xtb
index f4b6b3e383a..a6532eddf5a 100644
--- a/chromium/content/app/strings/translations/content_strings_gu.xtb
+++ b/chromium/content/app/strings/translations/content_strings_gu.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">સ્લાઇડર</translation>
<translation id="1211441953136645838">અંતિમ નોંધ</translation>
<translation id="1281252709823657822">સંવાદ</translation>
-<translation id="1289247557029249093">ચિત્રમાં ચિત્ર મોડમાંથી બહાર નીકળો</translation>
<translation id="1335095011850992622">ક્રેડિટ</translation>
<translation id="1342835525016946179">લેખ</translation>
<translation id="1359897965706325498">બેનર</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">આજે</translation>
<translation id="2158401438286456825">પેજ સૂચિ</translation>
<translation id="2226276347425096477">કૃપા કરીને આ ટેક્સ્ટને <ph name="MAX_CHARACTERS" /> અક્ષર અથવા તેથી ઓછા સુધી નાનો કરો (તમે હાલમાં <ph name="CURRENT_LENGTH" /> અક્ષરોનો ઉપયોગ કરી રહ્યા છો).</translation>
+<translation id="2246498165605549352">સ્થાનિક ફાઇલ</translation>
<translation id="2247351761944213033">અઠવાડિયું <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ટ્રૅક <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">ચેકબોક્સ</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">લેબલ વિનાની છબી</translation>
<translation id="3706100364254443312">સ્વિચ</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">ચિત્રમાં ચિત્રમાંથી બહાર નીકળો</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">ટર્મ</translation>
<translation id="3822383571486410024">કૃપા કરીને આ ટેક્સ્ટને <ph name="MIN_CHARACTERS" /> અક્ષર અથવા તેથી વધુ સુધી લંબાવો (તમે હાલમાં <ph name="CURRENT_LENGTH" /> અક્ષરોનો ઉપયોગ કરી રહ્યાં છો).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">ટ્રી</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ને અનુસરી રહેલા ભાગમાં '<ph name="INVALIDCHARACTER" />' પ્રતીક શામેલ હોવું જોઈએ નહીં.</translation>
<translation id="4668956016107839909">જોડાણ</translation>
+<translation id="4718048029184481307">ચિત્રમાં ચિત્રમાંથી ચલાવી રહ્યાં છીએ</translation>
<translation id="4742539557769756338">કવર</translation>
<translation id="4748357248530471599">ડિસ્પ્લેમાં જ સામેલ પૂર્ણસ્ક્રીન ટૉગલ કરો</translation>
<translation id="4757246831282535685">ટેબ પેનલ</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">સમાપન ભાષણ</translation>
<translation id="6209276755895393898">આના જેવું જણાય છે: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">શબ્દાવલી</translation>
-<translation id="628938136236500310">વીડિયો ચિત્ર-માં-ચિત્ર મોડમાં ચાલી રહ્યો છે</translation>
+<translation id="6310801910862476708">ચિત્ર-માં-ચિત્રમાંથી બહાર નીકળો</translation>
<translation id="6398862346408813489">મહિના પસંદગી પેનલ દર્શાવો</translation>
<translation id="6404546809543547843">ઑડિઓ સમય સ્ક્રબર</translation>
<translation id="6443871981718447451">બંધ કરેલું ઉપશીર્ષક મેનૂ દર્શાવો</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_hi.xtb b/chromium/content/app/strings/translations/content_strings_hi.xtb
index 0506b102e65..937a6af34b1 100644
--- a/chromium/content/app/strings/translations/content_strings_hi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hi.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">स्लाइडर</translation>
<translation id="1211441953136645838">एंड नोट</translation>
<translation id="1281252709823657822">संवाद</translation>
-<translation id="1289247557029249093">'पिक्चर में पिक्चर' मोड से बाहर निकलें</translation>
<translation id="1335095011850992622">क्रेडिट</translation>
<translation id="1342835525016946179">लेख</translation>
<translation id="1359897965706325498">बैनर</translation>
@@ -37,7 +36,8 @@
<translation id="2148716181193084225">आज</translation>
<translation id="2158401438286456825">पेज सूची</translation>
<translation id="2226276347425096477">कृपया इस टेक्स्ट को <ph name="MAX_CHARACTERS" /> वर्णों या कम तक छोटा करें (वर्तमान में आप <ph name="CURRENT_LENGTH" /> वर्णों का उपयोग कर रहे हैं).</translation>
-<translation id="2247351761944213033">सप्ताह <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2246498165605549352">लोकल फ़ाइल</translation>
+<translation id="2247351761944213033">हफ़्ता <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ट्रैक <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">चेकबॉक्स</translation>
<translation id="2311842470354187719">नया पेज</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">लेबल न की गई इमेज</translation>
<translation id="3706100364254443312">स्विच करें</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">'पिक्चर में पिक्चर' सुविधा से बाहर निकलें</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> जीबी</translation>
<translation id="3808586225841795776">शब्द</translation>
<translation id="3822383571486410024">कृपया इस लेख को <ph name="MIN_CHARACTERS" /> वर्णों या ज़्यादा तक बढ़ाएं (वर्तमान में आप <ph name="CURRENT_LENGTH" /> वर्णों का उपयोग कर रहे हैं).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">ट्री</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' के बाद आने वाले भाग में '<ph name="INVALIDCHARACTER" />' प्रतीक शामिल नहीं होना चाहिए.</translation>
<translation id="4668956016107839909">परिशिष्ट</translation>
+<translation id="4718048029184481307">वीडियो को 'पिक्चर में पिक्चर' सुविधा में चलाया जा रहा है</translation>
<translation id="4742539557769756338">कवर</translation>
<translation id="4748357248530471599">डिसप्ले कटआउट फ़ुलस्क्रीन टॉगल करें</translation>
<translation id="4757246831282535685">टैब पैनल</translation>
@@ -140,7 +142,7 @@
<translation id="588258955323874662">पूर्णस्‍क्रीन</translation>
<translation id="5888666972993069672">अब <ph name="DEVICE_FRIENDLY_NAME" /> पर कास्ट किया जा रहा है</translation>
<translation id="5939518447894949180">रीसेट करें</translation>
-<translation id="5966707198760109579">सप्ताह</translation>
+<translation id="5966707198760109579">हफ़्ता</translation>
<translation id="5987525920412732405">स्पिन बटन</translation>
<translation id="6011459053400940133">वॉल्यूम स्लाइडर</translation>
<translation id="6015796118275082299">वर्ष</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">उपसंहार</translation>
<translation id="6209276755895393898">यह इमेज इस बारे में लगती है: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">शब्दावली</translation>
-<translation id="628938136236500310">'पिक्चर में पिक्चर' मोड में चल रहा है</translation>
+<translation id="6310801910862476708">'पिक्चर में पिक्चर से बाहर निकलें'</translation>
<translation id="6398862346408813489">महीना चुनने का पैनल दिखाएं</translation>
<translation id="6404546809543547843">ऑडियो समय स्क्रबर</translation>
<translation id="6443871981718447451">बंद कैप्‍शन मेन्यू दिखाएं</translation>
@@ -210,7 +212,7 @@
<translation id="8057695513531652401">सूचना</translation>
<translation id="8105797009065549151">नोट संदर्भ</translation>
<translation id="811583516810654505">इमेज की जानकारी ढूंढी जा रही है</translation>
-<translation id="8117451130807776954">इस सप्ताह</translation>
+<translation id="8117451130807776954">इस हफ़्ते</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8261464734335370856">गलत स्पेलिंग</translation>
<translation id="8284326494547611709">कैप्शन</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_hr.xtb b/chromium/content/app/strings/translations/content_strings_hr.xtb
index 2dcf9a18501..46c9297575e 100644
--- a/chromium/content/app/strings/translations/content_strings_hr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hr.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">klizač</translation>
<translation id="1211441953136645838">završna napomena</translation>
<translation id="1281252709823657822">dijalog</translation>
-<translation id="1289247557029249093">Izlaz iz načina slike u slici</translation>
<translation id="1335095011850992622">zasluge</translation>
<translation id="1342835525016946179">članak</translation>
<translation id="1359897965706325498">natpis</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Danas</translation>
<translation id="2158401438286456825">popis stranica</translation>
<translation id="2226276347425096477">Skratite taj tekst na <ph name="MAX_CHARACTERS" /> znakova ili manje (trenutačno upotrebljavate <ph name="CURRENT_LENGTH" /> znakova).</translation>
+<translation id="2246498165605549352">Lokalna datoteka</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. tjedan, <ph name="YEAR" />. godina</translation>
<translation id="2277199496770840904">Zapis <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">potvrdni okvir</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Neoznačena slika</translation>
<translation id="3706100364254443312">prebaci</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Zatvori sliku u slici</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">pojam</translation>
<translation id="3822383571486410024">Produljite broj znakova u tekstu na minimalno <ph name="MIN_CHARACTERS" />. Trenutačno imate premalo znakova (<ph name="CURRENT_LENGTH" />).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">stablo</translation>
<translation id="4664250907885839816">Dio adrese iza znaka "<ph name="ATSIGN" />" ne smije sadržavati simbol "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">dodatak</translation>
+<translation id="4718048029184481307">Reproducira se u načinu slika u slici</translation>
<translation id="4742539557769756338">naslovnica</translation>
<translation id="4748357248530471599">prebacite urez na zaslonu u cijeli zaslon</translation>
<translation id="4757246831282535685">ploča kartice</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">pogovor</translation>
<translation id="6209276755895393898">Čini se da je to: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">pojmovnik</translation>
-<translation id="628938136236500310">Reproducira se u načinu slika u slici</translation>
+<translation id="6310801910862476708">Izlaz iz načina slika u slici</translation>
<translation id="6398862346408813489">Prikaži ploču za odabir mjeseca</translation>
<translation id="6404546809543547843">klizač vremena audiozapisa</translation>
<translation id="6443871981718447451">prikaži izbornik titlova</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_hu.xtb b/chromium/content/app/strings/translations/content_strings_hu.xtb
index d495dce010c..e67f09c45bc 100644
--- a/chromium/content/app/strings/translations/content_strings_hu.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hu.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">csúszka</translation>
<translation id="1211441953136645838">záró jegyzet</translation>
<translation id="1281252709823657822">párbeszédpanel</translation>
-<translation id="1289247557029249093">Kilépés a kép a képben módból</translation>
<translation id="1335095011850992622">készítők</translation>
<translation id="1342835525016946179">cikk</translation>
<translation id="1359897965706325498">szalaghirdetés</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Ma</translation>
<translation id="2158401438286456825">oldallista</translation>
<translation id="2226276347425096477">Kérjük, rövidítse le a szöveget legfeljebb <ph name="MAX_CHARACTERS" /> karakterre (jelenleg <ph name="CURRENT_LENGTH" /> karaktert használ).</translation>
+<translation id="2246498165605549352">Helyi fájl</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. hét, <ph name="YEAR" /></translation>
<translation id="2277199496770840904"><ph name="NUMBER" />. szám</translation>
<translation id="2291999235780842123">jelölőnégyzet</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Címke nélküli kép</translation>
<translation id="3706100364254443312">váltás</translation>
<translation id="3732799496749320381">hh</translation>
+<translation id="3754210790023674521">Kilépés a kép a képben módból</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">kifejezés</translation>
<translation id="3822383571486410024">Kérjük, <ph name="MIN_CHARACTERS" /> karakter hosszú vagy annál hosszabb szöveget adjon meg (jelenleg <ph name="CURRENT_LENGTH" /> karaktert használ).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">fa</translation>
<translation id="4664250907885839816">A „<ph name="ATSIGN" />” utáni rész nem tartalmazhat „<ph name="INVALIDCHARACTER" />” karaktert.</translation>
<translation id="4668956016107839909">függelék</translation>
+<translation id="4718048029184481307">Lejátszás kép a képben módban</translation>
<translation id="4742539557769756338">borító</translation>
<translation id="4748357248530471599">képernyőkivágás váltása teljes képernyőn</translation>
<translation id="4757246831282535685">lappanel</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">utószó</translation>
<translation id="6209276755895393898">Úgy tűnik, hogy a következőről van szó: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">szószedet</translation>
-<translation id="628938136236500310">Lejátszás kép a képben módban</translation>
+<translation id="6310801910862476708">Kilépés a kép a képben funkcióból</translation>
<translation id="6398862346408813489">A hónapválasztási panel megjelenítése</translation>
<translation id="6404546809543547843">hang idővonalának vezérlője</translation>
<translation id="6443871981718447451">a feliratok menü mutatása</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_id.xtb b/chromium/content/app/strings/translations/content_strings_id.xtb
index 5455029d973..c4435783f41 100644
--- a/chromium/content/app/strings/translations/content_strings_id.xtb
+++ b/chromium/content/app/strings/translations/content_strings_id.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">penggeser</translation>
<translation id="1211441953136645838">catatan akhir</translation>
<translation id="1281252709823657822">dialog</translation>
-<translation id="1289247557029249093">Keluar dari mode picture-in-picture</translation>
<translation id="1335095011850992622">daftar penghargaan</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">spanduk</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Hari ini</translation>
<translation id="2158401438286456825">daftar halaman</translation>
<translation id="2226276347425096477">Pendekkan teks ini menjadi <ph name="MAX_CHARACTERS" /> karakter atau kurang (saat ini Anda menggunakan <ph name="CURRENT_LENGTH" /> karakter).</translation>
+<translation id="2246498165605549352">File Lokal</translation>
<translation id="2247351761944213033">Minggu <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Lagu <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">kotak centang</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Gambar tidak berlabel</translation>
<translation id="3706100364254443312">saklar</translation>
<translation id="3732799496749320381">bb</translation>
+<translation id="3754210790023674521">Keluar dari mode picture-in-picture</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">istilah</translation>
<translation id="3822383571486410024">Perpanjang teks ini hingga <ph name="MIN_CHARACTERS" /> karakter atau lebih (saat ini Anda menggunakan <ph name="CURRENT_LENGTH" /> karakter).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Bagian setelah '<ph name="ATSIGN" />' tidak boleh berisi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="4668956016107839909">lampiran</translation>
+<translation id="4718048029184481307">Diputar dalam mode picture-in-picture</translation>
<translation id="4742539557769756338">sampul</translation>
<translation id="4748357248530471599">mengalihkan ke layar penuh potongan layar</translation>
<translation id="4757246831282535685">panel tab</translation>
@@ -130,7 +132,7 @@
<translation id="5537725057119320332">Cast</translation>
<translation id="5546461542133609677">suarakan</translation>
<translation id="561939826962581046">waktu</translation>
-<translation id="5630795885300617244">Tap dua kali ke kiri atau kanan untuk melewati 10 detik</translation>
+<translation id="5630795885300617244">Ketuk dua kali ke kiri atau kanan untuk melewati 10 detik</translation>
<translation id="5631759159893697722">abstrak</translation>
<translation id="5643186887447432888">tombol</translation>
<translation id="5677946354068040947">opsi lainnya</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">penutup</translation>
<translation id="6209276755895393898">Muncul sebagai: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glosarium</translation>
-<translation id="628938136236500310">Memutar dalam mode picture-in-picture</translation>
+<translation id="6310801910862476708">Keluar dari Mode Picture-in-Picture</translation>
<translation id="6398862346408813489">Tampilkan panel pilihan bulan</translation>
<translation id="6404546809543547843">scrubber waktu audio</translation>
<translation id="6443871981718447451">tampilkan menu subtitel</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_it.xtb b/chromium/content/app/strings/translations/content_strings_it.xtb
index 604a1117815..d3fa84f862f 100644
--- a/chromium/content/app/strings/translations/content_strings_it.xtb
+++ b/chromium/content/app/strings/translations/content_strings_it.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">dispositivo di scorrimento</translation>
<translation id="1211441953136645838">nota finale</translation>
<translation id="1281252709823657822">finestra di dialogo</translation>
-<translation id="1289247557029249093">Esci dalla modalità Picture-in-picture</translation>
<translation id="1335095011850992622">ringraziamenti</translation>
<translation id="1342835525016946179">articolo</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Oggi</translation>
<translation id="2158401438286456825">elenco pagine</translation>
<translation id="2226276347425096477">Riduci questo testo a <ph name="MAX_CHARACTERS" /> caratteri o meno (attualmente stai utilizzando <ph name="CURRENT_LENGTH" /> caratteri).</translation>
+<translation id="2246498165605549352">File locale</translation>
<translation id="2247351761944213033">Settimana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Traccia <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">casella di controllo</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">immagine senza etichetta</translation>
<translation id="3706100364254443312">strumento per il passaggio ad altri elementi</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Esci da Picture in picture</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">termine</translation>
<translation id="3822383571486410024">Prolunga questo testo a <ph name="MIN_CHARACTERS" /> o più caratteri (al momento stai utilizzando <ph name="CURRENT_LENGTH" /> caratteri).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Una parte che segue "<ph name="ATSIGN" />" non deve contenere il simbolo "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">appendice</translation>
+<translation id="4718048029184481307">Riproduzione in modalità Picture in picture</translation>
<translation id="4742539557769756338">copertina</translation>
<translation id="4748357248530471599">attiva/disattiva lo schermo intero tagliato dalla visualizzazione</translation>
<translation id="4757246831282535685">riquadro a schede</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">postfazione</translation>
<translation id="6209276755895393898">Sembra che sia: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glossario</translation>
-<translation id="628938136236500310">Riprodotto in modalità Picture in picture</translation>
+<translation id="6310801910862476708">Esci da Picture in picture</translation>
<translation id="6398862346408813489">Mostra il riquadro di selezione del mese</translation>
<translation id="6404546809543547843">dispositivo di scorrimento durata audio</translation>
<translation id="6443871981718447451">mostra menu sottotitoli</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_iw.xtb b/chromium/content/app/strings/translations/content_strings_iw.xtb
index 7badfe1f4bb..f43d6f11dd3 100644
--- a/chromium/content/app/strings/translations/content_strings_iw.xtb
+++ b/chromium/content/app/strings/translations/content_strings_iw.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">מחוון</translation>
<translation id="1211441953136645838">הערת סיום</translation>
<translation id="1281252709823657822">דו-שיח</translation>
-<translation id="1289247557029249093">יציאה ממצב 'תמונה בתוך תמונה'</translation>
<translation id="1335095011850992622">קרדיטים</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">מודעת באנר</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">היום</translation>
<translation id="2158401438286456825">רשימת דפים</translation>
<translation id="2226276347425096477">קצר טקסט זה ל-<ph name="MAX_CHARACTERS" /> תווים או פחות (אתה משתמש כעת ב-<ph name="CURRENT_LENGTH" /> תווים).</translation>
+<translation id="2246498165605549352">קובץ מקומי</translation>
<translation id="2247351761944213033">שבוע <ph name="WEEKNUMBER" />‏, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">רצועה <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">תיבת סימון</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">תמונה ללא תיאור</translation>
<translation id="3706100364254443312">מעבר</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">יציאה ממצב תמונה בתוך תמונה</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">מונח</translation>
<translation id="3822383571486410024">הארך טקסט זה ל-<ph name="MIN_CHARACTERS" /> תווים או יותר (אתה משתמש כרגע ב-<ph name="CURRENT_LENGTH" /> תווים).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">חלק ולאחריו '<ph name="ATSIGN" />' לא אמור לכלול את הסמל '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="4668956016107839909">נספח</translation>
+<translation id="4718048029184481307">הפעלה במצב תמונה בתוך תמונה</translation>
<translation id="4742539557769756338">שער</translation>
<translation id="4748357248530471599">מעבר מתצוגה באזור המגרעת של המסך למסך מלא</translation>
<translation id="4757246831282535685">חלונית כרטיסיות</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">אחרית דבר</translation>
<translation id="6209276755895393898">נראה כמו: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">מילון מונחים</translation>
-<translation id="628938136236500310">פועל במצב תמונה בתוך תמונה</translation>
+<translation id="6310801910862476708">יציאה ממצב 'תמונה בתוך תמונה'</translation>
<translation id="6398862346408813489">הצג חלונית לבחירת חודש</translation>
<translation id="6404546809543547843">מסתיר משך אודיו</translation>
<translation id="6443871981718447451">הצגת תפריט כתוביות</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ja.xtb b/chromium/content/app/strings/translations/content_strings_ja.xtb
index f846b79da14..e8451630393 100644
--- a/chromium/content/app/strings/translations/content_strings_ja.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ja.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">スライダ</translation>
<translation id="1211441953136645838">巻末注</translation>
<translation id="1281252709823657822">ダイアログ</translation>
-<translation id="1289247557029249093">ピクチャー イン ピクチャー モードを終了する</translation>
<translation id="1335095011850992622">クレジット</translation>
<translation id="1342835525016946179">記事</translation>
<translation id="1359897965706325498">バナー</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">今日</translation>
<translation id="2158401438286456825">ページリスト</translation>
<translation id="2226276347425096477">このテキストを半角 <ph name="MAX_CHARACTERS" /> 文字以下にしてください(現時点で半角 <ph name="CURRENT_LENGTH" /> 文字です)。</translation>
+<translation id="2246498165605549352">ローカル ファイル</translation>
<translation id="2247351761944213033"><ph name="YEAR" />年第<ph name="WEEKNUMBER" />週</translation>
<translation id="2277199496770840904">トラック <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">チェックボックス</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">ラベルのない画像</translation>
<translation id="3706100364254443312">切り替え</translation>
<translation id="3732799496749320381">月</translation>
+<translation id="3754210790023674521">ピクチャー イン ピクチャーを終了</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">用語</translation>
<translation id="3822383571486410024">このテキストは <ph name="MIN_CHARACTERS" /> 文字以上で指定してください(現在は <ph name="CURRENT_LENGTH" /> 文字です)。</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">ツリー</translation>
<translation id="4664250907885839816">「<ph name="ATSIGN" />」に続く文字列に記号「<ph name="INVALIDCHARACTER" />」を使用しないでください。</translation>
<translation id="4668956016107839909">付録</translation>
+<translation id="4718048029184481307">ピクチャー イン ピクチャーを再生しています</translation>
<translation id="4742539557769756338">表紙</translation>
<translation id="4748357248530471599">ディスプレイ カットアウトに合わせた全画面表示に切り替えます</translation>
<translation id="4757246831282535685">タブパネル</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">後書き</translation>
<translation id="6209276755895393898"><ph name="DESCRIPTION" /> の画像のようです</translation>
<translation id="6213469881011901533">用語集</translation>
-<translation id="628938136236500310">ピクチャー イン ピクチャー モードで再生しています</translation>
+<translation id="6310801910862476708">ピクチャー イン ピクチャーを終了</translation>
<translation id="6398862346408813489">月選択パネルを表示</translation>
<translation id="6404546809543547843">オーディオ再生バー</translation>
<translation id="6443871981718447451">字幕メニューを表示</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_kn.xtb b/chromium/content/app/strings/translations/content_strings_kn.xtb
index 3cb3e160960..4dfab24028a 100644
--- a/chromium/content/app/strings/translations/content_strings_kn.xtb
+++ b/chromium/content/app/strings/translations/content_strings_kn.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">ಸ್ಲೈಡರ್</translation>
<translation id="1211441953136645838">ಮುಕ್ತಾಯ ಟಿಪ್ಪಣಿ</translation>
<translation id="1281252709823657822">ಸಂವಾದ</translation>
-<translation id="1289247557029249093">ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರ ಮೋಡ್ ಅನ್ನು ನಿರ್ಗಮಿಸಿ</translation>
<translation id="1335095011850992622">ಕ್ರೆಡಿಟ್‌ಗಳು</translation>
<translation id="1342835525016946179">ಲೇಖನ</translation>
<translation id="1359897965706325498">ಬ್ಯಾನರ್</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">ಇಂದು</translation>
<translation id="2158401438286456825">ಪುಟ ಪಟ್ಟಿ</translation>
<translation id="2226276347425096477">ದಯವಿಟ್ಟು ಈ ಪಠ್ಯವನ್ನು <ph name="MAX_CHARACTERS" /> ಅಕ್ಷರಗಳಿಗೆ ಅಥವಾ ಅದಕ್ಕಿಂತಲೂ ಕಡಿಮೆಗೆ ಸೀಮಿತಗೊಳಿಸಿ (ನೀವು ಪ್ರಸ್ತುತ <ph name="CURRENT_LENGTH" /> ಅಕ್ಷರಗಳನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ).</translation>
+<translation id="2246498165605549352">ಸ್ಥಳೀಯ ಫೈಲ್</translation>
<translation id="2247351761944213033">ವಾರ <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ಟ್ರ್ಯಾಕ್ <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">ಚೆಕ್‌ಬಾಕ್ಸ್</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">ಲೇಬಲ್ ಮಾಡಿಲ್ಲದ ಚಿತ್ರ</translation>
<translation id="3706100364254443312">ಸ್ವಿಚ್</translation>
<translation id="3732799496749320381">ಮಿಮೀ</translation>
+<translation id="3754210790023674521">ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರ ಮೋಡ್‌ನಿಂದ ನಿರ್ಗಮಿಸಿ</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">ನಿಯಮ</translation>
<translation id="3822383571486410024">ಈ ಪಠ್ಯವನ್ನು <ph name="MIN_CHARACTERS" /> ಅಕ್ಷರಗಳಿಗೆ ಅಥವಾ ಅದಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಿಗೆ ಸೀಮಿತಗೊಳಿಸಿ (ನೀವು ಪ್ರಸ್ತುತವಾಗಿ <ph name="CURRENT_LENGTH" /> ಅಕ್ಷರಗಳನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">ಮರ</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ನಂತರದ ಭಾಗವು '<ph name="INVALIDCHARACTER" />' ಚಿಹ್ನೆಯನ್ನು ಒಳಗೊಂಡಿರಬಾರದು.</translation>
<translation id="4668956016107839909">ಅನುಬಂಧ</translation>
+<translation id="4718048029184481307">ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರ ಮೋಡ್‌ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲಾಗುತ್ತಿದೆ</translation>
<translation id="4742539557769756338">ಕವರ್</translation>
<translation id="4748357248530471599">ಡಿಸ್‌ಪ್ಲೇ ಕಟ್‌ಔಟ್ ಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಟಾಗಲ್ ಮಾಡಿ</translation>
<translation id="4757246831282535685">ಟ್ಯಾಬ್ ಫಲಕ</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">ನಂತರದ</translation>
<translation id="6209276755895393898">ಹೀಗೆ ಕಾಣಿಸುತ್ತಿದೆ: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">ಪದಕೋಶ</translation>
-<translation id="628938136236500310">ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರ ಮೋಡ್‌ನಲ್ಲಿ ಪ್ಲೇ ಆಗುತ್ತಿದೆ</translation>
+<translation id="6310801910862476708">ಚಿತ್ರದಲ್ಲಿನ ಚಿತ್ರದಿಂದ ನಿರ್ಗಮಿಸಿ</translation>
<translation id="6398862346408813489">ತಿಂಗಳ ಆಯ್ಕೆ ಪ್ಯಾನಲ್ ತೋರಿಸಿ</translation>
<translation id="6404546809543547843">ಆಡಿಯೊ ಸಮಯ ಸ್ಕ್ರಬ್ಬರ್</translation>
<translation id="6443871981718447451">ಮುಚ್ಚಿದ ಶೀರ್ಷಿಕೆಗಳ ಮೆನುವನ್ನು ತೋರಿಸಿ</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ko.xtb b/chromium/content/app/strings/translations/content_strings_ko.xtb
index 6c5c16ca6e8..a61796c24cb 100644
--- a/chromium/content/app/strings/translations/content_strings_ko.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ko.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">슬라이더</translation>
<translation id="1211441953136645838">미주</translation>
<translation id="1281252709823657822">대화상자</translation>
-<translation id="1289247557029249093">PIP 모드 종료</translation>
<translation id="1335095011850992622">저작권 표시</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">배너</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">오늘</translation>
<translation id="2158401438286456825">페이지 목록</translation>
<translation id="2226276347425096477">이 텍스트를 <ph name="MAX_CHARACTERS" />자 이하로 줄이세요(현재 <ph name="CURRENT_LENGTH" />자 사용 중).</translation>
+<translation id="2246498165605549352">로컬 파일</translation>
<translation id="2247351761944213033"><ph name="YEAR" />, <ph name="WEEKNUMBER" />번째 주</translation>
<translation id="2277199496770840904"><ph name="NUMBER" />번 트랙</translation>
<translation id="2291999235780842123">체크박스</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">라벨이 없는 이미지</translation>
<translation id="3706100364254443312">전환</translation>
<translation id="3732799496749320381">월</translation>
+<translation id="3754210790023674521">PIP 모드 종료</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" />GB</translation>
<translation id="3808586225841795776">용어</translation>
<translation id="3822383571486410024">이 텍스트를 <ph name="MIN_CHARACTERS" />자 이상으로 늘리세요(현재 <ph name="CURRENT_LENGTH" />자 사용 중).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' 다음 부분에 '<ph name="INVALIDCHARACTER" />' 기호가 포함되면 안됩니다.</translation>
<translation id="4668956016107839909">부록</translation>
+<translation id="4718048029184481307">PIP 모드에서 재생</translation>
<translation id="4742539557769756338">표지</translation>
<translation id="4748357248530471599">디스플레이 컷아웃을 전체화면으로 전환</translation>
<translation id="4757246831282535685">탭 패널</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">후기</translation>
<translation id="6209276755895393898"><ph name="DESCRIPTION" /> 같습니다</translation>
<translation id="6213469881011901533">용어설명</translation>
-<translation id="628938136236500310">PIP 모드로 재생 중</translation>
+<translation id="6310801910862476708">PIP 모드 종료</translation>
<translation id="6398862346408813489">월 선택 패널 표시</translation>
<translation id="6404546809543547843">오디오 시간 스크러버</translation>
<translation id="6443871981718447451">자막 메뉴 표시</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_lt.xtb b/chromium/content/app/strings/translations/content_strings_lt.xtb
index 6347a8a7ffd..a6eed4a8413 100644
--- a/chromium/content/app/strings/translations/content_strings_lt.xtb
+++ b/chromium/content/app/strings/translations/content_strings_lt.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">šliaužiklis</translation>
<translation id="1211441953136645838">išnaša</translation>
<translation id="1281252709823657822">dialogo langas</translation>
-<translation id="1289247557029249093">Išeiti iš vaizdo vaizde režimo</translation>
<translation id="1335095011850992622">titrai</translation>
<translation id="1342835525016946179">artikelis</translation>
<translation id="1359897965706325498">reklamjuostė</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Šiandien</translation>
<translation id="2158401438286456825">puslapių sąrašas</translation>
<translation id="2226276347425096477">Sutrumpinkite šį tekstą iki <ph name="MAX_CHARACTERS" /> simb. ar mažiau (šiuo metu naudojate <ph name="CURRENT_LENGTH" /> simb.).</translation>
+<translation id="2246498165605549352">Vietos failas</translation>
<translation id="2247351761944213033"><ph name="YEAR" /> m. <ph name="WEEKNUMBER" /> sav.</translation>
<translation id="2277199496770840904"><ph name="NUMBER" /> takelis</translation>
<translation id="2291999235780842123">žymimasis laukelis</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Nepažymėtas vaizdas</translation>
<translation id="3706100364254443312">jungiklis</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Išeiti iš vaizdo vaizde režimo</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">terminas</translation>
<translation id="3822383571486410024">Pailginkite šį tekstą iki <ph name="MIN_CHARACTERS" /> simb. ar daugiau (šiuo metu naudojate <ph name="CURRENT_LENGTH" /> simb.).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Po „<ph name="ATSIGN" />“ esančioje dalyje neturėtų būti simbolio „<ph name="INVALIDCHARACTER" />“.</translation>
<translation id="4668956016107839909">priedas</translation>
+<translation id="4718048029184481307">Leidžiama vaizdo vaizde režimu</translation>
<translation id="4742539557769756338">viršelis</translation>
<translation id="4748357248530471599">perjungti ekrano išpjovą į visą ekraną</translation>
<translation id="4757246831282535685">skirtuko skydelis</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">baigiamasis žodis</translation>
<translation id="6209276755895393898">Tai tikriausiai yra: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">aiškinamasis terminų žodynas</translation>
-<translation id="628938136236500310">Leidžiama vaizdo vaizde režimu</translation>
+<translation id="6310801910862476708">Išeiti iš vaizdo vaizde</translation>
<translation id="6398862346408813489">Rodyti mėnesio pasirinkimo skydelį</translation>
<translation id="6404546809543547843">garso laiko valdiklis</translation>
<translation id="6443871981718447451">rodyti subtitrų meniu</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_lv.xtb b/chromium/content/app/strings/translations/content_strings_lv.xtb
index 374f99a5aaf..61dd9ec9dea 100644
--- a/chromium/content/app/strings/translations/content_strings_lv.xtb
+++ b/chromium/content/app/strings/translations/content_strings_lv.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">slīdnis</translation>
<translation id="1211441953136645838">beigu vēre</translation>
<translation id="1281252709823657822">dialoglodziņš</translation>
-<translation id="1289247557029249093">Iziet no režīma “Attēls attēlā”</translation>
<translation id="1335095011850992622">pateicības</translation>
<translation id="1342835525016946179">raksts</translation>
<translation id="1359897965706325498">reklāmkarogs</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Šodien</translation>
<translation id="2158401438286456825">lapu saraksts</translation>
<translation id="2226276347425096477">Lūdzu, saīsiniet šo tekstu līdz <ph name="MAX_CHARACTERS" /> vai mazāk zīmēm (pašreiz tas ietver <ph name="CURRENT_LENGTH" /> rakstzīmes).</translation>
+<translation id="2246498165605549352">Lokāls fails</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. nedēļa, <ph name="YEAR" />. gads</translation>
<translation id="2277199496770840904"><ph name="NUMBER" />. ieraksts</translation>
<translation id="2291999235780842123">izvēles rūtiņa</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Attēls bez iezīmes</translation>
<translation id="3706100364254443312">slēdzis</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Iziet no režīma “Attēls attēlā”</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">vārds</translation>
<translation id="3822383571486410024">Lūdzu, papildiniet šo tekstu līdz vismaz <ph name="MIN_CHARACTERS" /> rakstzīmēm (pašlaik tas ietver <ph name="CURRENT_LENGTH" /> rakstzīmes).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">koks</translation>
<translation id="4664250907885839816">Daļā, kas atrodas aiz zīmes <ph name="ATSIGN" />, nedrīkst būt ietverts simbols <ph name="INVALIDCHARACTER" />.</translation>
<translation id="4668956016107839909">pielikums</translation>
+<translation id="4718048029184481307">Tiek atskaņots režīmā “Attēls attēlā”</translation>
<translation id="4742539557769756338">vāks</translation>
<translation id="4748357248530471599">pārslēdz displeja izgriezuma apgabalu pilnekrāna režīmā</translation>
<translation id="4757246831282535685">ciļņu panelis</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">pēcvārds</translation>
<translation id="6209276755895393898">Šķiet, ka tas ir: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glosārijs</translation>
-<translation id="628938136236500310">Tiek atskaņots režīmā “Attēls attēlā”</translation>
+<translation id="6310801910862476708">Aizvērt režīmu “Attēls attēlā”</translation>
<translation id="6398862346408813489">Rādīt mēneša atlases paneli</translation>
<translation id="6404546809543547843">audio laika skalas slīdnis</translation>
<translation id="6443871981718447451">rādīt slēgto parakstu izvēlni</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ml.xtb b/chromium/content/app/strings/translations/content_strings_ml.xtb
index 7b80031f7c4..8758eada7ff 100644
--- a/chromium/content/app/strings/translations/content_strings_ml.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ml.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">സ്ലൈഡർ</translation>
<translation id="1211441953136645838">അന്തിമ കുറിപ്പ്</translation>
<translation id="1281252709823657822">ഡയലോഗ്</translation>
-<translation id="1289247557029249093">ചിത്രത്തിനുള്ളിലെ ചിത്രം മോഡിന് പുറത്ത് കടക്കുക</translation>
<translation id="1335095011850992622">ക്രെഡിറ്റുകൾ</translation>
<translation id="1342835525016946179">ലേഖനം</translation>
<translation id="1359897965706325498">ബാനർ</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">ഇന്ന്</translation>
<translation id="2158401438286456825">പേജ് ലിസ്റ്റ്</translation>
<translation id="2226276347425096477">ഈ വാചകത്തെ <ph name="MAX_CHARACTERS" /> അല്ലെങ്കില്‍ അതില്‍‌ക്കുറവ് പ്രതീകങ്ങളായി ദയവായി കുറയ്ക്കുക (നിങ്ങള്‍ നിലവില്‍ <ph name="CURRENT_LENGTH" /> പ്രതീകങ്ങള്‍ ഉപയോഗിക്കുകയാണ്).</translation>
+<translation id="2246498165605549352">ലോക്കൽ ഫയൽ</translation>
<translation id="2247351761944213033">ആഴ്‌ച <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ട്രാക്ക് <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">ചെക്ക്‌ ബോക്‌സ്</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">ലേബൽ ചെയ്യാത്ത ചിത്രം</translation>
<translation id="3706100364254443312">സ്വിച്ച്</translation>
<translation id="3732799496749320381">മാസം</translation>
+<translation id="3754210790023674521">ചിത്രത്തിനുള്ളിലെ ചിത്രത്തിന് പുറത്ത് കടക്കുക</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">പദം</translation>
<translation id="3822383571486410024">ഈ ടെക്‌സ്റ്റിന്‍റെ ദൈർഘ്യം <ph name="MIN_CHARACTERS" /> അല്ലെങ്കിൽ അതിൽക്കൂടുതൽ പ്രതീകങ്ങൾ നൽകി കൂട്ടുക. (നിങ്ങൾ നിലവിൽ <ph name="CURRENT_LENGTH" /> പ്രതീകങ്ങളാണ് ഉപയോഗിക്കുന്നത്).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">ട്രീ</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' എന്നതിനുശേഷം വരുന്ന ഭാഗത്തിൽ '<ph name="INVALIDCHARACTER" />' ചിഹ്നം ഉണ്ടാകരുത്.</translation>
<translation id="4668956016107839909">അനുബന്ധം</translation>
+<translation id="4718048029184481307">ചിത്രത്തിനുള്ളിൽ ചിത്രത്തിൽ പ്ലേ ചെയ്യുന്നു</translation>
<translation id="4742539557769756338">കവർ</translation>
<translation id="4748357248530471599">ഡിസ്‌പ്ലേ കട്ടൗട്ട് പൂർണ്ണ സ്ക്രീൻ മാറ്റുക</translation>
<translation id="4757246831282535685">ടാബ് പാനൽ</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">പിൻ കുറിപ്പ്</translation>
<translation id="6209276755895393898">ഇങ്ങനെ ദൃശ്യമാകും: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">പദസഞ്ചയം</translation>
-<translation id="628938136236500310">ചിത്രത്തിനുള്ളിലെ ചിത്രം മോഡിൽ പ്ലേ ചെയ്യുന്നു</translation>
+<translation id="6310801910862476708">ചിത്രത്തിനുള്ളിലെ ചിത്രത്തിന് പുറത്ത് കടക്കുക</translation>
<translation id="6398862346408813489">മാസം തിരഞ്ഞെടുക്കുന്ന പാനൽ കാണിക്കുക</translation>
<translation id="6404546809543547843">ഓഡിയോ സമയ സ്‌ക്രബർ</translation>
<translation id="6443871981718447451">സബ്‌ടൈറ്റിൽ മെനു കാണിക്കുക</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_mr.xtb b/chromium/content/app/strings/translations/content_strings_mr.xtb
index 5afa1d4f006..486b34c461d 100644
--- a/chromium/content/app/strings/translations/content_strings_mr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_mr.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">स्लायडर</translation>
<translation id="1211441953136645838">तळटीप</translation>
<translation id="1281252709823657822">डायलॉग</translation>
-<translation id="1289247557029249093">चित्रात-चित्र मोडमधून बाहेर पडा</translation>
<translation id="1335095011850992622">श्रेय</translation>
<translation id="1342835525016946179">लेख</translation>
<translation id="1359897965706325498">बॅनर</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">आज</translation>
<translation id="2158401438286456825">पेज सूची</translation>
<translation id="2226276347425096477">कृपया हा मजकूर <ph name="MAX_CHARACTERS" /> वर्ण लहान किंवा कमी करा (तुम्ही सध्या <ph name="CURRENT_LENGTH" /> वर्ण वापरत आहात).</translation>
+<translation id="2246498165605549352">स्थानिक फाइल</translation>
<translation id="2247351761944213033">आठवडा <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ट्रॅक <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">चेकबॉक्‍स</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">लेबल न केलेली इमेज</translation>
<translation id="3706100364254443312">स्विच करा</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">चित्रात-चित्र मधून बाहेर पडा</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">संज्ञा</translation>
<translation id="3822383571486410024">कृपया हा मजकूर <ph name="MIN_CHARACTERS" /> वर्ण किंवा त्यापेक्षा अधिक मोठा करा (तुम्ही सध्‍या <ph name="CURRENT_LENGTH" /> वर्ण वापरत आहात).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' चे फॉलो करणार्‍या भागामध्ये '<ph name="INVALIDCHARACTER" />' चिन्ह नसावे.</translation>
<translation id="4668956016107839909">परिशिष्ट</translation>
+<translation id="4718048029184481307">चित्रात-चित्र मध्ये प्ले करत आहे</translation>
<translation id="4742539557769756338">कव्हर</translation>
<translation id="4748357248530471599">डिस्प्ले कटआउट फुलस्क्रीन टॉगल करा</translation>
<translation id="4757246831282535685">टॅब पॅनेल</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">अंतिम शब्द</translation>
<translation id="6209276755895393898">असे असल्याचे दिसत आहे: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">शब्दावली</translation>
-<translation id="628938136236500310">चित्रात-चित्र मोडमध्ये प्ले करत आहे</translation>
+<translation id="6310801910862476708">चित्रात-चित्र मधून बाहेर पडा</translation>
<translation id="6398862346408813489">महिना निवड पॅनेल दाखवा</translation>
<translation id="6404546809543547843">ऑडिओ वेळ स्क्रबर</translation>
<translation id="6443871981718447451">सबटायटल मेनू दाखवा</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ms.xtb b/chromium/content/app/strings/translations/content_strings_ms.xtb
index a5383d6b0d1..1a469fd7dae 100644
--- a/chromium/content/app/strings/translations/content_strings_ms.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ms.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">peluncur</translation>
<translation id="1211441953136645838">nota hujung</translation>
<translation id="1281252709823657822">dialog</translation>
-<translation id="1289247557029249093">Keluar daripada mod gambar dalam gambar</translation>
<translation id="1335095011850992622">kredit</translation>
<translation id="1342835525016946179">artikel</translation>
<translation id="1359897965706325498">sepanduk</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Hari ini</translation>
<translation id="2158401438286456825">senarai halaman</translation>
<translation id="2226276347425096477">Sila pendekkan teks ini menjadi <ph name="MAX_CHARACTERS" /> aksara atau kurang (anda kini menggunakan <ph name="CURRENT_LENGTH" /> aksara).</translation>
+<translation id="2246498165605549352">Fail Setempat</translation>
<translation id="2247351761944213033">Minggu <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Lagu <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">kotak pilihan</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Imej tidak berlabel</translation>
<translation id="3706100364254443312">tukar</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Keluar daripada gambar dalam gambar</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">istilah</translation>
<translation id="3822383571486410024">Sila panjangkan teks ini kepada <ph name="MIN_CHARACTERS" /> aksara atau lebih (anda sedang menggunakan <ph name="CURRENT_LENGTH" /> aksara).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">pohon</translation>
<translation id="4664250907885839816">Bahagian selepas '<ph name="ATSIGN" />' tidak boleh mengandungi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="4668956016107839909">lampiran</translation>
+<translation id="4718048029184481307">Memainkan video dalam gambar dalam gambar</translation>
<translation id="4742539557769756338">muka depan</translation>
<translation id="4748357248530471599">togol skrin penuh potongan paparan</translation>
<translation id="4757246831282535685">panel tab</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">kata hujungan</translation>
<translation id="6209276755895393898">Nampak seperti: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glosari</translation>
-<translation id="628938136236500310">Memainkan dalam mod gambar dalam gambar</translation>
+<translation id="6310801910862476708">Keluar daripada Gambar dalam Gambar</translation>
<translation id="6398862346408813489">Tunjukkan panel pilihan bulan</translation>
<translation id="6404546809543547843">pembersih masa audio</translation>
<translation id="6443871981718447451">tunjukkan menu sari kata</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_nl.xtb b/chromium/content/app/strings/translations/content_strings_nl.xtb
index ea67aa8ba0d..e4e825695ae 100644
--- a/chromium/content/app/strings/translations/content_strings_nl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_nl.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">schuifregelaar</translation>
<translation id="1211441953136645838">eindnoot</translation>
<translation id="1281252709823657822">dialoogvenster</translation>
-<translation id="1289247557029249093">Scherm-in-scherm-modus afsluiten</translation>
<translation id="1335095011850992622">bronvermelding</translation>
<translation id="1342835525016946179">artikel</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Vandaag</translation>
<translation id="2158401438286456825">paginalijst</translation>
<translation id="2226276347425096477">Kort deze tekst in tot <ph name="MAX_CHARACTERS" /> tekens of minder (je gebruikt momenteel <ph name="CURRENT_LENGTH" /> tekens).</translation>
+<translation id="2246498165605549352">Lokaal bestand</translation>
<translation id="2247351761944213033">Week <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Track <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">selectievakje</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Ongelabelde afbeelding</translation>
<translation id="3706100364254443312">schakelaar</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Scherm-in-scherm afsluiten</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">term</translation>
<translation id="3822383571486410024">Breid deze tekst uit tot <ph name="MIN_CHARACTERS" /> tekens of meer (je gebruikt momenteel <ph name="CURRENT_LENGTH" /> tekens).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">structuur</translation>
<translation id="4664250907885839816">Het adresgedeelte na '<ph name="ATSIGN" />' mag niet het teken '<ph name="INVALIDCHARACTER" />' bevatten.</translation>
<translation id="4668956016107839909">bijlage</translation>
+<translation id="4718048029184481307">Beeld-in-beeld afspelen</translation>
<translation id="4742539557769756338">omslag</translation>
<translation id="4748357248530471599">volledig scherm met display-cutout schakelen</translation>
<translation id="4757246831282535685">deelvenster met tabblad</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">nawoord</translation>
<translation id="6209276755895393898">Lijkt het volgende te zijn: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">woordenlijst</translation>
-<translation id="628938136236500310">Afspelen in scherm-in-scherm-modus</translation>
+<translation id="6310801910862476708">Scherm-in-scherm afsluiten</translation>
<translation id="6398862346408813489">Deelvenster voor maandselectie weergeven</translation>
<translation id="6404546809543547843">scrollbar met audiotijd</translation>
<translation id="6443871981718447451">ondertitelingsmenu weergeven</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_no.xtb b/chromium/content/app/strings/translations/content_strings_no.xtb
index c88080407a0..fd04f85ff10 100644
--- a/chromium/content/app/strings/translations/content_strings_no.xtb
+++ b/chromium/content/app/strings/translations/content_strings_no.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">glidebryter</translation>
<translation id="1211441953136645838">sluttnote</translation>
<translation id="1281252709823657822">dialog</translation>
-<translation id="1289247557029249093">Avslutt bilde-i-bilde-modus</translation>
<translation id="1335095011850992622">anerkjennelser</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">I dag</translation>
<translation id="2158401438286456825">sideliste</translation>
<translation id="2226276347425096477">Forkort denne teksten til <ph name="MAX_CHARACTERS" /> tegn eller færre (for øyeblikket bruker du <ph name="CURRENT_LENGTH" /> tegn).</translation>
+<translation id="2246498165605549352">Lokal fil</translation>
<translation id="2247351761944213033">Uke <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Spor <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">avmerkingsboks</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Umerket bilde</translation>
<translation id="3706100364254443312">bryter</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Avslutt bilde-i-bilde</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">term</translation>
<translation id="3822383571486410024">Du må forlenge denne teksten til <ph name="MIN_CHARACTERS" /> tegn eller mer (for øyeblikket bruker du <ph name="CURRENT_LENGTH" /> tegn).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">En del etterfulgt av «<ph name="ATSIGN" />» kan ikke inneholde symbolet «<ph name="INVALIDCHARACTER" />».</translation>
<translation id="4668956016107839909">vedlegg</translation>
+<translation id="4718048029184481307">Spiller av i bilde-i-bilde</translation>
<translation id="4742539557769756338">omslag</translation>
<translation id="4748357248530471599">slå av/på fullskjermsvisning av skjermutklipp</translation>
<translation id="4757246831282535685">fanepanel</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">etterord</translation>
<translation id="6209276755895393898">Dette ser ut til å være <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">ordliste</translation>
-<translation id="628938136236500310">Spilles av i bilde-i-bilde-modus</translation>
+<translation id="6310801910862476708">Avslutt bilde-i-bilde</translation>
<translation id="6398862346408813489">Se panelet for valg av måned</translation>
<translation id="6404546809543547843">lydtidslinje</translation>
<translation id="6443871981718447451">vis menyen for teksting for hørselshemmede</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_pl.xtb b/chromium/content/app/strings/translations/content_strings_pl.xtb
index 5aa0f5ca0aa..6d4fef4cce1 100644
--- a/chromium/content/app/strings/translations/content_strings_pl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pl.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">suwak</translation>
<translation id="1211441953136645838">przypis końcowy</translation>
<translation id="1281252709823657822">okno dialogowe</translation>
-<translation id="1289247557029249093">Wyłącz tryb obrazu w obrazie</translation>
<translation id="1335095011850992622">autorzy</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">baner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Dzisiaj</translation>
<translation id="2158401438286456825">lista stron</translation>
<translation id="2226276347425096477">Skróć ten tekst do maksymalnie <ph name="MAX_CHARACTERS" /> znaków (w tej chwili korzystasz z <ph name="CURRENT_LENGTH" /> znaków).</translation>
+<translation id="2246498165605549352">Plik lokalny</translation>
<translation id="2247351761944213033">Tydzień <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Utwór <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">pole wyboru</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Obraz bez etykiety</translation>
<translation id="3706100364254443312">przełącznik</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Wyłącz tryb obrazu w obrazie</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">termin</translation>
<translation id="3822383571486410024">Wydłuż ten tekst przynajmniej do <ph name="MIN_CHARACTERS" /> znaków (teraz używasz <ph name="CURRENT_LENGTH" /> znaków).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Część po znaku „<ph name="ATSIGN" />” nie może zawierać symbolu „<ph name="INVALIDCHARACTER" />”.</translation>
<translation id="4668956016107839909">dodatek</translation>
+<translation id="4718048029184481307">Odtwarzam w trybie obrazu w obrazie</translation>
<translation id="4742539557769756338">okładka</translation>
<translation id="4748357248530471599">przełącz z wycięcia w ekranie na tryb pełnoekranowy</translation>
<translation id="4757246831282535685">panel karty</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">posłowie</translation>
<translation id="6209276755895393898">Wygląda jak: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">słownik</translation>
-<translation id="628938136236500310">Odtwarzanie w trybie obrazu w obrazie</translation>
+<translation id="6310801910862476708">Wyłącz tryb obrazu w obrazie</translation>
<translation id="6398862346408813489">Pokaż panel wyboru miesiąca</translation>
<translation id="6404546809543547843">pasek czasu odtwarzania dźwięku</translation>
<translation id="6443871981718447451">wyświetlanie menu napisów</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_pt-BR.xtb b/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
index 243e041c8ee..dde5e251fbc 100644
--- a/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">controle deslizante</translation>
<translation id="1211441953136645838">nota final</translation>
<translation id="1281252709823657822">caixa de diálogo</translation>
-<translation id="1289247557029249093">Sair do modo picture-in-picture</translation>
<translation id="1335095011850992622">créditos</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Hoje</translation>
<translation id="2158401438286456825">lista de páginas</translation>
<translation id="2226276347425096477">Reduza este texto para <ph name="MAX_CHARACTERS" /> caracteres ou menos (você está usando <ph name="CURRENT_LENGTH" /> caracteres).</translation>
+<translation id="2246498165605549352">Arquivo local</translation>
<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Faixa <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">caixa de seleção</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Imagem sem etiqueta</translation>
<translation id="3706100364254443312">alternar</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Sair do modo picture-in-picture</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">termo</translation>
<translation id="3822383571486410024">Aumente este texto para <ph name="MIN_CHARACTERS" /> caracteres ou mais. No momento, você está usando <ph name="CURRENT_LENGTH" /> caracteres).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">A parte depois de "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">apêndice</translation>
+<translation id="4718048029184481307">Vídeo no modo picture-in-picture</translation>
<translation id="4742539557769756338">capa</translation>
<translation id="4748357248530471599">ativa tela cheia com corte de tela</translation>
<translation id="4757246831282535685">painel da guia</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">posfácio</translation>
<translation id="6209276755895393898">Parece ser: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glossário</translation>
-<translation id="628938136236500310">Vídeo aberto no modo picture-in-picture</translation>
+<translation id="6310801910862476708">Sair de picture-in-picture</translation>
<translation id="6398862346408813489">Mostrar painel de seleção de mês</translation>
<translation id="6404546809543547843">barra de progressão do áudio</translation>
<translation id="6443871981718447451">mostrar menu de closed captions</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_pt-PT.xtb b/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
index 51e7d9db844..156f99f3b19 100644
--- a/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">controlo de deslize</translation>
<translation id="1211441953136645838">nota final</translation>
<translation id="1281252709823657822">caixa de diálogo</translation>
-<translation id="1289247557029249093">Sair do modo ecrã no ecrã</translation>
<translation id="1335095011850992622">créditos</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Hoje</translation>
<translation id="2158401438286456825">lista de páginas</translation>
<translation id="2226276347425096477">Encurte este texto para <ph name="MAX_CHARACTERS" /> caracteres ou menos (está atualmente a utilizar <ph name="CURRENT_LENGTH" /> caracteres).</translation>
+<translation id="2246498165605549352">Ficheiro local</translation>
<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, de <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Faixa <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">caixa de verificação</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Imagem sem etiqueta</translation>
<translation id="3706100364254443312">alternar</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Sair de ecrã no ecrã</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">termo</translation>
<translation id="3822383571486410024">Aumente este texto para <ph name="MIN_CHARACTERS" /> carateres ou mais (está atualmente a utilizar <ph name="CURRENT_LENGTH" /> carateres).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">árvore</translation>
<translation id="4664250907885839816">Uma parte a seguir a "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">apêndice</translation>
+<translation id="4718048029184481307">A reproduzir em ecrã no ecrã…</translation>
<translation id="4742539557769756338">capa</translation>
<translation id="4748357248530471599">ativar/desativar o ecrã inteiro de recorte no ecrã</translation>
<translation id="4757246831282535685">painel de separadores</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">posfácio</translation>
<translation id="6209276755895393898">Parece ser: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glossário</translation>
-<translation id="628938136236500310">Em reprodução no modo ecrã no ecrã</translation>
+<translation id="6310801910862476708">Sair do modo ecrã no ecrã</translation>
<translation id="6398862346408813489">Mostrar painel de seleção do mês</translation>
<translation id="6404546809543547843">controlo de arrasto do tempo do áudio</translation>
<translation id="6443871981718447451">mostrar menu de legendas ocultas</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ro.xtb b/chromium/content/app/strings/translations/content_strings_ro.xtb
index 27ee4ee1802..4ee897bc2d0 100644
--- a/chromium/content/app/strings/translations/content_strings_ro.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ro.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">glisor</translation>
<translation id="1211441953136645838">notă de final</translation>
<translation id="1281252709823657822">dialog</translation>
-<translation id="1289247557029249093">Ieși din modul picture-in-picture</translation>
<translation id="1335095011850992622">mulțumiri</translation>
<translation id="1342835525016946179">articol</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Astăzi</translation>
<translation id="2158401438286456825">listă de pagini</translation>
<translation id="2226276347425096477">Micșorează acest text la cel mult <ph name="MAX_CHARACTERS" /> caractere (în prezent utilizezi <ph name="CURRENT_LENGTH" /> caractere).</translation>
+<translation id="2246498165605549352">Fișier local</translation>
<translation id="2247351761944213033">Săptămâna <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Melodia <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">casetă de selectare</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Imagine neetichetată</translation>
<translation id="3706100364254443312">comutator</translation>
<translation id="3732799496749320381">ll</translation>
+<translation id="3754210790023674521">Ieși din modul picture-in-picture</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">termen</translation>
<translation id="3822383571486410024">Mărește acest text la cel puțin <ph name="MIN_CHARACTERS" /> caractere (în prezent folosești <ph name="CURRENT_LENGTH" /> caractere).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">arbore</translation>
<translation id="4664250907885839816">Valoarea care urmează după semnul „<ph name="ATSIGN" />” nu trebuie să conțină simbolul „<ph name="INVALIDCHARACTER" />”.</translation>
<translation id="4668956016107839909">anexă</translation>
+<translation id="4718048029184481307">Se redă în modul picture-in-picture</translation>
<translation id="4742539557769756338">copertă</translation>
<translation id="4748357248530471599">decupaj inclus în ecranul complet</translation>
<translation id="4757246831282535685">panou de file</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">postfață</translation>
<translation id="6209276755895393898">Pare a fi: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glosar</translation>
-<translation id="628938136236500310">Se redă în modul picture-in-picture</translation>
+<translation id="6310801910862476708">Ieși din modul Picture-in-Picture</translation>
<translation id="6398862346408813489">Afișează panoul de selectare a lunii</translation>
<translation id="6404546809543547843">glisor redare audio</translation>
<translation id="6443871981718447451">afișează meniul de subtitrări</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ru.xtb b/chromium/content/app/strings/translations/content_strings_ru.xtb
index bed31bb2089..d4b3bac0d8a 100644
--- a/chromium/content/app/strings/translations/content_strings_ru.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ru.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">ползунок</translation>
<translation id="1211441953136645838">концевая сноска</translation>
<translation id="1281252709823657822">диалоговое окно</translation>
-<translation id="1289247557029249093">Выйти из режима "Картинка в картинке"</translation>
<translation id="1335095011850992622">выходные сведения</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">баннер</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Сегодня</translation>
<translation id="2158401438286456825">список страниц</translation>
<translation id="2226276347425096477">Длина текста не должна превышать <ph name="MAX_CHARACTERS" /> симв. (сейчас <ph name="CURRENT_LENGTH" /> симв.).</translation>
+<translation id="2246498165605549352">Локальный файл</translation>
<translation id="2247351761944213033">Неделя <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Трек <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">флажок</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Изображение без описания</translation>
<translation id="3706100364254443312">переключить</translation>
<translation id="3732799496749320381">мм</translation>
+<translation id="3754210790023674521">Выйти из режима "Картинка в картинке"</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> ГБ</translation>
<translation id="3808586225841795776">запрос</translation>
<translation id="3822383571486410024">Минимально допустимое количество символов: <ph name="MIN_CHARACTERS" />. Длина текста сейчас: <ph name="CURRENT_LENGTH" />.</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Часть адреса после символа "<ph name="ATSIGN" />" не должна содержать символ "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">приложение</translation>
+<translation id="4718048029184481307">Воспроизведение в режиме "Картинка в картинке"</translation>
<translation id="4742539557769756338">обложка</translation>
<translation id="4748357248530471599">Переключить вырезанную область на полный экран</translation>
<translation id="4757246831282535685">панель вкладок</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">послесловие</translation>
<translation id="6209276755895393898">Кажется, это "<ph name="DESCRIPTION" />"</translation>
<translation id="6213469881011901533">словарь</translation>
-<translation id="628938136236500310">Воспроизведение в режиме "Картинка в картинке"</translation>
+<translation id="6310801910862476708">Выйти из режима "Картинка в картинке"</translation>
<translation id="6398862346408813489">Показать панель выбора месяца</translation>
<translation id="6404546809543547843">полоса воспроизведения</translation>
<translation id="6443871981718447451">показать меню субтитров</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sk.xtb b/chromium/content/app/strings/translations/content_strings_sk.xtb
index 8a3993f4e0a..9347c54e7e7 100644
--- a/chromium/content/app/strings/translations/content_strings_sk.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sk.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">posúvač</translation>
<translation id="1211441953136645838">vysvetlivka</translation>
<translation id="1281252709823657822">dialóg</translation>
-<translation id="1289247557029249093">Ukončiť režim obraz v obraze</translation>
<translation id="1335095011850992622">titulky</translation>
<translation id="1342835525016946179">článok</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Dnes</translation>
<translation id="2158401438286456825">zoznam strán</translation>
<translation id="2226276347425096477">Tento text musíte skrátiť na <ph name="MAX_CHARACTERS" /> znakov alebo menej (súčasný počet znakov: <ph name="CURRENT_LENGTH" />).</translation>
+<translation id="2246498165605549352">Miestny súbor</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. týždeň, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Skladba <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">začiarkavacie políčko</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Neoznačený obrázok</translation>
<translation id="3706100364254443312">prepínač</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Ukončiť obraz v obraze</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">výraz</translation>
<translation id="3822383571486410024">Predĺžte tento text aspoň na <ph name="MIN_CHARACTERS" /> alebo viac znakov (momentálny počet znakov je <ph name="CURRENT_LENGTH" />).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">strom</translation>
<translation id="4664250907885839816">Časť za znakom <ph name="ATSIGN" /> by nemala obsahovať symbol <ph name="INVALIDCHARACTER" />.</translation>
<translation id="4668956016107839909">príloha</translation>
+<translation id="4718048029184481307">Prehráva sa v režime obrazu v obraze</translation>
<translation id="4742539557769756338">titulná strana</translation>
<translation id="4748357248530471599">prepnúť výrez obrazovky na celú obrazovku</translation>
<translation id="4757246831282535685">panel karty</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">doslov</translation>
<translation id="6209276755895393898">Zrejme to bude: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glosár</translation>
-<translation id="628938136236500310">Prehráva sa v režime obraz v obraze</translation>
+<translation id="6310801910862476708">Ukončiť obraz v obraze</translation>
<translation id="6398862346408813489">Zobraziť panel na výber mesiaca</translation>
<translation id="6404546809543547843">posúvač časovej osi zvuku</translation>
<translation id="6443871981718447451">zobraziť ponuku skrytých titulkov</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sl.xtb b/chromium/content/app/strings/translations/content_strings_sl.xtb
index e3cb0b8f192..302b23034c5 100644
--- a/chromium/content/app/strings/translations/content_strings_sl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sl.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">drsnik</translation>
<translation id="1211441953136645838">končna opomba</translation>
<translation id="1281252709823657822">pogovorno okno</translation>
-<translation id="1289247557029249093">Zapri način slike v sliki</translation>
<translation id="1335095011850992622">seznam sodelujočih</translation>
<translation id="1342835525016946179">člnk</translation>
<translation id="1359897965706325498">pasica</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Danes</translation>
<translation id="2158401438286456825">seznam strani</translation>
<translation id="2226276347425096477">Skrajšajte to besedilo na <ph name="MAX_CHARACTERS" /> znakov ali manj (trenutno uporabljate <ph name="CURRENT_LENGTH" /> znakov).</translation>
+<translation id="2246498165605549352">Lokalna datoteka</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. teden, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Besedilni posnetek <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">potrditveno polje</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Neoznačena slika</translation>
<translation id="3706100364254443312">preklop</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Zapri način slike v sliki</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">izraz</translation>
<translation id="3822383571486410024">Podaljšajte to besedilo na toliko znakov ali več: <ph name="MIN_CHARACTERS" /> (trenutno uporabljate toliko znakov: <ph name="CURRENT_LENGTH" />).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">drevo</translation>
<translation id="4664250907885839816">Del po »<ph name="ATSIGN" />« ne sme vsebovati znaka »<ph name="INVALIDCHARACTER" />«.</translation>
<translation id="4668956016107839909">dodatek</translation>
+<translation id="4718048029184481307">Predvajanje v načinu slike v sliki</translation>
<translation id="4742539557769756338">naslovnica</translation>
<translation id="4748357248530471599">preklop celozaslonskega načina na zarezo zaslona</translation>
<translation id="4757246831282535685">podokno z zavihki</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">spremna beseda</translation>
<translation id="6209276755895393898">Videti je kot: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">glosar</translation>
-<translation id="628938136236500310">Predvajanje v načinu slike v sliki</translation>
+<translation id="6310801910862476708">Zapri način slike v sliki</translation>
<translation id="6398862346408813489">Prikaz podokna za izbiro meseca</translation>
<translation id="6404546809543547843">časovni krmilnik za predvajanje zvoka</translation>
<translation id="6443871981718447451">pokaži meni s podnapisi</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sr.xtb b/chromium/content/app/strings/translations/content_strings_sr.xtb
index 373eb0a128a..ced5853f9ba 100644
--- a/chromium/content/app/strings/translations/content_strings_sr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sr.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">клизач</translation>
<translation id="1211441953136645838">завршна напомена</translation>
<translation id="1281252709823657822">дијалог</translation>
-<translation id="1289247557029249093">Изађи из режима слике у слици</translation>
<translation id="1335095011850992622">заслуге</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">банер</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Данас</translation>
<translation id="2158401438286456825">листа страница</translation>
<translation id="2226276347425096477">Скратите овај текст на <ph name="MAX_CHARACTERS" /> знак(ов)а или мање (тренутно користите <ph name="CURRENT_LENGTH" /> знак(ов)а).</translation>
+<translation id="2246498165605549352">Локална датотека</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. недеља, <ph name="YEAR" />.</translation>
<translation id="2277199496770840904"><ph name="NUMBER" />. песма</translation>
<translation id="2291999235780842123">поље за потврду</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Неозначена слика</translation>
<translation id="3706100364254443312">прекидач</translation>
<translation id="3732799496749320381">мм</translation>
+<translation id="3754210790023674521">Изађи из режима слике у слици</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">термин</translation>
<translation id="3822383571486410024">Продужите овај текст на <ph name="MIN_CHARACTERS" /> знак(ов)а или више (тренутно користите <ph name="CURRENT_LENGTH" /> знак(ов)а).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">стабло</translation>
<translation id="4664250907885839816">Део после „<ph name="ATSIGN" />“ не треба да садржи симбол „<ph name="INVALIDCHARACTER" />“.</translation>
<translation id="4668956016107839909">додатак</translation>
+<translation id="4718048029184481307">Репродукује се у режиму слике у слици</translation>
<translation id="4742539557769756338">корицe</translation>
<translation id="4748357248530471599">укључи/искључи цео екран без области изрезаног приказа</translation>
<translation id="4757246831282535685">табла са картицама</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">поговор</translation>
<translation id="6209276755895393898">Изгледа да је ово: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">речник термина</translation>
-<translation id="628938136236500310">Пуштање у режиму Слика у слици</translation>
+<translation id="6310801910862476708">Изађи из режима слике у слици</translation>
<translation id="6398862346408813489">Прикажи таблу за избор месеца</translation>
<translation id="6404546809543547843">клизач за трајање аудио-садржаја</translation>
<translation id="6443871981718447451">прикажите мени опционалног титла</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sv.xtb b/chromium/content/app/strings/translations/content_strings_sv.xtb
index c9130d10896..45a8eb12e6c 100644
--- a/chromium/content/app/strings/translations/content_strings_sv.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sv.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">skjutreglage</translation>
<translation id="1211441953136645838">slutnot</translation>
<translation id="1281252709823657822">dialogruta</translation>
-<translation id="1289247557029249093">Avsluta bild-i-bild-läge</translation>
<translation id="1335095011850992622">medverkande</translation>
<translation id="1342835525016946179">artikel</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Idag</translation>
<translation id="2158401438286456825">sidlista</translation>
<translation id="2226276347425096477">Förkorta texten till <ph name="MAX_CHARACTERS" /> tecken eller mindre (nu är texten <ph name="CURRENT_LENGTH" /> tecken).</translation>
+<translation id="2246498165605549352">Lokal fil</translation>
<translation id="2247351761944213033">Vecka <ph name="WEEKNUMBER" /> <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Spår <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">kryssruta</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Bild utan etikett</translation>
<translation id="3706100364254443312">växel</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Avsluta bild-i-bild-läge</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">term</translation>
<translation id="3822383571486410024">Lägg till minst <ph name="MIN_CHARACTERS" /> tecken (för närvarande har du angett <ph name="CURRENT_LENGTH" /> tecken).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">träd</translation>
<translation id="4664250907885839816">En del efter <ph name="ATSIGN" /> får inte innehålla symbolen <ph name="INVALIDCHARACTER" />.</translation>
<translation id="4668956016107839909">bilaga</translation>
+<translation id="4718048029184481307">Spelas upp i bild-i-bild-läge</translation>
<translation id="4742539557769756338">omslag</translation>
<translation id="4748357248530471599">aktivera och inaktivera skärmutskärning i helskärm</translation>
<translation id="4757246831282535685">flikpanel</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">efterord</translation>
<translation id="6209276755895393898">Det verkar vara: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">ordlista</translation>
-<translation id="628938136236500310">Spelar upp i bild-i-bild-läge</translation>
+<translation id="6310801910862476708">Avsluta bild-i-bild-läge</translation>
<translation id="6398862346408813489">Visa panelen för val av månad</translation>
<translation id="6404546809543547843">tidsreglage för ljud</translation>
<translation id="6443871981718447451">visa textningsmenyn</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sw.xtb b/chromium/content/app/strings/translations/content_strings_sw.xtb
index 1ec88570f4c..e5162b7c95f 100644
--- a/chromium/content/app/strings/translations/content_strings_sw.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sw.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">kitelezi</translation>
<translation id="1211441953136645838">maelezo ya mwisho wa kitabu</translation>
<translation id="1281252709823657822">kidirisha</translation>
-<translation id="1289247557029249093">Funga hali ya picha ndani ya picha</translation>
<translation id="1335095011850992622">walioshiriki</translation>
<translation id="1342835525016946179">makala</translation>
<translation id="1359897965706325498">bango</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Leo</translation>
<translation id="2158401438286456825">orodha ya kurasa</translation>
<translation id="2226276347425096477">Tafadhali fupisha maandishi haya hadi vibambo <ph name="MAX_CHARACTERS" /> au chini (kwa sasa unatumia vibambo <ph name="CURRENT_LENGTH" /> ).</translation>
+<translation id="2246498165605549352">Faili ya Ndani</translation>
<translation id="2247351761944213033">Wiki <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Wimbo wa <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">kisanduku cha kuteua</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Picha isiyo na lebo</translation>
<translation id="3706100364254443312">badilisha</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Funga hali ya picha ndani ya picha</translation>
<translation id="3757388668994797779">GB <ph name="QUANTITY" /></translation>
<translation id="3808586225841795776">neno</translation>
<translation id="3822383571486410024">Tafadhali refusha maandishi haya hadi herufi <ph name="MIN_CHARACTERS" /> au zaidi (kwa sasa unatumia herufi <ph name="CURRENT_LENGTH" />).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">mti</translation>
<translation id="4664250907885839816">Sehemu inayofuata '<ph name="ATSIGN" />' haipaswi kuwa na alama ya '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="4668956016107839909">kiambatisho</translation>
+<translation id="4718048029184481307">Inacheza katika hali ya picha ndani ya picha</translation>
<translation id="4742539557769756338">jalada</translation>
<translation id="4748357248530471599">tumia mkato kwenye skrini nzima</translation>
<translation id="4757246831282535685">kisanduku cha kichupo</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">maelezo kuhusu kitabu</translation>
<translation id="6209276755895393898">Inaonekana kuwa: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">faharasa</translation>
-<translation id="628938136236500310">Video inacheza katika hali ya picha ndani ya picha</translation>
+<translation id="6310801910862476708">Funga hali ya Picha ndani ya Picha</translation>
<translation id="6398862346408813489">Onyesha kisanduku cha uchaguzi wa mwezi</translation>
<translation id="6404546809543547843">kitelezi cha muda cha sauti</translation>
<translation id="6443871981718447451">kuonyesha menyu ya manukuu</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ta.xtb b/chromium/content/app/strings/translations/content_strings_ta.xtb
index 014379f437d..2681543ae78 100644
--- a/chromium/content/app/strings/translations/content_strings_ta.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ta.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">ஸ்லைடர்</translation>
<translation id="1211441953136645838">முடிவுக்குறிப்பு</translation>
<translation id="1281252709823657822">உரையாடல்</translation>
-<translation id="1289247557029249093">பிக்ச்சர்-இன்-பிக்ச்சர் பயன்முறையிலிருந்து வெளியேறு</translation>
<translation id="1335095011850992622">பங்களித்தவர்கள்</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">பேனர்</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">இன்று</translation>
<translation id="2158401438286456825">பக்கப் பட்டியல்</translation>
<translation id="2226276347425096477">இந்த உரையை <ph name="MAX_CHARACTERS" /> எழுத்துக்குறிகள் அல்லது அதற்கும் குறைவாக சுருக்கிடுங்கள் (நீங்கள் தற்போது <ph name="CURRENT_LENGTH" /> எழுத்துக்குறிகளைப் பயன்படுத்துகிறீர்கள்).</translation>
+<translation id="2246498165605549352">அகக் கோப்பு</translation>
<translation id="2247351761944213033">வாரம் <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ட்ராக் <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">செக்பாக்ஸ்</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">லேபிளிடப்படாத படம்</translation>
<translation id="3706100364254443312">ஸ்விட்ச்</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">’பிக்ச்சர்-இன்-பிக்ச்சரில்' இருந்து வெளியேறு</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">சொல்</translation>
<translation id="3822383571486410024">இந்த உரையை <ph name="MIN_CHARACTERS" /> எழுத்துக்குறிகள் அல்லது அதற்கும் அதிகமாக (தற்போது <ph name="CURRENT_LENGTH" /> எழுத்துக்குறிகளைப் பயன்படுத்துகிறீர்கள்) நீட்டிக்கவும்.</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ஐத் தொடரும் பகுதியில், '<ph name="INVALIDCHARACTER" />' சின்னம் இருக்கக்கூடாது.</translation>
<translation id="4668956016107839909">பிற்சேர்க்கை</translation>
+<translation id="4718048029184481307">’பிக்ச்சர்-இன்-பிக்ச்சர்' பயன்முறையில் பிளே ஆகிறது</translation>
<translation id="4742539557769756338">அட்டை</translation>
<translation id="4748357248530471599">டிஸ்ப்ளே கட்அவுட் முழுத்திரை நிலைமாற்ற பட்டன்</translation>
<translation id="4757246831282535685">தாவல் பலகம்</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">பின்னுரை</translation>
<translation id="6209276755895393898"><ph name="DESCRIPTION" /> போலத் தோன்றுகிறது.</translation>
<translation id="6213469881011901533">அருஞ்சொல் திரட்டு</translation>
-<translation id="628938136236500310">பிக்ச்சர்-இன்-பிக்ச்சர் பயன்முறையில் இயக்குகிறது</translation>
+<translation id="6310801910862476708">பிக்ச்சர்-இன்-பிக்ச்சர் பயன்முறையிலிருந்து வெளியேறு</translation>
<translation id="6398862346408813489">மாதம் தேர்ந்தெடுப்புப் பலகத்தைக் காட்டு</translation>
<translation id="6404546809543547843">ஆடியோ நேர ஸ்கிரப்பர்</translation>
<translation id="6443871981718447451">விரிவான வசனங்கள் மெனுவைக் காட்டும்</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_te.xtb b/chromium/content/app/strings/translations/content_strings_te.xtb
index 18201342a1b..050df443f6b 100644
--- a/chromium/content/app/strings/translations/content_strings_te.xtb
+++ b/chromium/content/app/strings/translations/content_strings_te.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">స్లయిడర్</translation>
<translation id="1211441953136645838">ఎండ్‌నోట్</translation>
<translation id="1281252709823657822">డైలాగ్</translation>
-<translation id="1289247557029249093">చిత్రంలో చిత్రం మోడ్ నుంచి నిష్క్రమించు</translation>
<translation id="1335095011850992622">సహకారులు</translation>
<translation id="1342835525016946179">కథనం</translation>
<translation id="1359897965706325498">బ్యానర్</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">ఈ రోజు</translation>
<translation id="2158401438286456825">పేజీ జాబితా</translation>
<translation id="2226276347425096477">దయచేసి ఈ వచనాన్ని <ph name="MAX_CHARACTERS" /> అక్షరాలకు లేదా అంతకంటే తక్కువకు తగ్గించండి (మీరు ప్రస్తుతం <ph name="CURRENT_LENGTH" /> అక్షరాలను ఉపయోగిస్తున్నారు).</translation>
+<translation id="2246498165605549352">స్థానిక ఫైల్</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />వ వారం, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ట్రాక్ <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">చెక్‌బాక్స్</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">లేబుల్ లేని చిత్రం</translation>
<translation id="3706100364254443312">మార్పు</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">చిత్రంలో చిత్రం మోడ్ నుండి నిష్క్రమింపజేయి</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">పదం</translation>
<translation id="3822383571486410024">దయచేసి ఈ వచనాన్ని <ph name="MIN_CHARACTERS" /> లేదా అంతకంటే ఎక్కువ అక్షరాలకు పొడిగించండి (ప్రస్తుతం మీరు <ph name="CURRENT_LENGTH" /> అక్షరాలను ఉపయోగిస్తున్నారు).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />'కి తర్వాత ఉన్న భాగంలో '<ph name="INVALIDCHARACTER" />' చిహ్నం ఉండకూడదు.</translation>
<translation id="4668956016107839909">అనుబంధం</translation>
+<translation id="4718048029184481307">చిత్రంలో చిత్రం మోడ్‌లో ప్లే అవుతోంది</translation>
<translation id="4742539557769756338">ముఖచిత్రం</translation>
<translation id="4748357248530471599">డిస్‌ప్లే కత్తిరింపు పూర్తి స్క్రీన్‌ని సక్రియం చేస్తుంది</translation>
<translation id="4757246831282535685">ట్యాబ్ ప్యానెల్</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">చివరిమాట</translation>
<translation id="6209276755895393898">వీరిలా కనిపిస్తున్నారు: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">పదకోశం</translation>
-<translation id="628938136236500310">చిత్రంలో చిత్రం మోడ్‌లో ప్లే చేస్తోంది</translation>
+<translation id="6310801910862476708">చిత్రంలో చిత్రం మోడ్ నుండి నిష్క్రమించు</translation>
<translation id="6398862346408813489">నెల ఎంపిక ప్యానెల్‌ను చూపుతుంది</translation>
<translation id="6404546809543547843">ఆడియో సమయ స్క్రబ్బర్</translation>
<translation id="6443871981718447451">ఉపశీర్షికల మెనూని చూపు</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_th.xtb b/chromium/content/app/strings/translations/content_strings_th.xtb
index e4c09f42ca1..787bb329882 100644
--- a/chromium/content/app/strings/translations/content_strings_th.xtb
+++ b/chromium/content/app/strings/translations/content_strings_th.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">แถบเลื่อน</translation>
<translation id="1211441953136645838">อ้างอิงท้ายเรื่อง</translation>
<translation id="1281252709823657822">กล่องโต้ตอบ</translation>
-<translation id="1289247557029249093">ออกจากโหมดการแสดงภาพซ้อนภาพ</translation>
<translation id="1335095011850992622">เครดิต</translation>
<translation id="1342835525016946179">บทความ</translation>
<translation id="1359897965706325498">แบนเนอร์</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">วันนี้</translation>
<translation id="2158401438286456825">รายการหน้า</translation>
<translation id="2226276347425096477">โปรดย่อข้อความนี้ให้เหลือไม่เกิน <ph name="MAX_CHARACTERS" /> อักขระ (ขณะนี้ข้อความของคุณมี <ph name="CURRENT_LENGTH" /> อักขระ)</translation>
+<translation id="2246498165605549352">ไฟล์ในตัวเครื่อง</translation>
<translation id="2247351761944213033">สัปดาห์ที่ <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">แทร็ก <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">ช่องทำเครื่องหมาย</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">รูปภาพที่ไม่มีป้ายกำกับ</translation>
<translation id="3706100364254443312">สวิตช์</translation>
<translation id="3732799496749320381">ดด</translation>
+<translation id="3754210790023674521">ออกจากการแสดงภาพซ้อนภาพ</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">คีย์เวิร์ด</translation>
<translation id="3822383571486410024">โปรดกรอกข้อความนี้ให้มีอักขระอย่างน้อย <ph name="MIN_CHARACTERS" /> ตัว (ตอนนี้คุณมี <ph name="CURRENT_LENGTH" /> ตัว)</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">แผนผัง</translation>
<translation id="4664250907885839816">ส่วนที่ต่อท้าย "<ph name="ATSIGN" />" ต้องไม่มีสัญลักษณ์ "<ph name="INVALIDCHARACTER" />"</translation>
<translation id="4668956016107839909">ภาคผนวก</translation>
+<translation id="4718048029184481307">กำลังเล่นแบบการแสดงภาพซ้อนภาพ</translation>
<translation id="4742539557769756338">หน้าปก</translation>
<translation id="4748357248530471599">สลับเป็นแบบเต็มหน้าจอสำหรับหน้าจอรอยบาก</translation>
<translation id="4757246831282535685">แผงแท็บ</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">คำแถลงท้ายเล่ม</translation>
<translation id="6209276755895393898">ดูเหมือนเป็น<ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">อภิธานศัพท์</translation>
-<translation id="628938136236500310">กำลังเล่นในโหมดการแสดงภาพซ้อนภาพ</translation>
+<translation id="6310801910862476708">ออกจากการแสดงภาพซ้อนภาพ</translation>
<translation id="6398862346408813489">แสดงแผงการเลือกเดือน</translation>
<translation id="6404546809543547843">ตัวควบคุมเวลาของเสียง</translation>
<translation id="6443871981718447451">แสดงเมนูคำอธิบายภาพ</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_tr.xtb b/chromium/content/app/strings/translations/content_strings_tr.xtb
index 7e8e4b9ef5d..8b5abc5d427 100644
--- a/chromium/content/app/strings/translations/content_strings_tr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_tr.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">kaydırma çubuğu</translation>
<translation id="1211441953136645838">son not</translation>
<translation id="1281252709823657822">iletişim kutusu</translation>
-<translation id="1289247557029249093">Pencere içinde pencere modundan çık</translation>
<translation id="1335095011850992622">katkıda bulunanlar</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Bugün</translation>
<translation id="2158401438286456825">sayfa listesi</translation>
<translation id="2226276347425096477">Lütfen bu metni <ph name="MAX_CHARACTERS" /> veya daha az karakter olacak şekilde kısaltın (şu anda <ph name="CURRENT_LENGTH" /> karakter kullanıyorsunuz).</translation>
+<translation id="2246498165605549352">Yerel Dosya</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. hafta, <ph name="YEAR" /></translation>
<translation id="2277199496770840904"><ph name="NUMBER" />. parça</translation>
<translation id="2291999235780842123">onay kutusu</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Etiketsiz resim</translation>
<translation id="3706100364254443312">anahtar</translation>
<translation id="3732799496749320381">aa</translation>
+<translation id="3754210790023674521">Pencere içinde pencere modundan çık</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">terim</translation>
<translation id="3822383571486410024">Lütfen bu metni <ph name="MIN_CHARACTERS" /> karakter veya daha fazla olacak şekilde uzatın (şu anda <ph name="CURRENT_LENGTH" /> karakter kullanıyorsunuz).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Başında "<ph name="ATSIGN" />" bulunan kısımda "<ph name="INVALIDCHARACTER" />" simgesi bulunmamalıdır.</translation>
<translation id="4668956016107839909">ek</translation>
+<translation id="4718048029184481307">Pencere içinde pencere modunda oynatılıyor</translation>
<translation id="4742539557769756338">kapak</translation>
<translation id="4748357248530471599">ekran kesimi alanını tam ekran olarak değiştirin</translation>
<translation id="4757246831282535685">sekme paneli</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">sonsöz</translation>
<translation id="6209276755895393898">Resimdeki şu olabilir: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">terimler sözlüğü</translation>
-<translation id="628938136236500310">Pencere içinde pencere modunda oynatılıyor</translation>
+<translation id="6310801910862476708">Pencere İçinde Pencereden Çık</translation>
<translation id="6398862346408813489">Ay seçim panelini göster</translation>
<translation id="6404546809543547843">ses zaman çizelgesi temizleyici</translation>
<translation id="6443871981718447451">altyazı menüsünü göster</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_uk.xtb b/chromium/content/app/strings/translations/content_strings_uk.xtb
index 29d136d694e..9b49dfa5145 100644
--- a/chromium/content/app/strings/translations/content_strings_uk.xtb
+++ b/chromium/content/app/strings/translations/content_strings_uk.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">повзунок</translation>
<translation id="1211441953136645838">кінцева виноска</translation>
<translation id="1281252709823657822">діалогове вікно</translation>
-<translation id="1289247557029249093">Вийти з режиму "картинка в картинці"</translation>
<translation id="1335095011850992622">подяки</translation>
<translation id="1342835525016946179">стаття</translation>
<translation id="1359897965706325498">банер</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Сьогодні</translation>
<translation id="2158401438286456825">список сторінок</translation>
<translation id="2226276347425096477">Скоротіть текст до такої кількості символів або менше: <ph name="MAX_CHARACTERS" /> (наразі використано символів: <ph name="CURRENT_LENGTH" />).</translation>
+<translation id="2246498165605549352">Локальний файл</translation>
<translation id="2247351761944213033">Тиждень <ph name="WEEKNUMBER" />, <ph name="YEAR" /> р.</translation>
<translation id="2277199496770840904">Композиція <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">прапорець</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Зображення без мітки</translation>
<translation id="3706100364254443312">перемикач</translation>
<translation id="3732799496749320381">мм</translation>
+<translation id="3754210790023674521">Вийти з режиму "Картинка в картинці"</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> ГБ</translation>
<translation id="3808586225841795776">термін</translation>
<translation id="3822383571486410024">У тексті має бути на менше <ph name="MIN_CHARACTERS" /> символів (ви ввели <ph name="CURRENT_LENGTH" /> символів).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">дерево</translation>
<translation id="4664250907885839816">Частина після знака "<ph name="ATSIGN" />" не може містити символ "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">додаток</translation>
+<translation id="4718048029184481307">Відтворюється в режимі "Картинка в картинці"</translation>
<translation id="4742539557769756338">обкладинка</translation>
<translation id="4748357248530471599">перемкнути виріз у повноекранному режимі</translation>
<translation id="4757246831282535685">панель вкладок</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">післямова</translation>
<translation id="6209276755895393898">Схоже, на цьому зображенні <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">глосарій</translation>
-<translation id="628938136236500310">Відтворення в режимі "картинка в картинці"</translation>
+<translation id="6310801910862476708">Вийти з режиму "Картинка в картинці"</translation>
<translation id="6398862346408813489">Показати панель вибору місяців</translation>
<translation id="6404546809543547843">повзунок часу відтворення аудіо</translation>
<translation id="6443871981718447451">показати меню субтитрів</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_vi.xtb b/chromium/content/app/strings/translations/content_strings_vi.xtb
index a95f7500286..cd2603b173e 100644
--- a/chromium/content/app/strings/translations/content_strings_vi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_vi.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">thanh trượt</translation>
<translation id="1211441953136645838">chú thích cuối</translation>
<translation id="1281252709823657822">hộp thoại</translation>
-<translation id="1289247557029249093">Thoát khỏi chế độ hình trong hình</translation>
<translation id="1335095011850992622">ghi nhận tác giả</translation>
<translation id="1342835525016946179">bài viết</translation>
<translation id="1359897965706325498">biểu ngữ</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">Hôm nay</translation>
<translation id="2158401438286456825">danh sách trang</translation>
<translation id="2226276347425096477">Hãy cắt ngắn văn bản này thành <ph name="MAX_CHARACTERS" /> ký tự hoặc ít hơn (bạn hiện đang sử dụng <ph name="CURRENT_LENGTH" /> ký tự).</translation>
+<translation id="2246498165605549352">Tệp trên máy</translation>
<translation id="2247351761944213033">Tuần <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Bản nhạc <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">hộp kiểm</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">Hình ảnh không có nhãn</translation>
<translation id="3706100364254443312">chuyển</translation>
<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Thoát chế độ hình trong hình</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">cụm từ</translation>
<translation id="3822383571486410024">Hãy kéo dài văn bản này thành <ph name="MIN_CHARACTERS" /> ký tự trở lên (bạn hiện đang sử dụng <ph name="CURRENT_LENGTH" /> ký tự).</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">cây</translation>
<translation id="4664250907885839816">Phần đứng sau '<ph name="ATSIGN" />' không được chứa biểu tượng '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="4668956016107839909">phụ lục</translation>
+<translation id="4718048029184481307">Đang phát ở chế độ hình trong hình</translation>
<translation id="4742539557769756338">trang bìa</translation>
<translation id="4748357248530471599">bật/tắt chế độ toàn màn hình có vết cắt</translation>
<translation id="4757246831282535685">bảng điều khiển tab</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">lời bạt</translation>
<translation id="6209276755895393898">Có vẻ như là: <ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">bảng thuật ngữ</translation>
-<translation id="628938136236500310">Đang phát ở chế độ hình trong hình</translation>
+<translation id="6310801910862476708">Thoát chế độ hình trong hình</translation>
<translation id="6398862346408813489">Hiển thị bảng lựa chọn tháng</translation>
<translation id="6404546809543547843">trình kiểm soát thời gian âm thanh</translation>
<translation id="6443871981718447451">hiển thị menu phụ đề chi tiết</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_zh-CN.xtb b/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
index 61f983db18c..91f6d1a1d12 100644
--- a/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
+++ b/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">滑块</translation>
<translation id="1211441953136645838">尾注</translation>
<translation id="1281252709823657822">对话框</translation>
-<translation id="1289247557029249093">退出“画中画”模式</translation>
<translation id="1335095011850992622">参与者名单</translation>
<translation id="1342835525016946179">文章标记</translation>
<translation id="1359897965706325498">横幅</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">今天</translation>
<translation id="2158401438286456825">页面列表</translation>
<translation id="2226276347425096477">请将该文本减少为 <ph name="MAX_CHARACTERS" /> 个字符或更少(您当前使用了 <ph name="CURRENT_LENGTH" /> 个字符)。</translation>
+<translation id="2246498165605549352">本地文件</translation>
<translation id="2247351761944213033"><ph name="YEAR" /> 年第 <ph name="WEEKNUMBER" /> 周</translation>
<translation id="2277199496770840904">字幕轨 <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">复选框</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">未加标签的图片</translation>
<translation id="3706100364254443312">切换</translation>
<translation id="3732799496749320381">月</translation>
+<translation id="3754210790023674521">退出“画中画”模式</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">字词</translation>
<translation id="3822383571486410024">请将该文本增加为 <ph name="MIN_CHARACTERS" /> 个字符或更多(您当前使用的是 <ph name="CURRENT_LENGTH" /> 个字符)。</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">“<ph name="ATSIGN" />”后面的内容不应包含符号“<ph name="INVALIDCHARACTER" />”。</translation>
<translation id="4668956016107839909">附录</translation>
+<translation id="4718048029184481307">以“画中画”模式播放</translation>
<translation id="4742539557769756338">封面</translation>
<translation id="4748357248530471599">开启/关闭全屏模式中的刘海屏</translation>
<translation id="4757246831282535685">标签面板</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">后记</translation>
<translation id="6209276755895393898">似乎是:<ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">词汇表</translation>
-<translation id="628938136236500310">以“画中画”模式播放</translation>
+<translation id="6310801910862476708">退出“画中画”模式</translation>
<translation id="6398862346408813489">显示月份选择面板</translation>
<translation id="6404546809543547843">音频时间进度条</translation>
<translation id="6443871981718447451">显示字幕菜单</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_zh-TW.xtb b/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
index c67b2e8af19..5bfd2ee0867 100644
--- a/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
+++ b/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
@@ -11,7 +11,6 @@
<translation id="1206693055195146388">滑桿</translation>
<translation id="1211441953136645838">章節附註</translation>
<translation id="1281252709823657822">對話方塊</translation>
-<translation id="1289247557029249093">離開子母畫面模式</translation>
<translation id="1335095011850992622">參與名單</translation>
<translation id="1342835525016946179">文章</translation>
<translation id="1359897965706325498">橫幅</translation>
@@ -37,6 +36,7 @@
<translation id="2148716181193084225">今天</translation>
<translation id="2158401438286456825">頁面清單</translation>
<translation id="2226276347425096477">請將這段文字刪減至 <ph name="MAX_CHARACTERS" /> 個字元以下 (目前的字元數為 <ph name="CURRENT_LENGTH" /> 個)。</translation>
+<translation id="2246498165605549352">本機檔案</translation>
<translation id="2247351761944213033"><ph name="YEAR" /> 年,第 <ph name="WEEKNUMBER" /> 週</translation>
<translation id="2277199496770840904">曲目 <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">核取方塊</translation>
@@ -75,6 +75,7 @@
<translation id="3685101356851116974">未標示的圖片</translation>
<translation id="3706100364254443312">切換</translation>
<translation id="3732799496749320381">月</translation>
+<translation id="3754210790023674521">離開子母畫面</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3808586225841795776">字詞</translation>
<translation id="3822383571486410024">請將這段文字加長到 <ph name="MIN_CHARACTERS" /> 個字元以上 (目前使用字元數:<ph name="CURRENT_LENGTH" />)。</translation>
@@ -102,6 +103,7 @@
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">「<ph name="ATSIGN" />」後面的部分不應包含「<ph name="INVALIDCHARACTER" />」符號。</translation>
<translation id="4668956016107839909">附錄</translation>
+<translation id="4718048029184481307">在子母畫面中播放</translation>
<translation id="4742539557769756338">封面</translation>
<translation id="4748357248530471599">切換螢幕凹口全螢幕模式</translation>
<translation id="4757246831282535685">分頁面板</translation>
@@ -150,7 +152,7 @@
<translation id="6166809985690652833">後記</translation>
<translation id="6209276755895393898">圖片內容似乎是:<ph name="DESCRIPTION" /></translation>
<translation id="6213469881011901533">詞彙解釋</translation>
-<translation id="628938136236500310">正在以子母畫面模式播放影片</translation>
+<translation id="6310801910862476708">離開子母畫面</translation>
<translation id="6398862346408813489">顯示月份選取面板</translation>
<translation id="6404546809543547843">音訊時間點拖曳工具</translation>
<translation id="6443871981718447451">顯示隱藏式輔助字幕選單</translation>
diff --git a/chromium/content/app_shim_remote_cocoa/DEPS b/chromium/content/app_shim_remote_cocoa/DEPS
new file mode 100644
index 00000000000..a9570cac7c9
--- /dev/null
+++ b/chromium/content/app_shim_remote_cocoa/DEPS
@@ -0,0 +1,35 @@
+# This should eventually shrink until nothing from content is included,
+# whereupon this code may be moved to components/remote_cocoa. Do not
+# add any additional dependencies on content code.
+# https://crbug.com/958255
+include_rules = [
+ "+components/remote_cocoa/app_shim",
+ "+content/app_shim_remote_cocoa",
+ "+content/browser/accessibility/browser_accessibility_cocoa.h",
+ "+content/browser/accessibility/browser_accessibility_mac.h",
+ "+content/browser/accessibility/browser_accessibility_manager_mac.h",
+ "+content/browser/cocoa/system_hotkey_helper_mac.h",
+ "+content/browser/cocoa/system_hotkey_map.h",
+ "+content/browser/download/drag_download_file.h",
+ "+content/browser/download/drag_download_util.h",
+ "+content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h",
+ "+content/browser/renderer_host/input/web_input_event_builders_mac.h",
+ "+content/browser/renderer_host/render_widget_host_view_mac.h",
+ "+content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h",
+ "+content/browser/web_contents/web_contents_impl.h",
+ "+content/browser/web_contents/web_contents_view_mac.h",
+ "+content/browser/web_contents/web_drag_dest_mac.h",
+ "+content/common/content_export.h",
+ "+content/common/cursors/webcursor.h",
+ "+content/common/edit_command.h",
+ "+content/common/render_widget_host_ns_view.mojom.h",
+ "+content/common/web_contents_ns_view_bridge.mojom.h",
+ "+content/public/browser/content_browser_client.h",
+ "+content/public/browser/native_web_keyboard_event.h",
+ "+content/public/browser/remote_cocoa.h",
+ "+content/public/browser/render_widget_host_view_mac_delegate.h",
+ "+content/public/common/content_client.h",
+ "+content/public/common/content_features.h",
+ "+content/public/common/drop_data.h",
+ "+content/public/common/widget_type.h",
+]
diff --git a/chromium/content/browser/ns_view_bridge_factory_impl.mm b/chromium/content/app_shim_remote_cocoa/ns_view_bridge_factory_impl.mm
index 68dc92ce3c0..98b4efbae00 100644
--- a/chromium/content/browser/ns_view_bridge_factory_impl.mm
+++ b/chromium/content/app_shim_remote_cocoa/ns_view_bridge_factory_impl.mm
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/public/browser/ns_view_bridge_factory_impl.h"
+#include "content/public/browser/remote_cocoa.h"
#include <utility>
#include <vector>
@@ -10,11 +10,12 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/no_destructor.h"
+#include "content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge_local.h"
+#include "content/app_shim_remote_cocoa/render_widget_host_ns_view_client_helper.h"
+#include "content/app_shim_remote_cocoa/web_contents_ns_view_bridge.h"
#include "content/browser/renderer_host/input/web_input_event_builders_mac.h"
-#include "content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h"
-#include "content/browser/renderer_host/render_widget_host_ns_view_client_helper.h"
-#include "content/browser/web_contents/web_contents_ns_view_bridge.h"
#include "content/common/render_widget_host_ns_view.mojom.h"
+#include "content/common/web_contents_ns_view_bridge.mojom.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
@@ -129,30 +130,18 @@ class RenderWidgetHostNSViewBridgeOwner
}
-// static
-NSViewBridgeFactoryImpl* NSViewBridgeFactoryImpl::Get() {
- static base::NoDestructor<NSViewBridgeFactoryImpl> instance;
- return instance.get();
-}
-
-void NSViewBridgeFactoryImpl::BindRequest(
- mojom::NSViewBridgeFactoryAssociatedRequest request) {
- binding_.Bind(std::move(request),
- ui::WindowResizeHelperMac::Get()->task_runner());
-}
-
-void NSViewBridgeFactoryImpl::CreateRenderWidgetHostNSViewBridge(
- mojom::StubInterfaceAssociatedPtrInfo stub_client,
- mojom::StubInterfaceAssociatedRequest stub_bridge_request) {
+void CreateRenderWidgetHostNSView(
+ mojo::ScopedInterfaceEndpointHandle host_handle,
+ mojo::ScopedInterfaceEndpointHandle view_request_handle) {
// Cast from the stub interface to the mojom::RenderWidgetHostNSViewClient
// and mojom::RenderWidgetHostNSViewBridge private interfaces.
// TODO(ccameron): Remove the need for this cast.
// https://crbug.com/888290
mojom::RenderWidgetHostNSViewClientAssociatedPtr client(
mojo::AssociatedInterfacePtrInfo<mojom::RenderWidgetHostNSViewClient>(
- stub_client.PassHandle(), 0));
+ std::move(host_handle), 0));
mojom::RenderWidgetHostNSViewBridgeAssociatedRequest bridge_request(
- stub_bridge_request.PassHandle());
+ std::move(view_request_handle));
// Create a RenderWidgetHostNSViewBridgeOwner. The resulting object will be
// destroyed when its underlying pipe is closed.
@@ -160,10 +149,15 @@ void NSViewBridgeFactoryImpl::CreateRenderWidgetHostNSViewBridge(
std::move(client), std::move(bridge_request)));
}
-void NSViewBridgeFactoryImpl::CreateWebContentsNSViewBridge(
+void CreateWebContentsNSView(
uint64_t view_id,
- mojom::WebContentsNSViewClientAssociatedPtrInfo client,
- mojom::WebContentsNSViewBridgeAssociatedRequest bridge_request) {
+ mojo::ScopedInterfaceEndpointHandle host_handle,
+ mojo::ScopedInterfaceEndpointHandle view_request_handle) {
+ mojom::WebContentsNSViewClientAssociatedPtr client(
+ mojo::AssociatedInterfacePtrInfo<mojom::WebContentsNSViewClient>(
+ std::move(host_handle), 0));
+ mojom::WebContentsNSViewBridgeAssociatedRequest bridge_request(
+ std::move(view_request_handle));
// Note that the resulting object will be destroyed when its underlying pipe
// is closed.
mojo::MakeStrongAssociatedBinding(
@@ -174,8 +168,4 @@ void NSViewBridgeFactoryImpl::CreateWebContentsNSViewBridge(
ui::WindowResizeHelperMac::Get()->task_runner());
}
-NSViewBridgeFactoryImpl::NSViewBridgeFactoryImpl() : binding_(this) {}
-
-NSViewBridgeFactoryImpl::~NSViewBridgeFactoryImpl() {}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/popup_window_mac.h b/chromium/content/app_shim_remote_cocoa/popup_window_mac.h
index 1b3d65da55f..518ffb83e3e 100644
--- a/chromium/content/browser/renderer_host/popup_window_mac.h
+++ b/chromium/content/app_shim_remote_cocoa/popup_window_mac.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_RENDERER_HOST_POPUP_WINDOW_MAC_H_
-#define CONTENT_BROWSER_RENDERER_HOST_POPUP_WINDOW_MAC_H_
+#ifndef CONTENT_APP_SHIM_REMOTE_COCOA_POPUP_WINDOW_MAC_H_
+#define CONTENT_APP_SHIM_REMOTE_COCOA_POPUP_WINDOW_MAC_H_
#import "base/mac/scoped_nsobject.h"
#include "base/macros.h"
@@ -37,4 +37,4 @@ class PopupWindowMac {
} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_POPUP_WINDOW_MAC_H_
+#endif // CONTENT_APP_SHIM_REMOTE_COCOA_POPUP_WINDOW_MAC_H_
diff --git a/chromium/content/browser/renderer_host/popup_window_mac.mm b/chromium/content/app_shim_remote_cocoa/popup_window_mac.mm
index 76001b3e373..3125dfc8927 100644
--- a/chromium/content/browser/renderer_host/popup_window_mac.mm
+++ b/chromium/content/app_shim_remote_cocoa/popup_window_mac.mm
@@ -2,9 +2,9 @@
// 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/popup_window_mac.h"
+#import "content/app_shim_remote_cocoa/popup_window_mac.h"
-#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
+#import "content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h"
#include "ui/gfx/mac/coordinate_conversion.h"
@interface RenderWidgetPopupWindow : NSWindow {
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h b/chromium/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge_local.h
index ebf87176f5e..6f19cdac9ad 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h
+++ b/chromium/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge_local.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_BRIDGE_LOCAL_H_
-#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_BRIDGE_LOCAL_H_
+#ifndef CONTENT_APP_SHIM_REMOTE_COCOA_RENDER_WIDGET_HOST_NS_VIEW_BRIDGE_LOCAL_H_
+#define CONTENT_APP_SHIM_REMOTE_COCOA_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"
+#import "content/app_shim_remote_cocoa/popup_window_mac.h"
+#import "content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h"
#include "content/common/render_widget_host_ns_view.mojom.h"
#include "content/public/common/widget_type.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
@@ -100,4 +100,4 @@ class RenderWidgetHostNSViewBridgeLocal
} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_BRIDGE_LOCAL_H_
+#endif // CONTENT_APP_SHIM_REMOTE_COCOA_RENDER_WIDGET_HOST_NS_VIEW_BRIDGE_LOCAL_H_
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm b/chromium/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge_local.mm
index c8b3df61e12..2aa04c3764e 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm
+++ b/chromium/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge_local.mm
@@ -2,16 +2,16 @@
// 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_local.h"
+#import "content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge_local.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/strings/sys_string_conversions.h"
-#include "content/browser/renderer_host/render_widget_host_ns_view_client_helper.h"
+#include "components/remote_cocoa/app_shim/ns_view_ids.h"
+#include "content/app_shim_remote_cocoa/render_widget_host_ns_view_client_helper.h"
#include "content/common/cursors/webcursor.h"
#import "skia/ext/skia_utils_mac.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#import "ui/base/cocoa/animation_utils.h"
-#include "ui/base/cocoa/ns_view_ids.h"
#include "ui/display/screen.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/mac/coordinate_conversion.h"
@@ -67,7 +67,7 @@ void RenderWidgetHostNSViewBridgeLocal::InitAsPopup(
void RenderWidgetHostNSViewBridgeLocal::SetParentWebContentsNSView(
uint64_t parent_ns_view_id) {
- NSView* parent_ns_view = ui::NSViewIds::GetNSView(parent_ns_view_id);
+ NSView* parent_ns_view = remote_cocoa::GetNSViewFromId(parent_ns_view_id);
// If the browser passed an invalid handle, then there is no recovery.
CHECK(parent_ns_view);
// Set the frame and autoresizing mask of the RenderWidgetHostViewCocoa as is
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_client_helper.h b/chromium/content/app_shim_remote_cocoa/render_widget_host_ns_view_client_helper.h
index 572f4e01b18..757f0c45e0d 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_ns_view_client_helper.h
+++ b/chromium/content/app_shim_remote_cocoa/render_widget_host_ns_view_client_helper.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_HELPER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_HELPER_H_
+#ifndef CONTENT_APP_SHIM_REMOTE_COCOA_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_HELPER_H_
+#define CONTENT_APP_SHIM_REMOTE_COCOA_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_HELPER_H_
#include "base/macros.h"
@@ -86,4 +86,4 @@ class RenderWidgetHostNSViewClientHelper {
} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_HELPER_H_
+#endif // CONTENT_APP_SHIM_REMOTE_COCOA_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_HELPER_H_
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h b/chromium/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h
index 039c1196036..b8eb5221fb8 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h
+++ b/chromium/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_COCOA_H_
-#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_COCOA_H_
+#ifndef CONTENT_APP_SHIM_REMOTE_COCOA_RENDER_WIDGET_HOST_VIEW_COCOA_H_
+#define CONTENT_APP_SHIM_REMOTE_COCOA_RENDER_WIDGET_HOST_VIEW_COCOA_H_
#import <Cocoa/Cocoa.h>
@@ -53,10 +53,11 @@ struct DidOverscrollParams;
// when it's removed from the view system.
// TODO(ccameron): Hide this interface behind RenderWidgetHostNSViewBridge.
@interface RenderWidgetHostViewCocoa
- : ToolTipBaseView<CommandDispatcherTarget,
- RenderWidgetHostNSViewClientOwner,
- NSCandidateListTouchBarItemDelegate,
- NSTextInputClient> {
+ : ToolTipBaseView <CommandDispatcherTarget,
+ RenderWidgetHostNSViewClientOwner,
+ NSCandidateListTouchBarItemDelegate,
+ NSTextInputClient,
+ NSAccessibility> {
@private
// The communications channel to the RenderWidgetHostViewMac. This pointer is
// always valid. When the original client disconnects, |client_| is changed to
@@ -276,4 +277,4 @@ struct DidOverscrollParams;
- (void)processedOverscroll:(const ui::DidOverscrollParams&)params;
@end
-#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_COCOA_H_
+#endif // CONTENT_APP_SHIM_REMOTE_COCOA_RENDER_WIDGET_HOST_VIEW_COCOA_H_
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm b/chromium/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
index eecc6771247..f583a0a6eaa 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
+++ b/chromium/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
+#import "content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h"
#include <limits>
#include <utility>
@@ -658,17 +658,10 @@ void ExtractUnderlines(NSAttributedString* string,
mouse_locked_ = locked;
if (mouse_locked_) {
CGAssociateMouseAndMouseCursorPosition(NO);
- NSRect bound = [[self window] convertRectToScreen:[self bounds]];
- gfx::Point screen_center = gfx::ScreenRectFromNSRect(bound).CenterPoint();
- mouse_locked_screen_position_ = last_mouse_screen_position_;
- CGDisplayMoveCursorToPoint(CGMainDisplayID(), screen_center.ToCGPoint());
[NSCursor hide];
} else {
// Unlock position of mouse cursor and unhide it.
CGAssociateMouseAndMouseCursorPosition(YES);
- CGDisplayMoveCursorToPoint(CGMainDisplayID(),
- NSMakePoint(mouse_locked_screen_position_.x(),
- mouse_locked_screen_position_.y()));
[NSCursor unhide];
}
}
@@ -1411,53 +1404,6 @@ void ExtractUnderlines(NSAttributedString* string,
accessibilityParent_.reset(accessibilityParent, base::scoped_policy::RETAIN);
}
-// TODO(crbug.com/921109): Migrate from the NSObject accessibility API to the
-// NSAccessibility API, then remove this suppression.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-
-- (NSArray*)accessibilityArrayAttributeValues:(NSString*)attribute
- index:(NSUInteger)index
- maxCount:(NSUInteger)maxCount {
- NSArray* fullArray = [self accessibilityAttributeValue:attribute];
- NSUInteger totalLength = [fullArray count];
- if (index >= totalLength)
- return nil;
- NSUInteger length = MIN(totalLength - index, maxCount);
- return [fullArray subarrayWithRange:NSMakeRange(index, length)];
-}
-
-- (NSUInteger)accessibilityArrayAttributeCount:(NSString*)attribute {
- NSArray* fullArray = [self accessibilityAttributeValue:attribute];
- return [fullArray count];
-}
-
-- (id)accessibilityAttributeValue:(NSString*)attribute {
- id root_element = clientHelper_->GetRootBrowserAccessibilityElement();
- // Contents specifies document view of RenderWidgetHostViewCocoa provided by
- // BrowserAccessibilityManager. Children includes all subviews in addition to
- // contents. Currently we do not have subviews besides the document view.
- if (([attribute isEqualToString:NSAccessibilityChildrenAttribute] ||
- [attribute isEqualToString:NSAccessibilityContentsAttribute]) &&
- root_element) {
- return [NSArray arrayWithObjects:root_element, nil];
- } else if ([attribute isEqualToString:NSAccessibilityParentAttribute] &&
- accessibilityParent_) {
- return NSAccessibilityUnignoredAncestor(accessibilityParent_);
- } else if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
- return NSAccessibilityScrollAreaRole;
- }
- id ret = [super accessibilityAttributeValue:attribute];
- return ret;
-}
-
-- (NSArray*)accessibilityAttributeNames {
- NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
- [ret addObject:NSAccessibilityContentsAttribute];
- [ret addObjectsFromArray:[super accessibilityAttributeNames]];
- return ret;
-}
-
- (id)accessibilityHitTest:(NSPoint)point {
id root_element = clientHelper_->GetRootBrowserAccessibilityElement();
if (!root_element)
@@ -1470,26 +1416,32 @@ void ExtractUnderlines(NSAttributedString* string,
return obj;
}
-- (BOOL)accessibilityIsIgnored {
- id root_element = clientHelper_->GetRootBrowserAccessibilityElement();
- return !root_element;
+- (id)accessibilityFocusedUIElement {
+ return clientHelper_->GetFocusedBrowserAccessibilityElement();
}
-- (NSUInteger)accessibilityGetIndexOf:(id)child {
- id root_element = clientHelper_->GetRootBrowserAccessibilityElement();
- // Only child is root.
- if (root_element == child) {
- return 0;
- } else {
- return NSNotFound;
- }
+// NSAccessibility formal protocol:
+
+- (NSArray*)accessibilityChildren {
+ id root = clientHelper_->GetRootBrowserAccessibilityElement();
+ if (root)
+ return @[ root ];
+ return nil;
}
-- (id)accessibilityFocusedUIElement {
- return clientHelper_->GetFocusedBrowserAccessibilityElement();
+- (NSArray*)accessibilityContents {
+ return self.accessibilityChildren;
+}
+
+- (id)accessibilityParent {
+ if (accessibilityParent_)
+ return NSAccessibilityUnignoredAncestor(accessibilityParent_);
+ return [super accessibilityParent];
}
-#pragma clang diagnostic pop
+- (NSAccessibilityRole)accessibilityRole {
+ return NSAccessibilityScrollAreaRole;
+}
// Below is our NSTextInputClient implementation.
//
diff --git a/chromium/content/browser/web_contents/web_contents_ns_view_bridge.h b/chromium/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.h
index 8911fedbae0..c7f28751253 100644
--- a/chromium/content/browser/web_contents/web_contents_ns_view_bridge.h
+++ b/chromium/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.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_CONTENTS_WEB_CONTENTS_NS_VIEW_BRIDGE_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_NS_VIEW_BRIDGE_H_
+#ifndef CONTENT_APP_SHIM_REMOTE_COCOA_WEB_CONTENTS_NS_VIEW_BRIDGE_H_
+#define CONTENT_APP_SHIM_REMOTE_COCOA_WEB_CONTENTS_NS_VIEW_BRIDGE_H_
#import <Cocoa/Cocoa.h>
@@ -11,9 +11,9 @@
#import "base/mac/scoped_nsobject.h"
#include "base/macros.h"
+#include "components/remote_cocoa/app_shim/ns_view_ids.h"
#include "content/common/content_export.h"
-#include "content/public/common/web_contents_ns_view_bridge.mojom.h"
-#include "ui/base/cocoa/ns_view_ids.h"
+#include "content/common/web_contents_ns_view_bridge.mojom.h"
@class WebContentsViewCocoa;
@@ -55,11 +55,11 @@ class CONTENT_EXPORT WebContentsNSViewBridge
base::scoped_nsobject<WebContentsViewCocoa> cocoa_view_;
mojom::WebContentsNSViewClientAssociatedPtr client_;
- std::unique_ptr<ui::ScopedNSViewIdMapping> view_id_;
+ std::unique_ptr<remote_cocoa::ScopedNSViewIdMapping> view_id_;
DISALLOW_COPY_AND_ASSIGN(WebContentsNSViewBridge);
};
} // namespace content
-#endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_NS_VIEW_BRIDGE_H_
+#endif // CONTENT_APP_SHIM_REMOTE_COCOA_WEB_CONTENTS_NS_VIEW_BRIDGE_H_
diff --git a/chromium/content/browser/web_contents/web_contents_ns_view_bridge.mm b/chromium/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.mm
index 8da6994ef3e..c5815d129da 100644
--- a/chromium/content/browser/web_contents/web_contents_ns_view_bridge.mm
+++ b/chromium/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.mm
@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/web_contents/web_contents_ns_view_bridge.h"
+#include "content/app_shim_remote_cocoa/web_contents_ns_view_bridge.h"
-#import "content/browser/web_contents/web_contents_view_cocoa.h"
+#include "components/remote_cocoa/app_shim/ns_view_ids.h"
+#import "content/app_shim_remote_cocoa/web_contents_view_cocoa.h"
#include "content/browser/web_contents/web_contents_view_mac.h"
#include "ui/gfx/image/image_skia_util_mac.h"
@@ -17,8 +18,8 @@ WebContentsNSViewBridge::WebContentsNSViewBridge(
cocoa_view_.reset(
[[WebContentsViewCocoa alloc] initWithViewsHostableView:nullptr]);
[cocoa_view_ setClient:client_.get()];
- view_id_ =
- std::make_unique<ui::ScopedNSViewIdMapping>(view_id, cocoa_view_.get());
+ view_id_ = std::make_unique<remote_cocoa::ScopedNSViewIdMapping>(
+ view_id, cocoa_view_.get());
}
WebContentsNSViewBridge::WebContentsNSViewBridge(
@@ -27,8 +28,8 @@ WebContentsNSViewBridge::WebContentsNSViewBridge(
cocoa_view_.reset([[WebContentsViewCocoa alloc]
initWithViewsHostableView:web_contents_view]);
[cocoa_view_ setClient:web_contents_view];
- view_id_ =
- std::make_unique<ui::ScopedNSViewIdMapping>(view_id, cocoa_view_.get());
+ view_id_ = std::make_unique<remote_cocoa::ScopedNSViewIdMapping>(
+ view_id, cocoa_view_.get());
}
WebContentsNSViewBridge::~WebContentsNSViewBridge() {
@@ -42,7 +43,7 @@ WebContentsNSViewBridge::~WebContentsNSViewBridge() {
}
void WebContentsNSViewBridge::SetParentNSView(uint64_t parent_ns_view_id) {
- NSView* parent_ns_view = ui::NSViewIds::GetNSView(parent_ns_view_id);
+ NSView* parent_ns_view = remote_cocoa::GetNSViewFromId(parent_ns_view_id);
// If the browser passed an invalid handle, then there is no recovery.
CHECK(parent_ns_view);
[parent_ns_view addSubview:cocoa_view_];
diff --git a/chromium/content/browser/web_contents/web_contents_view_cocoa.h b/chromium/content/app_shim_remote_cocoa/web_contents_view_cocoa.h
index a3ba5295d56..48529f4471d 100644
--- a/chromium/content/browser/web_contents/web_contents_view_cocoa.h
+++ b/chromium/content/app_shim_remote_cocoa/web_contents_view_cocoa.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_CONTENTS_WEB_CONTENTS_VIEW_COCOA_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_COCOA_H_
+#ifndef CONTENT_APP_SHIM_REMOTE_COCOA_WEB_CONTENTS_VIEW_COCOA_H_
+#define CONTENT_APP_SHIM_REMOTE_COCOA_WEB_CONTENTS_VIEW_COCOA_H_
#include "base/mac/scoped_nsobject.h"
#include "content/common/content_export.h"
@@ -58,4 +58,4 @@ CONTENT_EXPORT
- (void)viewDidBecomeFirstResponder:(NSNotification*)notification;
@end
-#endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_COCOA_H_
+#endif // CONTENT_APP_SHIM_REMOTE_COCOA_WEB_CONTENTS_VIEW_COCOA_H_
diff --git a/chromium/content/browser/web_contents/web_contents_view_cocoa.mm b/chromium/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm
index b31ddd30304..1bd2729c470 100644
--- a/chromium/content/browser/web_contents/web_contents_view_cocoa.mm
+++ b/chromium/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "content/browser/web_contents/web_contents_view_cocoa.h"
+#import "content/app_shim_remote_cocoa/web_contents_view_cocoa.h"
#import "base/mac/mac_util.h"
#include "base/mac/sdk_forward_declarations.h"
+#import "content/app_shim_remote_cocoa/web_drag_source_mac.h"
#import "content/browser/web_contents/web_drag_dest_mac.h"
-#import "content/browser/web_contents/web_drag_source_mac.h"
-#include "content/public/common/web_contents_ns_view_bridge.mojom.h"
+#include "content/common/web_contents_ns_view_bridge.mojom.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/clipboard/custom_data_helper.h"
diff --git a/chromium/content/browser/web_contents/web_drag_source_mac.h b/chromium/content/app_shim_remote_cocoa/web_drag_source_mac.h
index 169686fc7a7..0a166e3fcf3 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac.h
+++ b/chromium/content/app_shim_remote_cocoa/web_drag_source_mac.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_WEB_CONTENTS_WEB_DRAG_SOURCE_MAC_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_WEB_DRAG_SOURCE_MAC_H_
+#ifndef CONTENT_APP_SHIM_REMOTE_COCOA_WEB_DRAG_SOURCE_MAC_H_
+#define CONTENT_APP_SHIM_REMOTE_COCOA_WEB_DRAG_SOURCE_MAC_H_
#import <Cocoa/Cocoa.h>
@@ -101,4 +101,4 @@ CONTENT_EXPORT
@end
-#endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_DRAG_SOURCE_MAC_H_
+#endif // CONTENT_APP_SHIM_REMOTE_COCOA_WEB_DRAG_SOURCE_MAC_H_
diff --git a/chromium/content/browser/web_contents/web_drag_source_mac.mm b/chromium/content/app_shim_remote_cocoa/web_drag_source_mac.mm
index 8c75ab54f70..d6f709c95e3 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac.mm
+++ b/chromium/content/app_shim_remote_cocoa/web_drag_source_mac.mm
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "content/browser/web_contents/web_drag_source_mac.h"
+#import "content/app_shim_remote_cocoa/web_drag_source_mac.h"
#include <sys/param.h>
@@ -18,10 +18,10 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/download/drag_download_file.h"
#include "content/browser/download/drag_download_util.h"
+#include "content/common/web_contents_ns_view_bridge.mojom.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "content/public/common/drop_data.h"
-#include "content/public/common/web_contents_ns_view_bridge.mojom.h"
#include "net/base/escape.h"
#include "net/base/filename_util.h"
#include "net/base/mime_util.h"
@@ -116,9 +116,8 @@ using content::DropData;
// If NSURL creation failed, check for a badly-escaped JavaScript URL.
// Strip out any existing escapes and then re-escape uniformly.
if (!url && dropData_->url.SchemeIs(url::kJavaScriptScheme)) {
- std::string unescapedUrlString;
- net::UnescapeBinaryURLComponent(dropData_->url.spec(),
- &unescapedUrlString);
+ std::string unescapedUrlString =
+ net::UnescapeBinaryURLComponent(dropData_->url.spec());
std::string escapedUrlString =
net::EscapeUrlEncodedData(unescapedUrlString, false);
url = [NSURL URLWithString:SysUTF8ToNSString(escapedUrlString)];
diff --git a/chromium/content/browser/BUILD.gn b/chromium/content/browser/BUILD.gn
index 78e8ed893a2..62b68955246 100644
--- a/chromium/content/browser/BUILD.gn
+++ b/chromium/content/browser/BUILD.gn
@@ -23,6 +23,7 @@ jumbo_source_set("browser") {
# internal content ones) should depend on the public one.
visibility = [
":for_content_tests", # See top of //content/BUILD.gn for why.
+ ":for_internal_webauthn",
"//content/app:*",
"//content/public/browser:browser_sources",
"//content/test/fuzzer:appcache_fuzzer",
@@ -60,8 +61,10 @@ jumbo_source_set("browser") {
"//components/offline_pages/buildflags",
"//components/offline_pages/core/request_header",
"//components/os_crypt",
+ "//components/payments/content/icon",
"//components/rappor",
"//components/services/filesystem:lib",
+ "//components/services/heap_profiling/public/cpp:manifest",
"//components/services/leveldb:lib",
"//components/tracing",
"//components/tracing:startup_tracing",
@@ -116,10 +119,11 @@ jumbo_source_set("browser") {
"//media/midi",
"//media/midi:mojo",
"//media/mojo:buildflags",
- "//media/mojo/clients:jpeg_decode_accelerator",
"//media/mojo/interfaces",
"//media/mojo/interfaces:constants",
"//media/mojo/services",
+ "//media/mojo/services:cdm_manifest",
+ "//media/mojo/services:media_manifest",
"//media/webrtc",
"//mojo/core/embedder",
"//mojo/public/cpp/bindings",
@@ -133,14 +137,17 @@ jumbo_source_set("browser") {
"//printing/buildflags",
"//services/audio:lib",
"//services/audio/public/cpp",
+ "//services/audio/public/cpp:manifest",
"//services/audio/public/mojom",
"//services/content:impl",
"//services/content/public/cpp",
"//services/content/public/mojom",
"//services/data_decoder/public/cpp",
+ "//services/data_decoder/public/cpp:manifest",
"//services/data_decoder/public/mojom",
"//services/device:lib",
"//services/device/public/cpp:device_features",
+ "//services/device/public/cpp:manifest",
"//services/device/public/cpp/geolocation",
"//services/device/public/mojom",
"//services/device/public/mojom:generic_sensor",
@@ -148,13 +155,17 @@ jumbo_source_set("browser") {
"//services/file/public/mojom",
"//services/media_session:lib",
"//services/media_session/public/cpp",
+ "//services/media_session/public/cpp:manifest",
"//services/media_session/public/mojom",
"//services/metrics",
+ "//services/metrics/public/cpp:manifest",
"//services/metrics/public/cpp:metrics_cpp",
"//services/network:network_service",
"//services/network/public/cpp",
+ "//services/network/public/cpp:manifest",
"//services/network/public/mojom",
"//services/resource_coordinator:lib",
+ "//services/resource_coordinator/public/cpp:manifest",
"//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
"//services/service_manager",
"//services/service_manager/embedder",
@@ -163,15 +174,18 @@ jumbo_source_set("browser") {
"//services/service_manager/public/mojom",
"//services/service_manager/zygote:zygote_buildflags",
"//services/shape_detection:lib",
+ "//services/shape_detection/public/cpp:manifest",
"//services/shape_detection/public/mojom",
"//services/tracing:lib",
"//services/tracing:manifest",
"//services/tracing/public/cpp",
"//services/video_capture:lib",
"//services/video_capture/public/cpp",
+ "//services/video_capture/public/cpp:manifest",
"//services/video_capture/public/mojom:constants",
"//services/video_capture/public/uma",
"//services/viz/privileged/interfaces",
+ "//services/viz/public/cpp:manifest",
"//services/viz/public/interfaces",
"//services/ws/public/cpp/gpu",
"//skia",
@@ -181,11 +195,11 @@ jumbo_source_set("browser") {
"//third_party/angle:angle_common",
"//third_party/blink/public:blink_headers",
"//third_party/blink/public:buildflags",
- "//third_party/blink/public:mojo_bindings",
"//third_party/blink/public:resources",
"//third_party/blink/public:scaled_resources",
"//third_party/blink/public/common",
"//third_party/blink/public/mojom:mojom_broadcastchannel_bindings",
+ "//third_party/blink/public/mojom:web_bluetooth_mojo_bindings",
"//third_party/boringssl",
"//third_party/brotli:dec",
"//third_party/icu",
@@ -230,6 +244,7 @@ jumbo_source_set("browser") {
public_deps = [
":accessibility_buildflags",
+ "//base/util/type_safety",
"//ipc",
"//media/mojo/interfaces:remoting",
"//third_party/blink/public/mojom:embedded_frame_sink_mojo_bindings",
@@ -284,6 +299,8 @@ jumbo_source_set("browser") {
"$target_gen_dir/devtools/protocol/tethering.h",
"$target_gen_dir/devtools/protocol/tracing.cc",
"$target_gen_dir/devtools/protocol/tracing.h",
+ "../app_shim_remote_cocoa/web_drag_source_mac.h",
+ "../app_shim_remote_cocoa/web_drag_source_mac.mm",
"../common/service_manager/child_connection.cc",
"../common/service_manager/child_connection.h",
"about_url_loader_factory.cc",
@@ -519,8 +536,12 @@ jumbo_source_set("browser") {
"bluetooth/bluetooth_blocklist.h",
"bluetooth/bluetooth_device_chooser_controller.cc",
"bluetooth/bluetooth_device_chooser_controller.h",
+ "bluetooth/bluetooth_device_scanning_prompt_controller.cc",
+ "bluetooth/bluetooth_device_scanning_prompt_controller.h",
"bluetooth/bluetooth_metrics.cc",
"bluetooth/bluetooth_metrics.h",
+ "bluetooth/bluetooth_util.cc",
+ "bluetooth/bluetooth_util.h",
"bluetooth/frame_connected_bluetooth_devices.cc",
"bluetooth/frame_connected_bluetooth_devices.h",
"bluetooth/web_bluetooth_service_impl.cc",
@@ -568,6 +589,8 @@ jumbo_source_set("browser") {
"browsing_data/storage_partition_http_cache_data_remover.h",
"browsing_instance.cc",
"browsing_instance.h",
+ "builtin_service_manifests.cc",
+ "builtin_service_manifests.h",
"byte_stream.cc",
"byte_stream.h",
"cache_storage/cache_storage.cc",
@@ -604,6 +627,9 @@ jumbo_source_set("browser") {
"cache_storage/legacy/legacy_cache_storage.h",
"cache_storage/legacy/legacy_cache_storage_cache.cc",
"cache_storage/legacy/legacy_cache_storage_cache.h",
+ "cache_storage/legacy/legacy_cache_storage_manager.cc",
+ "cache_storage/legacy/legacy_cache_storage_manager.h",
+ "cache_storage/scoped_writable_entry.h",
"child_process_launcher.cc",
"child_process_launcher.h",
"child_process_launcher_helper.cc",
@@ -653,8 +679,10 @@ jumbo_source_set("browser") {
"devtools/browser_devtools_agent_host.h",
"devtools/devtools_agent_host_impl.cc",
"devtools/devtools_agent_host_impl.h",
- "devtools/devtools_background_services_context.cc",
- "devtools/devtools_background_services_context.h",
+ "devtools/devtools_background_services_context_impl.cc",
+ "devtools/devtools_background_services_context_impl.h",
+ "devtools/devtools_frame_metadata.cc",
+ "devtools/devtools_frame_metadata.h",
"devtools/devtools_frame_trace_recorder.cc",
"devtools/devtools_frame_trace_recorder.h",
"devtools/devtools_http_handler.cc",
@@ -672,12 +700,12 @@ jumbo_source_set("browser") {
"devtools/devtools_network_transaction_factory.cc",
"devtools/devtools_pipe_handler.cc",
"devtools/devtools_pipe_handler.h",
+ "devtools/devtools_protocol_encoding.cc",
+ "devtools/devtools_protocol_encoding.h",
"devtools/devtools_renderer_channel.cc",
"devtools/devtools_renderer_channel.h",
"devtools/devtools_session.cc",
"devtools/devtools_session.h",
- "devtools/devtools_session_encoding.cc",
- "devtools/devtools_session_encoding.h",
"devtools/devtools_stream_blob.cc",
"devtools/devtools_stream_blob.h",
"devtools/devtools_stream_file.cc",
@@ -853,8 +881,6 @@ jumbo_source_set("browser") {
"file_url_loader_factory.h",
"fileapi/browser_file_system_helper.cc",
"fileapi/browser_file_system_helper.h",
- "fileapi/file_system_chooser.cc",
- "fileapi/file_system_chooser.h",
"fileapi/file_system_manager_impl.cc",
"fileapi/file_system_manager_impl.h",
"fileapi/file_system_url_loader_factory.cc",
@@ -951,7 +977,6 @@ jumbo_source_set("browser") {
"gpu/browser_gpu_client_delegate.h",
"gpu/compositor_util.cc",
"gpu/compositor_util.h",
- "gpu/delegate_to_browser_gpu_service_accelerator_factory.cc",
"gpu/gpu_client.cc",
"gpu/gpu_data_manager_impl.cc",
"gpu/gpu_data_manager_impl.h",
@@ -969,8 +994,6 @@ jumbo_source_set("browser") {
"gpu/gpu_process_host.h",
"gpu/shader_cache_factory.cc",
"gpu/shader_cache_factory.h",
- "gpu/video_capture_dependencies.cc",
- "gpu/video_capture_dependencies.h",
"histogram_controller.cc",
"histogram_controller.h",
"histogram_subscriber.h",
@@ -995,6 +1018,7 @@ jumbo_source_set("browser") {
"indexed_db/indexed_db_backing_store.h",
"indexed_db/indexed_db_blob_info.cc",
"indexed_db/indexed_db_blob_info.h",
+ "indexed_db/indexed_db_callback_helpers.h",
"indexed_db/indexed_db_callbacks.cc",
"indexed_db/indexed_db_callbacks.h",
"indexed_db/indexed_db_class_factory.cc",
@@ -1031,6 +1055,10 @@ jumbo_source_set("browser") {
"indexed_db/indexed_db_metadata_coding.h",
"indexed_db/indexed_db_observer.cc",
"indexed_db/indexed_db_observer.h",
+ "indexed_db/indexed_db_origin_state.cc",
+ "indexed_db/indexed_db_origin_state.h",
+ "indexed_db/indexed_db_origin_state_handle.cc",
+ "indexed_db/indexed_db_origin_state_handle.h",
"indexed_db/indexed_db_pending_connection.cc",
"indexed_db/indexed_db_pending_connection.h",
"indexed_db/indexed_db_pre_close_task_queue.cc",
@@ -1065,8 +1093,15 @@ jumbo_source_set("browser") {
"indexed_db/list_set.h",
"indexed_db/scopes/disjoint_range_lock_manager.cc",
"indexed_db/scopes/disjoint_range_lock_manager.h",
+ "indexed_db/scopes/leveldb_scope.cc",
+ "indexed_db/scopes/leveldb_scope.h",
+ "indexed_db/scopes/leveldb_scope_deletion_mode.h",
+ "indexed_db/scopes/leveldb_scopes.cc",
+ "indexed_db/scopes/leveldb_scopes.h",
"indexed_db/scopes/leveldb_scopes_coding.cc",
"indexed_db/scopes/leveldb_scopes_coding.h",
+ "indexed_db/scopes/leveldb_scopes_factory.cc",
+ "indexed_db/scopes/leveldb_scopes_factory.h",
"indexed_db/scopes/leveldb_scopes_tasks.cc",
"indexed_db/scopes/leveldb_scopes_tasks.h",
"indexed_db/scopes/leveldb_state.cc",
@@ -1092,6 +1127,8 @@ jumbo_source_set("browser") {
"keyboard_lock/keyboard_lock_metrics.h",
"keyboard_lock/keyboard_lock_service_impl.cc",
"keyboard_lock/keyboard_lock_service_impl.h",
+ "loader/cross_origin_read_blocking_checker.cc",
+ "loader/cross_origin_read_blocking_checker.h",
"loader/cross_site_document_resource_handler.cc",
"loader/cross_site_document_resource_handler.h",
"loader/data_pipe_to_source_stream.cc",
@@ -1127,6 +1164,10 @@ jumbo_source_set("browser") {
"loader/prefetch_url_loader.h",
"loader/prefetch_url_loader_service.cc",
"loader/prefetch_url_loader_service.h",
+ "loader/prefetched_signed_exchange_cache.cc",
+ "loader/prefetched_signed_exchange_cache.h",
+ "loader/prefetched_signed_exchange_cache_adapter.cc",
+ "loader/prefetched_signed_exchange_cache_adapter.h",
"loader/resource_controller.h",
"loader/resource_dispatcher_host_impl.cc",
"loader/resource_dispatcher_host_impl.h",
@@ -1141,6 +1182,8 @@ jumbo_source_set("browser") {
"loader/resource_request_info_impl.h",
"loader/resource_requester_info.cc",
"loader/resource_requester_info.h",
+ "loader/sec_fetch_site_resource_handler.cc",
+ "loader/sec_fetch_site_resource_handler.h",
"loader/shared_cors_origin_access_list_impl.cc",
"loader/shared_cors_origin_access_list_impl.h",
"loader/source_stream_to_data_pipe.cc",
@@ -1222,6 +1265,8 @@ jumbo_source_set("browser") {
"media/media_devices_permission_checker.h",
"media/media_devices_util.cc",
"media/media_devices_util.h",
+ "media/media_experiment_manager.cc",
+ "media/media_experiment_manager.h",
"media/media_interface_proxy.cc",
"media/media_interface_proxy.h",
"media/media_internals.cc",
@@ -1283,6 +1328,20 @@ jumbo_source_set("browser") {
"message_port_provider.cc",
"mime_registry_impl.cc",
"mime_registry_impl.h",
+ "native_file_system/file_system_chooser.cc",
+ "native_file_system/file_system_chooser.h",
+ "native_file_system/native_file_system_directory_handle_impl.cc",
+ "native_file_system/native_file_system_directory_handle_impl.h",
+ "native_file_system/native_file_system_file_handle_impl.cc",
+ "native_file_system/native_file_system_file_handle_impl.h",
+ "native_file_system/native_file_system_handle_base.cc",
+ "native_file_system/native_file_system_handle_base.h",
+ "native_file_system/native_file_system_manager_impl.cc",
+ "native_file_system/native_file_system_manager_impl.h",
+ "native_file_system/native_file_system_transfer_token_impl.cc",
+ "native_file_system/native_file_system_transfer_token_impl.h",
+ "navigation_subresource_loader_params.cc",
+ "navigation_subresource_loader_params.h",
"net/browser_online_state_observer.cc",
"net/browser_online_state_observer.h",
"net/network_errors_listing_ui.cc",
@@ -1295,11 +1354,14 @@ jumbo_source_set("browser") {
"net/view_blob_internals_job_factory.h",
"network_service_client.cc",
"network_service_client.h",
- "network_service_instance.cc",
+ "network_service_instance_impl.cc",
+ "network_service_instance_impl.h",
"notification_service_impl.cc",
"notification_service_impl.h",
"notifications/blink_notification_service_impl.cc",
"notifications/blink_notification_service_impl.h",
+ "notifications/devtools_event_logging.cc",
+ "notifications/devtools_event_logging.h",
"notifications/notification_database.cc",
"notifications/notification_database.h",
"notifications/notification_database_conversions.cc",
@@ -1335,10 +1397,10 @@ jumbo_source_set("browser") {
"permissions/permission_service_context.h",
"permissions/permission_service_impl.cc",
"permissions/permission_service_impl.h",
- "picture_in_picture/overlay_surface_embedder.cc",
- "picture_in_picture/overlay_surface_embedder.h",
"picture_in_picture/picture_in_picture_service_impl.cc",
"picture_in_picture/picture_in_picture_service_impl.h",
+ "picture_in_picture/picture_in_picture_session.cc",
+ "picture_in_picture/picture_in_picture_session.h",
"picture_in_picture/picture_in_picture_window_controller_impl.cc",
"picture_in_picture/picture_in_picture_window_controller_impl.h",
"portal/portal.cc",
@@ -1634,12 +1696,14 @@ jumbo_source_set("browser") {
"sandbox_ipc_linux.h",
"sandbox_parameters_mac.h",
"sandbox_parameters_mac.mm",
+ "scheduler/browser_io_task_environment.cc",
+ "scheduler/browser_io_task_environment.h",
"scheduler/browser_task_executor.cc",
"scheduler/browser_task_executor.h",
+ "scheduler/browser_task_queues.cc",
+ "scheduler/browser_task_queues.h",
"scheduler/browser_ui_thread_scheduler.cc",
"scheduler/browser_ui_thread_scheduler.h",
- "scheduler/browser_ui_thread_task_queue.cc",
- "scheduler/browser_ui_thread_task_queue.h",
"scheduler/responsiveness/calculator.cc",
"scheduler/responsiveness/calculator.h",
"scheduler/responsiveness/message_loop_observer.cc",
@@ -1757,6 +1821,14 @@ jumbo_source_set("browser") {
"service_worker/service_worker_version.h",
"site_instance_impl.cc",
"site_instance_impl.h",
+ "sms/sms_manager_impl.cc",
+ "sms/sms_manager_impl.h",
+ "sms/sms_parser.cc",
+ "sms/sms_parser.h",
+ "sms/sms_provider.cc",
+ "sms/sms_provider.h",
+ "sms/sms_service_impl.cc",
+ "sms/sms_service_impl.h",
"speech/speech_recognition_dispatcher_host.cc",
"speech/speech_recognition_dispatcher_host.h",
"speech/speech_recognition_manager_impl.cc",
@@ -1838,8 +1910,10 @@ jumbo_source_set("browser") {
"web_contents/aura/gesture_nav_simple.h",
"web_contents/aura/types.cc",
"web_contents/aura/types.h",
- "web_contents/web_contents_getter_registry.cc",
- "web_contents/web_contents_getter_registry.h",
+ "web_contents/frame_tree_node_id_registry.cc",
+ "web_contents/frame_tree_node_id_registry.h",
+ "web_contents/javascript_dialog_navigation_deferrer.cc",
+ "web_contents/javascript_dialog_navigation_deferrer.h",
"web_contents/web_contents_impl.cc",
"web_contents/web_contents_impl.h",
"web_contents/web_contents_view.h",
@@ -1853,8 +1927,6 @@ jumbo_source_set("browser") {
"web_contents/web_contents_view_mac.mm",
"web_contents/web_drag_dest_mac.h",
"web_contents/web_drag_dest_mac.mm",
- "web_contents/web_drag_source_mac.h",
- "web_contents/web_drag_source_mac.mm",
"web_contents/web_drag_utils_win.cc",
"web_contents/web_drag_utils_win.h",
"web_package/http_structured_header.cc",
@@ -1961,6 +2033,7 @@ jumbo_source_set("browser") {
if (is_linux) {
deps += [
"//components/services/font:lib",
+ "//components/services/font/public/cpp:manifest",
"//components/services/font/public/interfaces",
"//services/service_manager/zygote",
]
@@ -1981,7 +2054,10 @@ jumbo_source_set("browser") {
"tracing/cros_tracing_agent.cc",
"tracing/cros_tracing_agent.h",
]
- deps += [ "//chromeos/resources" ]
+ deps += [
+ "//chromeos/resources",
+ "//components/chromeos_camera:mojo_mjpeg_decode_accelerator",
+ ]
} else {
sources += [
"memory/memory_monitor_linux.cc",
@@ -2031,16 +2107,21 @@ jumbo_source_set("browser") {
if (is_mac) {
sources += [
+ "../app_shim_remote_cocoa/web_contents_ns_view_bridge.h",
+ "../app_shim_remote_cocoa/web_contents_ns_view_bridge.mm",
"gpu/ca_transaction_gpu_coordinator.cc",
"gpu/ca_transaction_gpu_coordinator.h",
"media/now_playing_info_center_notifier.cc",
"media/now_playing_info_center_notifier.h",
"sandbox_support_mac_impl.h",
"sandbox_support_mac_impl.mm",
- "web_contents/web_contents_ns_view_bridge.h",
- "web_contents/web_contents_ns_view_bridge.mm",
]
- deps += [ "//ui/events:dom_keyboard_layout" ]
+ deps += [
+ "//components/remote_cocoa/app_shim",
+ "//components/remote_cocoa/browser",
+ "//components/remote_cocoa/common:mojo",
+ "//ui/events:dom_keyboard_layout",
+ ]
}
if (!is_mac) {
@@ -2194,6 +2275,17 @@ jumbo_source_set("browser") {
"renderer_host/pepper/pepper_tcp_server_socket_message_filter.h",
"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_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_host.cc",
+ "renderer_host/pepper/pepper_truetype_font_list_host.h",
+ "renderer_host/pepper/pepper_truetype_font_list_mac.mm",
+ "renderer_host/pepper/pepper_truetype_font_list_win.cc",
+ "renderer_host/pepper/pepper_truetype_font_mac.mm",
+ "renderer_host/pepper/pepper_truetype_font_win.cc",
"renderer_host/pepper/pepper_udp_socket_message_filter.cc",
"renderer_host/pepper/pepper_udp_socket_message_filter.h",
"renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.cc",
@@ -2209,6 +2301,12 @@ jumbo_source_set("browser") {
"//ppapi/proxy:ipc",
"//ppapi/shared_impl",
]
+ if (use_ozone) {
+ sources += [ "renderer_host/pepper/pepper_truetype_font_list_ozone.cc" ]
+ }
+ if (use_pangocairo) {
+ sources += [ "renderer_host/pepper/pepper_truetype_font_list_pango.cc" ]
+ }
if (is_linux) {
deps += [ "//components/services/font:ppapi_fontconfig_matching" ]
}
@@ -2355,6 +2453,8 @@ jumbo_source_set("browser") {
"renderer_host/render_widget_host_view_android.h",
"screen_orientation/screen_orientation_delegate_android.cc",
"screen_orientation/screen_orientation_delegate_android.h",
+ "sms/sms_provider_android.cc",
+ "sms/sms_provider_android.h",
"web_contents/web_contents_android.cc",
"web_contents/web_contents_android.h",
"web_contents/web_contents_view_android.cc",
@@ -2404,12 +2504,23 @@ jumbo_source_set("browser") {
"ENABLE_SCREEN_CAPTURE=1",
]
libs += [ "jnigraphics" ]
+
+ if (notouch_build) {
+ # There should be an API to let the embedder control this.
+ defines += [ "DISABLE_OVERSCROLL" ]
+ }
} else {
# Not Android.
sources += [
+ # The WebAuthn devtools protocol API is not supported in Android yet.
+ "$target_gen_dir/devtools/protocol/web_authn.cc",
+ "$target_gen_dir/devtools/protocol/web_authn.h",
+
# Devtools frontend not included in Android
"devtools/devtools_frontend_host_impl.cc",
"devtools/devtools_frontend_host_impl.h",
+ "devtools/protocol/webauthn_handler.cc",
+ "devtools/protocol/webauthn_handler.h",
"host_zoom_level_context.cc",
"host_zoom_level_context.h",
"host_zoom_map_impl.cc",
@@ -2421,6 +2532,10 @@ jumbo_source_set("browser") {
"serial/serial_service.cc",
"serial/serial_service.h",
+ # The SMS API is stubbed out outside of Android.
+ "sms/sms_provider_desktop.cc",
+ "sms/sms_provider_desktop.h",
+
# Most speech code is non-Android.
"speech/audio_buffer.cc",
"speech/audio_buffer.h",
@@ -2442,17 +2557,20 @@ jumbo_source_set("browser") {
# Most webauth code is non-Android
"webauth/authenticator_common.cc",
"webauth/authenticator_common.h",
+ "webauth/authenticator_environment_impl.cc",
+ "webauth/authenticator_environment_impl.h",
"webauth/authenticator_impl.cc",
"webauth/authenticator_impl.h",
"webauth/authenticator_type_converters.cc",
"webauth/authenticator_type_converters.h",
- "webauth/scoped_virtual_authenticator_environment.cc",
- "webauth/scoped_virtual_authenticator_environment.h",
"webauth/virtual_authenticator.cc",
"webauth/virtual_authenticator.h",
"webauth/virtual_discovery.cc",
"webauth/virtual_discovery.h",
+ "webauth/virtual_fido_discovery_factory.cc",
+ "webauth/virtual_fido_discovery_factory.h",
]
+
deps += [ "//third_party/flac" ]
}
@@ -2469,21 +2587,26 @@ jumbo_source_set("browser") {
"IOSurface.framework",
]
sources += [
- "ns_view_bridge_factory_host.mm",
- "ns_view_bridge_factory_impl.mm",
- "renderer_host/popup_window_mac.h",
- "renderer_host/popup_window_mac.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_helper.h",
- "renderer_host/render_widget_host_view_cocoa.h",
- "renderer_host/render_widget_host_view_cocoa.mm",
- "web_contents/web_contents_view_cocoa.h",
- "web_contents/web_contents_view_cocoa.mm",
+ "../app_shim_remote_cocoa/ns_view_bridge_factory_impl.mm",
+ "../app_shim_remote_cocoa/popup_window_mac.h",
+ "../app_shim_remote_cocoa/popup_window_mac.mm",
+ "../app_shim_remote_cocoa/render_widget_host_ns_view_bridge_local.h",
+ "../app_shim_remote_cocoa/render_widget_host_ns_view_bridge_local.mm",
+ "../app_shim_remote_cocoa/render_widget_host_ns_view_client_helper.h",
+ "../app_shim_remote_cocoa/render_widget_host_view_cocoa.h",
+ "../app_shim_remote_cocoa/render_widget_host_view_cocoa.mm",
+ "../app_shim_remote_cocoa/web_contents_view_cocoa.h",
+ "../app_shim_remote_cocoa/web_contents_view_cocoa.mm",
]
}
if (is_chromeos) {
+ sources += [
+ "gpu/chromeos/delegate_to_browser_gpu_service_accelerator_factory.cc",
+ "gpu/chromeos/video_capture_dependencies.cc",
+ "gpu/chromeos/video_capture_dependencies.h",
+ ]
+
deps += [
"//chromeos/assistant:buildflags",
"//chromeos/audio",
@@ -2497,12 +2620,14 @@ jumbo_source_set("browser") {
}
if (enable_cros_libassistant) {
- deps += [ "//chromeos/services/assistant/public/mojom" ]
+ deps += [
+ "//chromeos/services/assistant/public/cpp:audio_decoder_manifest",
+ "//chromeos/services/assistant/public/mojom",
+ ]
}
if (use_aura) {
deps += [
- "//services/ws/public/cpp",
"//services/ws/public/cpp/host",
"//services/ws/public/mojom",
"//ui/aura",
@@ -2546,8 +2671,6 @@ jumbo_source_set("browser") {
"compositor/browser_compositor_output_surface.h",
"compositor/gpu_browser_compositor_output_surface.cc",
"compositor/gpu_browser_compositor_output_surface.h",
- "compositor/gpu_output_surface_mac.cc",
- "compositor/gpu_output_surface_mac.h",
"compositor/gpu_process_transport_factory.cc",
"compositor/gpu_process_transport_factory.h",
"compositor/gpu_surfaceless_browser_compositor_output_surface.cc",
@@ -2572,16 +2695,6 @@ jumbo_source_set("browser") {
"renderer_host/delegated_frame_host.cc",
"renderer_host/delegated_frame_host.h",
]
- if (is_mac) {
- jumbo_excluded_sources = [
- # Both Mac SDK headers and third_party/khronos/GLES2/gl2ext.h
- # declare macros GL_LINES_ADJACENCY_EXT, GL_LINE_STRIP_ADJACENCY_EXT,
- # GL_TRIANGLES_ADJACENCY_EXT and GL_TRIANGLE_STRIP_ADJACENCY_EXT. They
- # get the same values but with different formatting (0xD vs 0x000D).
- # https://crbug.com/783666
- "compositor/gpu_output_surface_mac.cc",
- ]
- }
deps += [
"//components/viz/service",
"//ui/compositor",
@@ -2667,3 +2780,13 @@ group("for_content_tests") {
]
}
}
+
+# Meant for internal components to facilitate WebAuthn.
+group("for_internal_webauthn") {
+ visibility = [ "//components/autofill/content/browser/webauthn" ]
+ if (!is_component_build) {
+ public_deps = [
+ ":browser",
+ ]
+ }
+}
diff --git a/chromium/content/browser/DEPS b/chromium/content/browser/DEPS
index edc485a8651..3dd1ab489cb 100644
--- a/chromium/content/browser/DEPS
+++ b/chromium/content/browser/DEPS
@@ -22,6 +22,7 @@ include_rules = [
"+components/payments",
"+components/profile_service",
"+components/rappor/public",
+ "+components/services/heap_profiling/public",
"+components/tracing",
"+components/ukm",
"+components/url_formatter",
@@ -108,6 +109,7 @@ include_rules = [
"+third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h",
"+third_party/blink/public/platform/modules/notifications/web_notification_constants.h",
"+third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h",
+ "+third_party/blink/public/platform/modules/sms/sms_manager.mojom.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",
@@ -125,13 +127,6 @@ include_rules = [
"+third_party/blink/public/web/web_tree_scope_type.h",
"+third_party/blink/public/web/web_triggering_event_info.h",
- # Allow mojo generated files in WebKit. These files use STL types and
- # don't use WTF types.
- "+third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h",
- "+third_party/blink/public/platform/modules/cookie_store/cookie_store.mojom.h",
- "+third_party/blink/public/platform/modules/mediastream/media_devices.mojom.h",
- "+third_party/blink/public/platform/modules/websockets/websocket.mojom.h",
-
# DO NOT ADD ANY CHROME OR COMPONENTS INCLUDES HERE!!!
# See https://sites.google.com/a/chromium.org/dev/developers/content-module
# for more information.
@@ -141,6 +136,5 @@ specific_include_rules = {
# To share values of UMA enums between product code and tests.
"cross_site_document_blocking_browsertest.cc": [
"+services/network/cross_origin_read_blocking.h",
- "+services/network/initiator_lock_compatibility.h",
],
}
diff --git a/chromium/content/browser/OWNERS b/chromium/content/browser/OWNERS
index 6e40c8f6579..f62fe26283e 100644
--- a/chromium/content/browser/OWNERS
+++ b/chromium/content/browser/OWNERS
@@ -30,3 +30,9 @@ per-file sandbox_mac_unittest.*=file://sandbox/mac/OWNERS
# Linux sandboxing.
per-file sandbox_host_linux.*=file://sandbox/linux/OWNERS
per-file sandbox_ipc_linux.*=file://sandbox/linux/OWNERS
+
+# Service manifests provided by content require security review
+per-file builtin_service_manifests.cc=set noparent
+per-file builtin_service_manifests.cc=file://ipc/SECURITY_OWNERS
+per-file builtin_service_manifests.h=set noparent
+per-file builtin_service_manifests.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/browser/accessibility/OWNERS b/chromium/content/browser/accessibility/OWNERS
index b6fb1fb8c5b..4450a80e765 100644
--- a/chromium/content/browser/accessibility/OWNERS
+++ b/chromium/content/browser/accessibility/OWNERS
@@ -4,5 +4,13 @@ file://ui/accessibility/OWNERS
jdiggs@igalia.com
mrobinson@igalia.com
+# For Windows / UIA
+per-file *_win*=kschmi@microsoft.com
+per-file *_win*=kbabbitt@microsoft.com
+per-file *_win*=iapres@microsoft.com
+per-file *test*=kschmi@microsoft.com
+per-file *test*=kbabbitt@microsoft.com
+per-file *test*=iapres@microsoft.com
+
# TEAM: chromium-accessibility@chromium.org
# COMPONENT: UI>Accessibility
diff --git a/chromium/content/browser/accessibility/accessibility_action_browsertest.cc b/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
index 925da6605c7..b38f11a7db1 100644
--- a/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
@@ -115,7 +115,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, FocusAction) {
waiter2.WaitForNotification();
BrowserAccessibility* focus = GetManager()->GetFocus();
- EXPECT_EQ(focus->GetId(), target->GetId());
+ ASSERT_NE(nullptr, focus);
+ EXPECT_EQ(target->GetId(), focus->GetId());
}
IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest,
diff --git a/chromium/content/browser/accessibility/accessibility_auralinux_browsertest.cc b/chromium/content/browser/accessibility/accessibility_auralinux_browsertest.cc
index 7335c1f4ab5..649e794d531 100644
--- a/chromium/content/browser/accessibility/accessibility_auralinux_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_auralinux_browsertest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <atk/atk.h>
+#include <dlfcn.h>
#include "base/bind_helpers.h"
#include "base/macros.h"
@@ -18,6 +19,19 @@
namespace content {
+namespace {
+
+AtkObject* FindAtkObjectParentFrame(AtkObject* atk_object) {
+ while (atk_object) {
+ if (atk_object_get_role(atk_object) == ATK_ROLE_FRAME)
+ return atk_object;
+ atk_object = atk_object_get_parent(atk_object);
+ }
+ return nullptr;
+}
+
+} // namespace
+
class AccessibilityAuraLinuxBrowserTest : public AccessibilityBrowserTest {
public:
AccessibilityAuraLinuxBrowserTest() = default;
@@ -43,8 +57,9 @@ class AccessibilityAuraLinuxBrowserTest : public AccessibilityBrowserTest {
AtkText* SetUpInputField();
AtkText* SetUpTextareaField();
AtkText* SetUpSampleParagraph();
- AtkText* SetUpSampleParagraphInScrollableEditable();
+ AtkText* SetUpSampleParagraphInScrollableDocument();
+ AtkText* GetSampleParagraph();
AtkText* GetAtkTextForChild(AtkRole expected_role);
private:
@@ -104,10 +119,7 @@ AtkText* AccessibilityAuraLinuxBrowserTest::SetUpSampleParagraph() {
return ATK_TEXT(input);
}
-AtkText*
-AccessibilityAuraLinuxBrowserTest::SetUpSampleParagraphInScrollableEditable() {
- LoadSampleParagraphInScrollableEditable();
-
+AtkText* AccessibilityAuraLinuxBrowserTest::GetSampleParagraph() {
AtkObject* document = GetRendererAccessible();
EXPECT_EQ(1, atk_object_get_n_accessible_children(document));
@@ -181,6 +193,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
CheckTextAtOffset(atk_text, 0, ATK_TEXT_BOUNDARY_LINE_START, 0,
InputContentsString().size(),
InputContentsString().c_str());
+
+ g_object_unref(atk_text);
}
IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
@@ -197,6 +211,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
// Last line does not have a trailing newline.
CheckTextAtOffset(atk_text, 32, ATK_TEXT_BOUNDARY_LINE_START, 32,
InputContentsString().size(), "\"KHTML, like\".");
+
+ g_object_unref(atk_text);
}
IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
@@ -224,6 +240,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
n_characters,
"cooperation between intelligent rational decision-makers.\"");
}
+
+ g_object_unref(atk_text);
}
#if defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 30, 0)
@@ -286,6 +304,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
EXPECT_EQ(0, y);
EXPECT_EQ(0, width);
EXPECT_EQ(0, height);
+
+ g_object_unref(atk_text);
}
AtkCoordType kCoordinateTypes[] = {
@@ -388,12 +408,16 @@ IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
EXPECT_EQ(combined_extents.height(), atk_rect.height);
}
}
+
+ g_object_unref(atk_text);
}
IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
TestCharacterExtentsInScrollableEditable) {
+ LoadSampleParagraphInScrollableEditable();
+
// By construction, only the first line of the content editable is visible.
- AtkText* atk_text = SetUpSampleParagraphInScrollableEditable();
+ AtkText* atk_text = GetSampleParagraph();
constexpr int first_line_end = 5;
constexpr int last_line_start = 8;
@@ -465,6 +489,410 @@ IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
EXPECT_EQ(previous_height, height);
}
}
+
+ g_object_unref(atk_text);
+}
+
+#if defined(ATK_230)
+typedef bool (*ScrollToPointFunc)(AtkComponent* component,
+ AtkCoordType coords,
+ gint x,
+ gint y);
+typedef bool (*ScrollToFunc)(AtkComponent* component, AtkScrollType type);
+
+IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest, TestScrollToPoint) {
+ // There's a chance we may be compiled with a newer version of ATK and then
+ // run with an older one, so we need to do a runtime check for this method
+ // that is available in ATK 2.30 instead of linking directly.
+ ScrollToPointFunc scroll_to_point = reinterpret_cast<ScrollToPointFunc>(
+ dlsym(RTLD_DEFAULT, "atk_component_scroll_to_point"));
+ if (!scroll_to_point) {
+ LOG(WARNING)
+ << "Skipping AccessibilityAuraLinuxBrowserTest::TestScrollToPoint"
+ " because ATK version < 2.30 detected.";
+ return;
+ }
+
+ LoadSampleParagraphInScrollableDocument();
+ AtkText* atk_text = GetSampleParagraph();
+ ASSERT_TRUE(ATK_IS_COMPONENT(atk_text));
+ AtkComponent* atk_component = ATK_COMPONENT(atk_text);
+
+ int prev_x, prev_y, x, y;
+ atk_component_get_extents(atk_component, &prev_x, &prev_y, nullptr, nullptr,
+ ATK_XY_SCREEN);
+
+ AccessibilityNotificationWaiter location_changed_waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kLocationChanged);
+ scroll_to_point(atk_component, ATK_XY_PARENT, 0, 0);
+ location_changed_waiter.WaitForNotification();
+
+ atk_component_get_extents(atk_component, &x, &y, nullptr, nullptr,
+ ATK_XY_SCREEN);
+ EXPECT_EQ(prev_x, x);
+ EXPECT_GT(prev_y, y);
+
+ constexpr int kScrollToY = 0;
+ scroll_to_point(atk_component, ATK_XY_SCREEN, 0, kScrollToY);
+ location_changed_waiter.WaitForNotification();
+ atk_component_get_extents(atk_component, &x, &y, nullptr, nullptr,
+ ATK_XY_SCREEN);
+ EXPECT_EQ(kScrollToY, y);
+
+ constexpr int kScrollToY_2 = 243;
+ scroll_to_point(atk_component, ATK_XY_SCREEN, 0, kScrollToY_2);
+ location_changed_waiter.WaitForNotification();
+ atk_component_get_extents(atk_component, nullptr, &y, nullptr, nullptr,
+ ATK_XY_SCREEN);
+ EXPECT_EQ(kScrollToY_2, y);
+
+ scroll_to_point(atk_component, ATK_XY_SCREEN, 0, 129);
+ location_changed_waiter.WaitForNotification();
+ atk_component_get_extents(atk_component, nullptr, &y, nullptr, nullptr,
+ ATK_XY_SCREEN);
+
+ AtkObject* frame = FindAtkObjectParentFrame(ATK_OBJECT(atk_component));
+ int frame_y;
+ atk_component_get_extents(ATK_COMPONENT(frame), nullptr, &frame_y, nullptr,
+ nullptr, ATK_XY_SCREEN);
+ EXPECT_EQ(frame_y, y);
+
+ g_object_unref(atk_text);
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest, TestScrollTo) {
+ // There's a chance we may be compiled with a newer version of ATK and then
+ // run with an older one, so we need to do a runtime check for this method
+ // that is available in ATK 2.30 instead of linking directly.
+ ScrollToFunc scroll_to = reinterpret_cast<ScrollToFunc>(
+ dlsym(RTLD_DEFAULT, "atk_component_scroll_to"));
+ if (!scroll_to) {
+ LOG(WARNING) << "Skipping AccessibilityAuraLinuxBrowserTest::TestScrollTo"
+ " because ATK version < 2.30 detected.";
+ return;
+ }
+
+ LoadInitialAccessibilityTreeFromHtml(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <div style="height: 5000px; width: 5000px;"></div>
+ <img style="display: relative; left: 1000px;" alt="Target1">
+ <div style="height: 5000px;"></div>
+ <img style="display: relative; left: 1000px;" alt="Target2">
+ <div style="height: 5000px;"></div>
+ <span>Target 3</span>
+ <div style="height: 5000px;"></div>
+ </body>
+ </html>)HTML");
+
+ // Retrieve the AtkObject interface for the document node.
+ AtkObject* document = GetRendererAccessible();
+ ASSERT_TRUE(ATK_IS_COMPONENT(document));
+
+ // Get the dimensions of the document.
+ int doc_x, doc_y, doc_width, doc_height;
+ atk_component_get_extents(ATK_COMPONENT(document), &doc_x, &doc_y, &doc_width,
+ &doc_height, ATK_XY_SCREEN);
+
+ // The document should only have three children, two img elements
+ // and a single span element.
+ ASSERT_EQ(3, atk_object_get_n_accessible_children(document));
+
+ AtkObject* target = atk_object_ref_accessible_child(document, 0);
+ AtkObject* target2 = atk_object_ref_accessible_child(document, 1);
+ AtkObject* target3 = atk_object_ref_accessible_child(document, 2);
+
+ ASSERT_TRUE(ATK_IS_COMPONENT(target));
+ ASSERT_TRUE(ATK_IS_COMPONENT(target2));
+ ASSERT_TRUE(ATK_IS_COMPONENT(target3));
+
+ ASSERT_EQ(ATK_ROLE_IMAGE, atk_object_get_role(target));
+ ASSERT_EQ(ATK_ROLE_IMAGE, atk_object_get_role(target2));
+
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kScrollPositionChanged);
+ ASSERT_TRUE(scroll_to(ATK_COMPONENT(target), ATK_SCROLL_TOP_EDGE));
+ waiter.WaitForNotification();
+ int x, y;
+ atk_component_get_extents(ATK_COMPONENT(target), &x, &y, nullptr, nullptr,
+ ATK_XY_SCREEN);
+ EXPECT_EQ(y, doc_y);
+ EXPECT_NE(x, doc_x);
+
+ ASSERT_TRUE(scroll_to(ATK_COMPONENT(target), ATK_SCROLL_TOP_LEFT));
+ waiter.WaitForNotification();
+ atk_component_get_extents(ATK_COMPONENT(target), &x, &y, nullptr, nullptr,
+ ATK_XY_SCREEN);
+ EXPECT_EQ(y, doc_y);
+ EXPECT_EQ(x, doc_x);
+
+ ASSERT_TRUE(scroll_to(ATK_COMPONENT(target), ATK_SCROLL_BOTTOM_EDGE));
+ waiter.WaitForNotification();
+ atk_component_get_extents(ATK_COMPONENT(target), &x, &y, nullptr, nullptr,
+ ATK_XY_SCREEN);
+ EXPECT_NE(y, doc_y);
+ EXPECT_EQ(x, doc_x);
+
+ ASSERT_TRUE(scroll_to(ATK_COMPONENT(target), ATK_SCROLL_RIGHT_EDGE));
+ waiter.WaitForNotification();
+ atk_component_get_extents(ATK_COMPONENT(target), &x, &y, nullptr, nullptr,
+ ATK_XY_SCREEN);
+ EXPECT_NE(y, doc_y);
+ EXPECT_NE(x, doc_x);
+
+ ASSERT_TRUE(scroll_to(ATK_COMPONENT(target2), ATK_SCROLL_LEFT_EDGE));
+ waiter.WaitForNotification();
+ atk_component_get_extents(ATK_COMPONENT(target2), &x, &y, nullptr, nullptr,
+ ATK_XY_SCREEN);
+ EXPECT_NE(y, doc_y);
+ EXPECT_EQ(x, doc_x);
+
+ ASSERT_TRUE(scroll_to(ATK_COMPONENT(target2), ATK_SCROLL_TOP_LEFT));
+ waiter.WaitForNotification();
+ atk_component_get_extents(ATK_COMPONENT(target2), &x, &y, nullptr, nullptr,
+ ATK_XY_SCREEN);
+ EXPECT_EQ(y, doc_y);
+ EXPECT_EQ(x, doc_x);
+
+ // Orca expects atk_text_set_caret_offset to operate like scroll to the
+ // target node like atk_component_scroll_to, so we test that here.
+ ASSERT_TRUE(ATK_IS_TEXT(target3));
+ AccessibilityNotificationWaiter waiter3(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kScrollPositionChanged);
+ atk_text_set_caret_offset(ATK_TEXT(target3), 0);
+ waiter3.WaitForNotification();
+
+ // Same as above, make sure the node is roughly centered.
+ int width, height;
+ atk_component_get_extents(ATK_COMPONENT(target3), &x, &y, &width, &height,
+ ATK_XY_SCREEN);
+ EXPECT_GT(y + height / 2, doc_y + 0.4 * doc_height);
+ EXPECT_LT(y + height / 2, doc_y + 0.6 * doc_height);
+
+ g_object_unref(target);
+ g_object_unref(target2);
+ g_object_unref(target3);
+}
+#endif // defined(ATK_230)
+
+IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest, TestSetSelection) {
+ AtkText* atk_text = SetUpInputField();
+
+ int start_offset, end_offset;
+ gchar* selected_text =
+ atk_text_get_selection(atk_text, 0, &start_offset, &end_offset);
+ EXPECT_EQ(nullptr, selected_text);
+ EXPECT_EQ(0, start_offset);
+ EXPECT_EQ(0, end_offset);
+
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kTextSelectionChanged);
+ int contents_string_length = int{InputContentsString().size()};
+ start_offset = 0;
+ end_offset = contents_string_length;
+
+ EXPECT_TRUE(atk_text_set_selection(atk_text, 0, start_offset, end_offset));
+ waiter.WaitForNotification();
+ selected_text =
+ atk_text_get_selection(atk_text, 0, &start_offset, &end_offset);
+ EXPECT_NE(nullptr, selected_text);
+ EXPECT_EQ(0, start_offset);
+ EXPECT_EQ(contents_string_length, end_offset);
+ g_free(selected_text);
+
+ start_offset = contents_string_length;
+ end_offset = 1;
+ EXPECT_TRUE(atk_text_set_selection(atk_text, 0, start_offset, end_offset));
+ waiter.WaitForNotification();
+ selected_text =
+ atk_text_get_selection(atk_text, 0, &start_offset, &end_offset);
+ EXPECT_NE(nullptr, selected_text);
+ EXPECT_EQ(1, start_offset);
+ EXPECT_EQ(contents_string_length, end_offset);
+ g_free(selected_text);
+
+ g_object_unref(atk_text);
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest, TestAtkTextListItem) {
+ LoadInitialAccessibilityTreeFromHtml(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <li>Text 1</li>
+ <li>Text 2</li>
+ <li>Text 3</li>
+ </body>
+ </html>)HTML");
+
+ // Retrieve the AtkObject interface for the document node.
+ AtkObject* document = GetRendererAccessible();
+ EXPECT_EQ(3, atk_object_get_n_accessible_children(document));
+ AtkObject* list_item_1 = atk_object_ref_accessible_child(document, 0);
+ AtkObject* list_item_2 = atk_object_ref_accessible_child(document, 1);
+
+ EXPECT_TRUE(ATK_IS_TEXT(list_item_1));
+
+ const base::string16 string16_embed(
+ 1, ui::AXPlatformNodeAuraLinux::kEmbeddedCharacter);
+ std::string expected_string = base::UTF16ToUTF8(string16_embed) + "Text 1";
+
+ // The text of the list item should include the list marker as an embedded
+ // object.
+ gchar* text = atk_text_get_text(ATK_TEXT(list_item_1), 0, -1);
+ ASSERT_STREQ(text, expected_string.c_str());
+ g_free(text);
+ text = atk_text_get_text_at_offset(
+ ATK_TEXT(list_item_2), 0, ATK_TEXT_BOUNDARY_WORD_START, nullptr, nullptr);
+ ASSERT_STREQ(text, base::UTF16ToUTF8(string16_embed).c_str());
+ g_free(text);
+
+ text = atk_text_get_text_at_offset(
+ ATK_TEXT(list_item_2), 1, ATK_TEXT_BOUNDARY_WORD_START, nullptr, nullptr);
+ ASSERT_STREQ(text, "Text ");
+ g_free(text);
+
+ g_object_unref(list_item_1);
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
+ TestSetCaretSetsSequentialFocusNavigationStartingPoint) {
+ LoadInitialAccessibilityTreeFromHtml(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <div>
+ 0
+ <a href="http://google.com">1</a>
+ 2
+ <a href="http://google.com">3</a>
+ 4
+ <a href="http://google.com">5</a>
+ 6
+ <a href="http://google.com">7</a>
+ 8
+ </div>
+ </body>
+ </html>)HTML");
+
+ // Retrieve the AtkObject interface for the document node.
+ AtkObject* document = GetRendererAccessible();
+ ASSERT_TRUE(ATK_IS_COMPONENT(document));
+
+ AtkObject* parent_div = atk_object_ref_accessible_child(document, 0);
+ EXPECT_NE(parent_div, nullptr);
+
+ AtkObject* child_2 = atk_object_ref_accessible_child(parent_div, 2);
+ AtkObject* child_3 = atk_object_ref_accessible_child(parent_div, 3);
+ AtkObject* child_7 = atk_object_ref_accessible_child(parent_div, 7);
+ EXPECT_NE(child_2, nullptr);
+ EXPECT_NE(child_3, nullptr);
+ EXPECT_NE(child_7, nullptr);
+
+ // Move the caret to the "3" div. This should also set the sequential
+ // focus navigation starting point.
+ atk_text_set_caret_offset(ATK_TEXT(child_2), 0);
+
+ auto waiter = std::make_unique<AccessibilityNotificationWaiter>(
+ shell()->web_contents(), ui::kAXModeComplete, ax::mojom::Event::kFocus);
+
+ // Now send two tab presses to advance the focus.
+ // TODO(mrobinson): For some reason, in the test harness two tabs are
+ // necessary to advance focus after setting the selection (caret). This isn't
+ // necessary when running interactively.
+ SimulateKeyPress(shell()->web_contents(), ui::DomKey::TAB, ui::DomCode::TAB,
+ ui::VKEY_TAB, false, false, false, false);
+ waiter->WaitForNotification();
+
+ SimulateKeyPress(shell()->web_contents(), ui::DomKey::TAB, ui::DomCode::TAB,
+ ui::VKEY_TAB, false, false, false, false);
+ waiter->WaitForNotification();
+
+ AtkStateSet* state_set = atk_object_ref_state_set(child_3);
+ ASSERT_TRUE(atk_state_set_contains_state(state_set, ATK_STATE_FOCUSED));
+ g_object_unref(state_set);
+
+ // Now we repeat a similar test, but this time setting the caret offset
+ // on the parent node. In this case, the sequential navigation starting
+ // point should move to the appropriate child.
+ atk_text_set_caret_offset(ATK_TEXT(parent_div), 13);
+ SimulateKeyPress(shell()->web_contents(), ui::DomKey::TAB, ui::DomCode::TAB,
+ ui::VKEY_TAB, false, false, false, false);
+ waiter->WaitForNotification();
+
+ SimulateKeyPress(shell()->web_contents(), ui::DomKey::TAB, ui::DomCode::TAB,
+ ui::VKEY_TAB, false, false, false, false);
+ waiter->WaitForNotification();
+
+ state_set = atk_object_ref_state_set(child_7);
+ ASSERT_TRUE(atk_state_set_contains_state(state_set, ATK_STATE_FOCUSED));
+ g_object_unref(state_set);
+
+ // Now test setting the caret in a node that can accept focus. That
+ // node should actually receive focus.
+ atk_text_set_caret_offset(ATK_TEXT(child_3), 0);
+ SimulateKeyPress(shell()->web_contents(), ui::DomKey::TAB, ui::DomCode::TAB,
+ ui::VKEY_TAB, false, false, false, false);
+ waiter->WaitForNotification();
+ state_set = atk_object_ref_state_set(child_3);
+ ASSERT_TRUE(atk_state_set_contains_state(state_set, ATK_STATE_FOCUSED));
+ g_object_unref(state_set);
+
+ g_object_unref(child_2);
+ g_object_unref(child_3);
+ g_object_unref(child_7);
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
+ TestTextEventsInStaticText) {
+ LoadInitialAccessibilityTreeFromHtml(std::string(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <div contenteditable="true">Text inside field</div>
+ </body>
+ </html>)HTML"));
+
+ AtkObject* document = GetRendererAccessible();
+ EXPECT_EQ(1, atk_object_get_n_accessible_children(document));
+
+ AtkText* div_element = ATK_TEXT(atk_object_ref_accessible_child(document, 0));
+ EXPECT_EQ(1, atk_object_get_n_accessible_children(ATK_OBJECT(div_element)));
+ AtkText* text =
+ ATK_TEXT(atk_object_ref_accessible_child(ATK_OBJECT(div_element), 0));
+
+ auto callback = G_CALLBACK(+[](AtkText*, gint, bool* flag) { *flag = true; });
+ bool saw_caret_move_in_text = false;
+ bool saw_caret_move_in_div = false;
+ g_signal_connect(text, "text-caret-moved", callback, &saw_caret_move_in_text);
+ g_signal_connect(div_element, "text-caret-moved", callback,
+ &saw_caret_move_in_div);
+
+ AccessibilityNotificationWaiter selection_waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kTextSelectionChanged);
+ ExecuteScript(base::UTF8ToUTF16(
+ "let selection = document.getSelection();"
+ "let editable = document.querySelector('div[contenteditable=\"true\"]');"
+ "editable.focus();"
+ "let range = document.createRange();"
+ "range.setStart(editable.lastChild, 4);"
+ "range.setEnd(editable.lastChild, 4);"
+ "selection.removeAllRanges();"
+ "selection.addRange(range);"));
+ selection_waiter.WaitForNotification();
+
+ // We should see the event happen in div and not the static text element.
+ EXPECT_TRUE(saw_caret_move_in_div);
+ EXPECT_FALSE(saw_caret_move_in_text);
+
+ g_object_unref(div_element);
+ g_object_unref(text);
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_browsertest.cc b/chromium/content/browser/accessibility/accessibility_browsertest.cc
index 6f43f2094c0..f480a902f34 100644
--- a/chromium/content/browser/accessibility/accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_browsertest.cc
@@ -113,6 +113,25 @@ void AccessibilityBrowserTest::LoadSampleParagraphInScrollableEditable() {
selection_waiter.WaitForNotification();
}
+// Loads a page with a paragraph of sample text which is below the
+// bottom of the screen.
+void AccessibilityBrowserTest::LoadSampleParagraphInScrollableDocument(
+ ui::AXMode accessibility_mode) {
+ LoadInitialAccessibilityTreeFromHtml(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <p style="margin-top:50vh; margin-bottom:200vh">
+ <b>Game theory</b> is "the study of
+ <a href="" title="Mathematical model">mathematical models</a>
+ of conflict and<br>cooperation between intelligent rational
+ decision-makers."
+ </p>
+ </body>
+ </html>)HTML",
+ accessibility_mode);
+}
+
// static
std::string AccessibilityBrowserTest::InputContentsString() {
return kInputContents;
diff --git a/chromium/content/browser/accessibility/accessibility_browsertest.h b/chromium/content/browser/accessibility/accessibility_browsertest.h
index 56a7392b790..56448e986f1 100644
--- a/chromium/content/browser/accessibility/accessibility_browsertest.h
+++ b/chromium/content/browser/accessibility/accessibility_browsertest.h
@@ -30,6 +30,8 @@ class AccessibilityBrowserTest : public ContentBrowserTest {
void LoadTextareaField();
void LoadSampleParagraph(ui::AXMode accessibility_mode = ui::kAXModeComplete);
void LoadSampleParagraphInScrollableEditable();
+ void LoadSampleParagraphInScrollableDocument(
+ ui::AXMode accessibility_mode = ui::kAXModeComplete);
static std::string InputContentsString();
static std::string TextAreaContentsString();
diff --git a/chromium/content/browser/accessibility/accessibility_content_browsertest.cc b/chromium/content/browser/accessibility/accessibility_content_browsertest.cc
new file mode 100644
index 00000000000..541e7eb268e
--- /dev/null
+++ b/chromium/content/browser/accessibility/accessibility_content_browsertest.cc
@@ -0,0 +1,130 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/accessibility/accessibility_content_browsertest.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/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "net/base/escape.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+namespace content {
+
+void AccessibilityContentBrowserTest::LoadInitialAccessibilityTreeFromUrl(
+ const GURL& url,
+ ui::AXMode accessibility_mode) {
+ AccessibilityNotificationWaiter waiter(GetWebContentsAndAssertNonNull(),
+ accessibility_mode,
+ ax::mojom::Event::kLoadComplete);
+ NavigateToURL(shell(), url);
+ waiter.WaitForNotification();
+}
+
+void AccessibilityContentBrowserTest::
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ const std::string& html_file_path,
+ ui::AXMode accessibility_mode) {
+ if (!embedded_test_server()->Started())
+ ASSERT_TRUE(embedded_test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->Started());
+ LoadInitialAccessibilityTreeFromUrl(
+ embedded_test_server()->GetURL(html_file_path), accessibility_mode);
+}
+
+void AccessibilityContentBrowserTest::LoadInitialAccessibilityTreeFromHtml(
+ const std::string& html,
+ ui::AXMode accessibility_mode) {
+ LoadInitialAccessibilityTreeFromUrl(
+ GURL("data:text/html," + net::EscapeQueryParamValue(html, false)),
+ accessibility_mode);
+}
+
+WebContents* AccessibilityContentBrowserTest::GetWebContentsAndAssertNonNull()
+ const {
+ // Perform the null pointer validation inside a void function to allow for a
+ // return type.
+ auto GetWebContentsAndAssertNonNull = [this](WebContents** result) {
+ WebContents* web_contents = shell()->web_contents();
+ ASSERT_NE(nullptr, web_contents);
+ *result = web_contents;
+ };
+
+ WebContents* web_contents;
+ GetWebContentsAndAssertNonNull(&web_contents);
+ return web_contents;
+}
+
+WebContentsImpl*
+AccessibilityContentBrowserTest::GetWebContentsImplAndAssertNonNull() const {
+ return static_cast<WebContentsImpl*>(GetWebContentsAndAssertNonNull());
+}
+
+BrowserAccessibilityManager*
+AccessibilityContentBrowserTest::GetManagerAndAssertNonNull() const {
+ // Perform the null pointer validation inside a void function to allow for a
+ // return type.
+ auto GetManagerAndAssertNonNull =
+ [this](BrowserAccessibilityManager** result) {
+ BrowserAccessibilityManager* browser_accessibility_manager =
+ GetWebContentsImplAndAssertNonNull()
+ ->GetRootBrowserAccessibilityManager();
+ ASSERT_NE(nullptr, browser_accessibility_manager);
+ *result = browser_accessibility_manager;
+ };
+
+ BrowserAccessibilityManager* browser_accessibility_manager;
+ GetManagerAndAssertNonNull(&browser_accessibility_manager);
+ return browser_accessibility_manager;
+}
+
+BrowserAccessibility* AccessibilityContentBrowserTest::GetRootAndAssertNonNull()
+ const {
+ // Perform the null pointer validation inside a void function to allow for a
+ // return type.
+ auto GetRootAndAssertNonNull = [this](BrowserAccessibility** result) {
+ BrowserAccessibility* root_browser_accessibility =
+ GetManagerAndAssertNonNull()->GetRoot();
+ ASSERT_NE(nullptr, result);
+ *result = root_browser_accessibility;
+ };
+
+ BrowserAccessibility* root_browser_accessibility;
+ GetRootAndAssertNonNull(&root_browser_accessibility);
+ return root_browser_accessibility;
+}
+
+BrowserAccessibility* AccessibilityContentBrowserTest::FindNode(
+ const ax::mojom::Role role,
+ const std::string& name_or_value) const {
+ return FindNodeInSubtree(GetRootAndAssertNonNull(), role, name_or_value);
+}
+
+BrowserAccessibility* AccessibilityContentBrowserTest::FindNodeInSubtree(
+ BrowserAccessibility* node,
+ const ax::mojom::Role role,
+ const std::string& name_or_value) const {
+ const auto& name =
+ node->GetStringAttribute(ax::mojom::StringAttribute::kName);
+ const auto& value =
+ node->GetStringAttribute(ax::mojom::StringAttribute::kValue);
+ if (node->GetRole() == role &&
+ (name == name_or_value || value == name_or_value)) {
+ return node;
+ }
+
+ for (uint32_t i = 0; i < node->PlatformChildCount(); ++i) {
+ BrowserAccessibility* result =
+ FindNodeInSubtree(node->PlatformGetChild(i), role, name_or_value);
+ if (result)
+ return result;
+ }
+
+ return nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_content_browsertest.h b/chromium/content/browser/accessibility/accessibility_content_browsertest.h
new file mode 100644
index 00000000000..6a379c05dce
--- /dev/null
+++ b/chromium/content/browser/accessibility/accessibility_content_browsertest.h
@@ -0,0 +1,53 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_CONTENT_BROWSERTEST_H_
+#define CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_CONTENT_BROWSERTEST_H_
+
+#include "content/public/test/content_browser_test.h"
+#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/ax_mode.h"
+
+namespace content {
+
+class BrowserAccessibility;
+class BrowserAccessibilityManager;
+class WebContents;
+class WebContentsImpl;
+
+class AccessibilityContentBrowserTest : public ContentBrowserTest {
+ protected:
+ void LoadInitialAccessibilityTreeFromUrl(
+ const GURL& url,
+ ui::AXMode accessibility_mode = ui::kAXModeComplete);
+
+ void LoadInitialAccessibilityTreeFromHtmlFilePath(
+ const std::string& html_file_path,
+ ui::AXMode accessibility_mode = ui::kAXModeComplete);
+
+ void LoadInitialAccessibilityTreeFromHtml(
+ const std::string& html,
+ ui::AXMode accessibility_mode = ui::kAXModeComplete);
+
+ WebContents* GetWebContentsAndAssertNonNull() const;
+
+ WebContentsImpl* GetWebContentsImplAndAssertNonNull() const;
+
+ BrowserAccessibilityManager* GetManagerAndAssertNonNull() const;
+
+ BrowserAccessibility* GetRootAndAssertNonNull() const;
+
+ BrowserAccessibility* FindNode(const ax::mojom::Role role,
+ const std::string& name_or_value) const;
+
+ private:
+ BrowserAccessibility* FindNodeInSubtree(
+ BrowserAccessibility* node,
+ const ax::mojom::Role role,
+ const std::string& name_or_value) const;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_CONTENT_BROWSERTEST_H_
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc b/chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
index 24c83f29709..31cd7730647 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
@@ -51,6 +51,7 @@ class AccessibilityEventRecorderAuraLinux : public AccessibilityEventRecorder {
private:
bool ShouldUseATSPI();
+ std::string AtkObjectToString(AtkObject* obj, bool include_name);
void AddATKEventListener(const char* event_name);
void AddATKEventListeners();
void RemoveATKEventListeners();
@@ -152,6 +153,7 @@ void AccessibilityEventRecorderAuraLinux::AddATKEventListeners() {
AddATKEventListener("ATK:AtkObject:state-change");
AddATKEventListener("ATK:AtkObject:focus-event");
AddATKEventListener("ATK:AtkObject:property-change");
+ AddATKEventListener("ATK:AtkObject:children-changed");
AddATKEventListener("ATK:AtkText:text-insert");
AddATKEventListener("ATK:AtkText:text-remove");
AddATKEventListener("ATK:AtkSelection:selection-changed");
@@ -182,6 +184,20 @@ bool AccessibilityEventRecorderAuraLinux::IncludeState(
}
}
+std::string AccessibilityEventRecorderAuraLinux::AtkObjectToString(
+ AtkObject* obj,
+ bool include_name) {
+ std::string role = atk_role_get_name(atk_object_get_role(obj));
+ base::ReplaceChars(role, " ", "_", &role);
+ std::string str =
+ base::StringPrintf("role=ROLE_%s", base::ToUpperASCII(role).c_str());
+ // Getting the name breaks firing of name-change events. Allow disabling of
+ // logging the name in those situations.
+ if (include_name)
+ str += base::StringPrintf(" name='%s'", atk_object_get_name(obj));
+ return str;
+}
+
void AccessibilityEventRecorderAuraLinux::ProcessATKEvent(
const char* event,
unsigned int n_params,
@@ -192,6 +208,7 @@ void AccessibilityEventRecorderAuraLinux::ProcessATKEvent(
return;
}
+ bool log_name = true;
std::string event_name(event);
std::string log;
if (event_name.find("property-change") != std::string::npos) {
@@ -214,6 +231,17 @@ void AccessibilityEventRecorderAuraLinux::ProcessATKEvent(
} else {
return;
}
+ } else if (event_name.find("children-changed") != std::string::npos) {
+ log_name = false;
+ log += base::ToUpperASCII(event);
+ // Despite this actually being a signed integer, it's defined as a uint.
+ int index = static_cast<int>(g_value_get_uint(&params[1]));
+ log += base::StringPrintf(" index:%d", index);
+ AtkObject* child = static_cast<AtkObject*>(g_value_get_pointer(&params[2]));
+ if (child)
+ log += " CHILD:(" + AtkObjectToString(child, log_name) + ")";
+ else
+ log += " CHILD:(NULL)";
} else {
log += base::ToUpperASCII(event);
if (event_name.find("state-change") != std::string::npos) {
@@ -234,10 +262,7 @@ void AccessibilityEventRecorderAuraLinux::ProcessATKEvent(
}
AtkObject* obj = ATK_OBJECT(g_value_get_object(&params[0]));
- std::string role = atk_role_get_name(atk_object_get_role(obj));
- base::ReplaceChars(role, " ", "_", &role);
- log += base::StringPrintf(" role=ROLE_%s", base::ToUpperASCII(role).c_str());
- log += base::StringPrintf(" name='%s'", atk_object_get_name(obj));
+ log += " " + AtkObjectToString(obj, log_name);
std::string states = "";
AtkStateSet* state_set = atk_object_ref_state_set(obj);
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder_uia_win.cc b/chromium/content/browser/accessibility/accessibility_event_recorder_uia_win.cc
index 94fd3880e2b..06458b6f3e3 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder_uia_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder_uia_win.cc
@@ -157,18 +157,27 @@ void AccessibilityEventRecorderUia::Thread::ThreadMain() {
cache_request_.Get(),
uia_event_handler_.Get());
- // Subscribe to all automation events (except structure-change events, which
- // are handled above.
+ // Subscribe to all automation events (except structure-change events and
+ // live-region events, which are handled elsewhere).
static const EVENTID kMinEvent = UIA_ToolTipOpenedEventId;
static const EVENTID kMaxEvent = UIA_NotificationEventId;
for (EVENTID event_id = kMinEvent; event_id <= kMaxEvent; ++event_id) {
- if (event_id != UIA_StructureChangedEventId) {
+ if (event_id != UIA_StructureChangedEventId &&
+ event_id != UIA_LiveRegionChangedEventId) {
uia_->AddAutomationEventHandler(
event_id, root_.Get(), TreeScope::TreeScope_Subtree,
cache_request_.Get(), uia_event_handler_.Get());
}
}
+ // Subscribe to live-region change events. This must be the last event we
+ // subscribe to, because |AXFragmentRootWin| will fire events when advised of
+ // the subscription, and this can hang the test-process (on Windows 19H1+) if
+ // we're simultaneously trying to subscribe to other events.
+ uia_->AddAutomationEventHandler(
+ UIA_LiveRegionChangedEventId, root_.Get(), TreeScope::TreeScope_Subtree,
+ cache_request_.Get(), uia_event_handler_.Get());
+
// Signal that initialization is complete; this will wake the main thread to
// start executing the test.
std::move(initialization_complete_).Run();
diff --git a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
index b6e8ad2423f..74a4c644ae4 100644
--- a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
@@ -117,16 +117,16 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
VLOG(1) << tree->ToString();
EXPECT_EQ(ax::mojom::Role::kRootWebArea, root->data().role);
- ASSERT_EQ(2, root->child_count());
+ ASSERT_EQ(2u, root->children().size());
- const ui::AXNode* live_region = root->ChildAtIndex(0);
- ASSERT_EQ(1, live_region->child_count());
+ const ui::AXNode* live_region = root->children()[0];
+ ASSERT_EQ(1u, live_region->children().size());
EXPECT_EQ(ax::mojom::Role::kGenericContainer, live_region->data().role);
- const ui::AXNode* para = live_region->ChildAtIndex(0);
+ const ui::AXNode* para = live_region->children().front();
EXPECT_EQ(ax::mojom::Role::kParagraph, para->data().role);
- const ui::AXNode* button = root->ChildAtIndex(1);
+ const ui::AXNode* button = root->children()[1];
EXPECT_EQ(ax::mojom::Role::kButton, button->data().role);
}
@@ -174,10 +174,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
int max_iterations = RenderFrameHostImpl::kMaxAccessibilityResets;
for (int iteration = 0; iteration < max_iterations; iteration++) {
- // Send the browser accessibility the bad message.
- BrowserAccessibilityManager* manager =
- frame->GetOrCreateBrowserAccessibilityManager();
- manager->OnAccessibilityEvents(bad_accessibility_event);
+ // Make sure the manager has been created.
+ frame->GetOrCreateBrowserAccessibilityManager();
+ ASSERT_NE(nullptr, frame->browser_accessibility_manager());
+
+ // Send the bad message to the manager.
+ frame->SendAccessibilityEventsToManager(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_android.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
index 9c7856ee9c6..fbe4ae41b53 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
@@ -150,7 +150,7 @@ void AccessibilityTreeFormatterAndroid::AddProperties(
dict->SetBoolean("interesting", android_node->IsInterestingOnAndroid());
// String attributes.
- dict->SetString("name", android_node->GetText());
+ dict->SetString("name", android_node->GetInnerText());
dict->SetString("hint", android_node->GetHint());
dict->SetString("role_description", android_node->GetRoleDescription());
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
index 20c7cf36fec..a237eaffc88 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -75,6 +75,8 @@ std::string IntAttrToString(const BrowserAccessibility& node,
return ui::ToString(static_cast<ax::mojom::DefaultActionVerb>(value));
case ax::mojom::IntAttribute::kDescriptionFrom:
return ui::ToString(static_cast<ax::mojom::DescriptionFrom>(value));
+ case ax::mojom::IntAttribute::kDropeffect:
+ return node.GetData().DropeffectBitfieldToString();
case ax::mojom::IntAttribute::kHasPopup:
return ui::ToString(static_cast<ax::mojom::HasPopup>(value));
case ax::mojom::IntAttribute::kInvalidState:
@@ -114,6 +116,7 @@ std::string IntAttrToString(const BrowserAccessibility& node,
case ax::mojom::IntAttribute::kNextFocusId:
case ax::mojom::IntAttribute::kNextOnLineId:
case ax::mojom::IntAttribute::kPosInSet:
+ case ax::mojom::IntAttribute::kPopupForId:
case ax::mojom::IntAttribute::kPreviousFocusId:
case ax::mojom::IntAttribute::kPreviousOnLineId:
case ax::mojom::IntAttribute::kScrollX:
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index 8a4fbbc3fad..71b71384eee 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -19,7 +19,7 @@
#include "content/browser/accessibility/browser_accessibility_manager.h"
// This file uses the deprecated NSObject accessibility interface.
-// TODO(crbug.com/921109): Migrate to the new NSAccessibility interface.
+// TODO(crbug.com/948844): Migrate to the new NSAccessibility interface.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -43,12 +43,16 @@ const char kRangeLenDictAttr[] = "len";
std::unique_ptr<base::DictionaryValue> PopulatePosition(
const BrowserAccessibility& node) {
+ DCHECK(node.instance_active());
+ BrowserAccessibilityManager* root_manager = node.manager()->GetRootManager();
+ DCHECK(root_manager);
+
std::unique_ptr<base::DictionaryValue> position(new base::DictionaryValue);
// The NSAccessibility position of an object is in global coordinates and
// based on the lower-left corner of the object. To make this easier and less
// confusing, convert it to local window coordinates using the top-left
// corner when dumping the position.
- BrowserAccessibility* root = node.manager()->GetRootManager()->GetRoot();
+ BrowserAccessibility* root = root_manager->GetRoot();
BrowserAccessibilityCocoa* cocoa_root = ToBrowserAccessibilityCocoa(root);
NSPoint root_position = [[cocoa_root position] pointValue];
NSSize root_size = [[cocoa_root size] sizeValue];
@@ -118,7 +122,7 @@ std::unique_ptr<base::Value> StringForBrowserAccessibility(
// Include the description, title, or value - the first one not empty.
id title = [obj title];
- id description = [obj description];
+ id description = [obj descriptionForAccessibility];
id value = [obj value];
if (description && ![description isEqual:@""]) {
[tokens addObject:description];
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
index 3ce5bbd458c..9ab186fa32d 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
@@ -1033,7 +1033,7 @@ AccessibilityTreeFormatterUia::GetExpectedFileSuffix() {
const base::FilePath::StringType
AccessibilityTreeFormatterUia::GetVersionSpecificExpectedFileSuffix() {
- if (base::win::GetVersion() == base::win::Version::VERSION_WIN7) {
+ if (base::win::GetVersion() == base::win::Version::WIN7) {
return FILE_PATH_LITERAL("-expected-uia-win7.txt");
}
return FILE_PATH_LITERAL("");
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
index 077eb10b89f..e8330f437e6 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -277,11 +277,14 @@ std::unique_ptr<base::DictionaryValue>
AccessibilityTreeFormatterWin::BuildAccessibilityTree(
BrowserAccessibility* start_node) {
DCHECK(start_node);
+ DCHECK(start_node->instance_active());
+ BrowserAccessibilityManager* root_manager =
+ start_node->manager()->GetRootManager();
+ DCHECK(root_manager);
base::win::ScopedVariant variant_self(CHILDID_SELF);
LONG root_x, root_y, root_width, root_height;
- BrowserAccessibility* root =
- start_node->manager()->GetRootManager()->GetRoot();
+ BrowserAccessibility* root = root_manager->GetRoot();
HRESULT hr = ToBrowserAccessibilityWin(root)->GetCOM()->accLocation(
&root_x, &root_y, &root_width, &root_height, variant_self);
DCHECK(SUCCEEDED(hr));
diff --git a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
index 385babb5949..2ed9d12d0a7 100644
--- a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -346,20 +346,7 @@ void AccessibilityWinBrowserTest::SetUpSampleParagraph(
void AccessibilityWinBrowserTest::SetUpSampleParagraphInScrollableDocument(
Microsoft::WRL::ComPtr<IAccessibleText>* accessible_text,
ui::AXMode accessibility_mode) {
- LoadInitialAccessibilityTreeFromHtml(
- R"HTML(<!DOCTYPE html>
- <html>
- <body>
- <p style="margin-top:50vh; margin-bottom:200vh">
- <b>Game theory</b> is "the study of
- <a href="" title="Mathematical model">mathematical models</a>
- of conflict and<br>cooperation between intelligent rational
- decision-makers."
- </p>
- </body>
- </html>)HTML",
- accessibility_mode);
-
+ LoadSampleParagraphInScrollableDocument(accessibility_mode);
SetUpSampleParagraphHelper(accessible_text);
}
@@ -906,7 +893,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Set focus to the radio group.
auto waiter = std::make_unique<AccessibilityNotificationWaiter>(
shell()->web_contents(), ui::kAXModeComplete, ax::mojom::Event::kFocus);
- ExecuteScript(L"document.body.children[0].focus()");
+ ExecuteScript(L"document.body.children[0].focus();");
waiter->WaitForNotification();
// Check that the accessibility tree of the browser has been updated.
@@ -1016,7 +1003,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
TestNotificationFocusChanged) {
// The role attribute causes the node to be in the accessibility tree.
- LoadInitialAccessibilityTreeFromHtml("<div role=group tabindex='-1'></div>");
+ LoadInitialAccessibilityTreeFromHtml(R"HTML(
+ <div role="group" tabindex="-1">
+ </div>)HTML");
// Check the browser's copy of the renderer accessibility tree.
SCOPED_TRACE("Check initial tree");
@@ -1028,29 +1017,32 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
document_checker.AppendExpectedChild(&group_checker);
document_checker.CheckAccessible(GetRendererAccessible());
- // Focus the div in the document
- std::unique_ptr<AccessibilityNotificationWaiter> waiter(
- new AccessibilityNotificationWaiter(shell()->web_contents(),
- ui::kAXModeComplete,
- ax::mojom::Event::kFocus));
- ExecuteScript(L"document.body.children[0].focus()");
- waiter->WaitForNotification();
+ {
+ // Focus the div in the document
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ax::mojom::Event::kFocus);
+ ExecuteScript(L"document.body.children[0].focus();");
+ waiter.WaitForNotification();
+ }
// Check that the accessibility tree of the browser has been updated.
SCOPED_TRACE("Check updated tree after focusing div");
group_checker.SetExpectedState(STATE_SYSTEM_FOCUSABLE | STATE_SYSTEM_FOCUSED);
document_checker.CheckAccessible(GetRendererAccessible());
- // Focus the document accessible. This will un-focus the current node.
- waiter.reset(new AccessibilityNotificationWaiter(
- shell()->web_contents(), ui::kAXModeComplete, ax::mojom::Event::kBlur));
- Microsoft::WRL::ComPtr<IAccessible> document_accessible(
- GetRendererAccessible());
- ASSERT_NE(document_accessible.Get(), reinterpret_cast<IAccessible*>(NULL));
- base::win::ScopedVariant childid_self(CHILDID_SELF);
- HRESULT hr = document_accessible->accSelect(SELFLAG_TAKEFOCUS, childid_self);
- ASSERT_EQ(S_OK, hr);
- waiter->WaitForNotification();
+ {
+ // Focus the document accessible. This will un-focus the current node.
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ax::mojom::Event::kBlur);
+ Microsoft::WRL::ComPtr<IAccessible> document_accessible(
+ GetRendererAccessible());
+ ASSERT_NE(nullptr, document_accessible.Get());
+ base::win::ScopedVariant childid_self(CHILDID_SELF);
+ HRESULT hr =
+ document_accessible->accSelect(SELFLAG_TAKEFOCUS, childid_self);
+ ASSERT_EQ(S_OK, hr);
+ waiter.WaitForNotification();
+ }
// Check that the accessibility tree of the browser has been updated.
SCOPED_TRACE("Check updated tree after focusing document again");
@@ -1058,6 +1050,151 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
document_checker.CheckAccessible(GetRendererAccessible());
}
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, FocusEventOnPageLoad) {
+ // Some screen readers, such as older versions of Jaws, require a focus event
+ // on the top document after the page loads, if there is no focused element on
+ // the page.
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLoadComplete);
+ GURL html_data_url(
+ "data:text/html," +
+ net::EscapeQueryParamValue(R"HTML(<p> Hello</ p>)HTML", false));
+ NavigateToURL(shell(), html_data_url);
+ WaitForAccessibilityFocusChange();
+ waiter.WaitForNotification();
+
+ Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible());
+ ASSERT_TRUE(document);
+ base::win::ScopedVariant focus;
+ base::win::ScopedVariant childid_self(CHILDID_SELF);
+ ASSERT_HRESULT_SUCCEEDED(document->get_accFocus(focus.Receive()));
+ EXPECT_EQ(VT_I4, focus.type());
+ EXPECT_EQ(CHILDID_SELF, V_I4(focus.ptr()));
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, NoFocusEventOnRootChange) {
+ LoadInitialAccessibilityTreeFromHtml(R"HTML(
+ <p>Hello</p>
+ )HTML");
+
+ // Adding an iframe as a direct descendant of the root will reserialize the
+ // root node.
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLayoutComplete);
+ ExecuteScript(
+ L"let iframe = document.createElement('iframe');"
+ L"iframe.srcdoc = '<button>Button</button>';"
+ L"document.body.appendChild(iframe);");
+ waiter.WaitForNotification();
+
+ Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible());
+ ASSERT_TRUE(document);
+ base::win::ScopedVariant focus;
+ base::win::ScopedVariant childid_self(CHILDID_SELF);
+ ASSERT_HRESULT_SUCCEEDED(document->get_accFocus(focus.Receive()));
+ EXPECT_EQ(VT_I4, focus.type());
+ EXPECT_EQ(CHILDID_SELF, V_I4(focus.ptr()));
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+ FocusEventOnFocusedIframeAddedAndRemoved) {
+ LoadInitialAccessibilityTreeFromHtml(R"HTML(
+ <button autofocus>Outer button</button>
+ )HTML");
+
+ Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible());
+ ASSERT_TRUE(document);
+
+ {
+ AccessibilityNotificationWaiter iframe_waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ax::mojom::Event::kFocus);
+ ExecuteScript(
+ L"let iframe = document.createElement('iframe');"
+ L"iframe.srcdoc = '<button autofocus>Inner button</button>';"
+ L"document.body.appendChild(iframe);");
+ WaitForAccessibilityFocusChange();
+ iframe_waiter.WaitForNotification();
+
+ const BrowserAccessibility* inner_button =
+ FindNode(ax::mojom::Role::kButton, "Inner button");
+ ASSERT_NE(nullptr, inner_button);
+ const auto* inner_button_win =
+ ToBrowserAccessibilityWin(inner_button)->GetCOM();
+ ASSERT_NE(nullptr, inner_button_win);
+
+ base::win::ScopedVariant focus;
+ base::win::ScopedVariant childid_self(CHILDID_SELF);
+ ASSERT_HRESULT_SUCCEEDED(document->get_accFocus(focus.Receive()));
+ EXPECT_EQ(VT_DISPATCH, focus.type());
+ EXPECT_EQ(inner_button_win, V_DISPATCH(focus.ptr()));
+ }
+
+ {
+ AccessibilityNotificationWaiter iframe_waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kLayoutComplete);
+ ExecuteScript(L"document.body.removeChild(iframe);");
+ WaitForAccessibilityFocusChange();
+ iframe_waiter.WaitForNotification();
+
+ base::win::ScopedVariant focus;
+ base::win::ScopedVariant childid_self(CHILDID_SELF);
+ ASSERT_HRESULT_SUCCEEDED(document->get_accFocus(focus.Receive()));
+ EXPECT_EQ(VT_I4, focus.type());
+ EXPECT_EQ(CHILDID_SELF, V_I4(focus.ptr()));
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+ NoFocusEventOnIframeAddedAndRemoved) {
+ LoadInitialAccessibilityTreeFromHtml(R"HTML(
+ <button autofocus>Outer button</button>
+ )HTML");
+
+ Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible());
+ ASSERT_TRUE(document);
+
+ const BrowserAccessibility* outer_button =
+ FindNode(ax::mojom::Role::kButton, "Outer button");
+ ASSERT_NE(nullptr, outer_button);
+ const auto* outer_button_win =
+ ToBrowserAccessibilityWin(outer_button)->GetCOM();
+ ASSERT_NE(nullptr, outer_button_win);
+
+ {
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLayoutComplete);
+ ExecuteScript(
+ L"let iframe = document.createElement('iframe');"
+ L"iframe.srcdoc = '<button>Inner button</button>';"
+ L"document.body.appendChild(iframe);");
+ waiter.WaitForNotification();
+
+ base::win::ScopedVariant focus;
+ base::win::ScopedVariant childid_self(CHILDID_SELF);
+ ASSERT_HRESULT_SUCCEEDED(document->get_accFocus(focus.Receive()));
+ EXPECT_EQ(VT_DISPATCH, focus.type());
+ EXPECT_EQ(outer_button_win, V_DISPATCH(focus.ptr()));
+ }
+
+ {
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLayoutComplete);
+ ExecuteScript(L"document.body.removeChild(iframe);");
+ waiter.WaitForNotification();
+
+ base::win::ScopedVariant focus;
+ base::win::ScopedVariant childid_self(CHILDID_SELF);
+ ASSERT_HRESULT_SUCCEEDED(document->get_accFocus(focus.Receive()));
+ EXPECT_EQ(VT_DISPATCH, focus.type());
+ EXPECT_EQ(outer_button_win, V_DISPATCH(focus.ptr()));
+ }
+}
+
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
TestNotificationValueChanged) {
LoadInitialAccessibilityTreeFromHtml(
diff --git a/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc b/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
index fc5aee1fd6c..65fe193ce51 100644
--- a/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
+++ b/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
@@ -80,7 +80,7 @@ class AndroidGranularityMovementBrowserTest : public ContentBrowserTest {
static_cast<BrowserAccessibilityAndroid*>(node);
BrowserAccessibilityManagerAndroid* manager =
static_cast<BrowserAccessibilityManagerAndroid*>(node->manager());
- base::string16 text = android_node->GetText();
+ base::string16 text = android_node->GetInnerText();
base::string16 concatenated;
int previous_end_index = -1;
while (manager->NextAtGranularity(granularity, end_index, android_node,
diff --git a/chromium/content/browser/accessibility/aom_browsertest.cc b/chromium/content/browser/accessibility/aom_browsertest.cc
index 0a614f8f0a5..4b9ddac7a43 100644
--- a/chromium/content/browser/accessibility/aom_browsertest.cc
+++ b/chromium/content/browser/accessibility/aom_browsertest.cc
@@ -91,7 +91,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityObjectModelBrowserTest,
waiter2.WaitForNotification();
BrowserAccessibility* focus = GetManager()->GetFocus();
- EXPECT_EQ(focus->GetId(), button->GetId());
+ ASSERT_NE(nullptr, focus);
+ EXPECT_EQ(button->GetId(), focus->GetId());
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/ax_platform_node_textprovider_win_browsertest.cc b/chromium/content/browser/accessibility/ax_platform_node_textprovider_win_browsertest.cc
new file mode 100644
index 00000000000..8daaed20ff5
--- /dev/null
+++ b/chromium/content/browser/accessibility/ax_platform_node_textprovider_win_browsertest.cc
@@ -0,0 +1,190 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/platform/ax_platform_node_textprovider_win.h"
+#include "ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h"
+
+#include "base/win/scoped_bstr.h"
+#include "base/win/scoped_safearray.h"
+#include "base/win/scoped_variant.h"
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/browser/accessibility/browser_accessibility_com_win.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "net/base/escape.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
+
+using Microsoft::WRL::ComPtr;
+
+namespace content {
+
+#define ASSERT_UIA_SAFEARRAY_OF_TEXTRANGEPROVIDER(safearray, expected_size) \
+ { \
+ EXPECT_EQ(sizeof(CComPtr<ITextRangeProvider>), \
+ ::SafeArrayGetElemsize(safearray)); \
+ ASSERT_EQ(1u, SafeArrayGetDim(safearray)); \
+ LONG array_lower_bound; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ SafeArrayGetLBound(safearray, 1, &array_lower_bound)); \
+ LONG array_upper_bound; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ SafeArrayGetUBound(safearray, 1, &array_upper_bound)); \
+ size_t count = array_upper_bound - array_lower_bound + 1; \
+ ASSERT_EQ(expected_size, count); \
+ }
+
+#define EXPECT_UIA_TEXTRANGE_EQ(provider, expected_content) \
+ { \
+ base::win::ScopedBstr provider_content; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ provider->GetText(-1, provider_content.Receive())); \
+ EXPECT_STREQ(expected_content, provider_content); \
+ }
+
+class AXPlatformNodeTextProviderWinBrowserTest : public ContentBrowserTest {
+ protected:
+ void LoadInitialAccessibilityTreeFromUrl(
+ const GURL& url,
+ ui::AXMode accessibility_mode = ui::kAXModeComplete) {
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ accessibility_mode,
+ ax::mojom::Event::kLoadComplete);
+ NavigateToURL(shell(), url);
+ waiter.WaitForNotification();
+ }
+
+ void LoadInitialAccessibilityTreeFromHtmlFilePath(
+ const std::string& html_file_path,
+ ui::AXMode accessibility_mode = ui::kAXModeComplete) {
+ if (!embedded_test_server()->Started())
+ ASSERT_TRUE(embedded_test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->Started());
+ LoadInitialAccessibilityTreeFromUrl(
+ embedded_test_server()->GetURL(html_file_path), accessibility_mode);
+ }
+
+ void LoadInitialAccessibilityTreeFromHtml(
+ const std::string& html,
+ ui::AXMode accessibility_mode = ui::kAXModeComplete) {
+ LoadInitialAccessibilityTreeFromUrl(
+ GURL("data:text/html," + net::EscapeQueryParamValue(html, false)),
+ accessibility_mode);
+ }
+
+ BrowserAccessibilityManager* GetManagerAndAssertNonNull() {
+ auto GetManagerAndAssertNonNull =
+ [this](BrowserAccessibilityManager** result) {
+ WebContentsImpl* web_contents_impl =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ ASSERT_NE(nullptr, web_contents_impl);
+ BrowserAccessibilityManager* browser_accessibility_manager =
+ web_contents_impl->GetRootBrowserAccessibilityManager();
+ ASSERT_NE(nullptr, browser_accessibility_manager);
+ *result = browser_accessibility_manager;
+ };
+
+ BrowserAccessibilityManager* browser_accessibility_manager;
+ GetManagerAndAssertNonNull(&browser_accessibility_manager);
+ return browser_accessibility_manager;
+ }
+
+ BrowserAccessibility* GetRootAndAssertNonNull() {
+ auto GetRootAndAssertNonNull = [this](BrowserAccessibility** result) {
+ BrowserAccessibility* root_browser_accessibility =
+ GetManagerAndAssertNonNull()->GetRoot();
+ ASSERT_NE(nullptr, result);
+ *result = root_browser_accessibility;
+ };
+
+ BrowserAccessibility* root_browser_accessibility;
+ GetRootAndAssertNonNull(&root_browser_accessibility);
+ return root_browser_accessibility;
+ }
+
+ BrowserAccessibility* FindNode(ax::mojom::Role role,
+ const std::string& name_or_value) {
+ return FindNodeInSubtree(*GetRootAndAssertNonNull(), role, name_or_value);
+ }
+
+ void GetTextProviderFromTextNode(
+ ComPtr<ITextProvider>& text_provider,
+ BrowserAccessibility* target_browser_accessibility) {
+ auto* provider_simple =
+ ToBrowserAccessibilityWin(target_browser_accessibility)->GetCOM();
+ ASSERT_NE(nullptr, provider_simple);
+
+ EXPECT_HRESULT_SUCCEEDED(
+ provider_simple->GetPatternProvider(UIA_TextPatternId, &text_provider));
+ ASSERT_NE(nullptr, text_provider.Get());
+ }
+
+ private:
+ BrowserAccessibility* FindNodeInSubtree(BrowserAccessibility& node,
+ ax::mojom::Role role,
+ const std::string& name_or_value) {
+ const auto& name =
+ node.GetStringAttribute(ax::mojom::StringAttribute::kName);
+ const auto& value =
+ node.GetStringAttribute(ax::mojom::StringAttribute::kValue);
+ if (node.GetRole() == role &&
+ (name == name_or_value || value == name_or_value)) {
+ return &node;
+ }
+
+ for (unsigned int i = 0; i < node.PlatformChildCount(); ++i) {
+ BrowserAccessibility* result =
+ FindNodeInSubtree(*node.PlatformGetChild(i), role, name_or_value);
+ if (result)
+ return result;
+ }
+
+ return nullptr;
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextProviderWinBrowserTest,
+ GetVisibleBounds) {
+ LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+ <!DOCTYPE html>
+ <html>
+ <body>
+ <div style='overflow: hidden visible; width: 10em; height: 2.4em;'>
+ <span style='white-space: pre-line;'>AAA BBB
+ CCCCCC
+ DDDDDD</span>
+ </div>
+ </body>
+ </html>
+ )HTML"));
+
+ auto* node =
+ FindNode(ax::mojom::Role::kStaticText, "AAA BBB\nCCCCCC\nDDDDDD");
+ ASSERT_NE(nullptr, node);
+ EXPECT_TRUE(node->PlatformIsLeaf());
+ EXPECT_EQ(0u, node->PlatformChildCount());
+
+ ComPtr<ITextProvider> text_provider;
+ GetTextProviderFromTextNode(text_provider, node);
+
+ base::win::ScopedSafearray text_provider_ranges;
+ CComPtr<ITextRangeProvider>* array_data;
+ EXPECT_HRESULT_SUCCEEDED(
+ text_provider->GetVisibleRanges(text_provider_ranges.Receive()));
+ ASSERT_UIA_SAFEARRAY_OF_TEXTRANGEPROVIDER(text_provider_ranges.Get(), 2U);
+
+ ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData(
+ text_provider_ranges.Get(), reinterpret_cast<void**>(&array_data)));
+
+ EXPECT_UIA_TEXTRANGE_EQ(array_data[0], L"AAA BBB");
+ EXPECT_UIA_TEXTRANGE_EQ(array_data[1], L"CCCCCC");
+
+ ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(text_provider_ranges.Get()));
+ text_provider_ranges.Reset();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc b/chromium/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
new file mode 100644
index 00000000000..c44e9ad119e
--- /dev/null
+++ b/chromium/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
@@ -0,0 +1,888 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h"
+
+#include "base/win/scoped_bstr.h"
+#include "base/win/scoped_safearray.h"
+#include "base/win/scoped_variant.h"
+#include "content/browser/accessibility/accessibility_content_browsertest.h"
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/browser/accessibility/browser_accessibility_com_win.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "net/dns/mock_host_resolver.h"
+
+using Microsoft::WRL::ComPtr;
+
+namespace content {
+
+#define EXPECT_UIA_DOUBLE_SAFEARRAY_EQ(safearray, expected_property_values) \
+ { \
+ EXPECT_EQ(sizeof(V_R8(LPVARIANT(NULL))), \
+ ::SafeArrayGetElemsize(safearray)); \
+ ASSERT_EQ(1u, SafeArrayGetDim(safearray)); \
+ LONG array_lower_bound; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ SafeArrayGetLBound(safearray, 1, &array_lower_bound)); \
+ LONG array_upper_bound; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ SafeArrayGetUBound(safearray, 1, &array_upper_bound)); \
+ double* array_data; \
+ ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( \
+ safearray, reinterpret_cast<void**>(&array_data))); \
+ size_t count = array_upper_bound - array_lower_bound + 1; \
+ ASSERT_EQ(expected_property_values.size(), count); \
+ for (size_t i = 0; i < count; ++i) { \
+ EXPECT_EQ(array_data[i], expected_property_values[i]); \
+ } \
+ ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(safearray)); \
+ }
+
+#define EXPECT_UIA_TEXTRANGE_EQ(provider, expected_content) \
+ { \
+ base::win::ScopedBstr provider_content; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ provider->GetText(-1, provider_content.Receive())); \
+ EXPECT_STREQ(expected_content, provider_content); \
+ }
+
+#define EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(text_range_provider, endpoint, unit, \
+ count, expected_text, expected_count) \
+ { \
+ int result_count; \
+ EXPECT_HRESULT_SUCCEEDED(text_range_provider->MoveEndpointByUnit( \
+ endpoint, unit, count, &result_count)); \
+ EXPECT_EQ(expected_count, result_count); \
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, expected_text); \
+ }
+
+#define EXPECT_UIA_MOVE(text_range_provider, unit, count, expected_text, \
+ expected_count) \
+ { \
+ int result_count; \
+ EXPECT_HRESULT_SUCCEEDED( \
+ text_range_provider->Move(unit, count, &result_count)); \
+ EXPECT_EQ(expected_count, result_count); \
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, expected_text); \
+ }
+
+class AXPlatformNodeTextRangeProviderWinBrowserTest
+ : public AccessibilityContentBrowserTest {
+ protected:
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+
+ void GetTextRangeProviderFromTextNode(
+ ComPtr<ITextRangeProvider>& text_range_provider,
+ BrowserAccessibility* target_browser_accessibility) {
+ auto* provider_simple =
+ ToBrowserAccessibilityWin(target_browser_accessibility)->GetCOM();
+ ASSERT_NE(nullptr, provider_simple);
+
+ ComPtr<ITextProvider> text_provider;
+ EXPECT_HRESULT_SUCCEEDED(
+ provider_simple->GetPatternProvider(UIA_TextPatternId, &text_provider));
+ ASSERT_NE(nullptr, text_provider.Get());
+
+ EXPECT_HRESULT_SUCCEEDED(
+ text_provider->get_DocumentRange(&text_range_provider));
+ ASSERT_NE(nullptr, text_range_provider.Get());
+ }
+
+ // Run through ITextRangeProvider::ScrollIntoView top tests. It's assumed that
+ // the browser has already loaded an HTML document's accessibility tree.
+ // Assert the text range generated for an accessibility node is scrolled to be
+ // flush with the top of the viewport.
+ // expected_start_role: the expected accessibility role of the text range
+ // start node under test
+ // fstart: the function to retrieve the accessibility text
+ // range start node under test from the root
+ // accessibility node
+ // expected_end_role: the expected accessibility role of the text range
+ // end node under test
+ // fend: the function to retrieve the accessibility text
+ // range end node under test from the root
+ // accessibility node
+ // align_to_top: true to test top viewport alignment, otherwise test
+ // bottom viewport alignment
+ void ScrollIntoViewBrowserTestTemplate(
+ const ax::mojom::Role expected_start_role,
+ BrowserAccessibility* (BrowserAccessibility::*fstart)() const,
+ const ax::mojom::Role expected_end_role,
+ BrowserAccessibility* (BrowserAccessibility::*fend)() const,
+ const bool align_to_top) {
+ BrowserAccessibility* root_browser_accessibility =
+ GetRootAndAssertNonNull();
+
+ BrowserAccessibility* browser_accessibility_start =
+ (root_browser_accessibility->*fstart)();
+ ASSERT_NE(nullptr, browser_accessibility_start);
+ ASSERT_EQ(expected_start_role, browser_accessibility_start->GetRole());
+
+ BrowserAccessibility* browser_accessibility_end =
+ (root_browser_accessibility->*fend)();
+ ASSERT_NE(nullptr, browser_accessibility_end);
+ ASSERT_EQ(expected_end_role, browser_accessibility_end->GetRole());
+
+ AssertScrollIntoView(root_browser_accessibility,
+ browser_accessibility_start, browser_accessibility_end,
+ align_to_top);
+ }
+
+ // Run through ITextRangeProvider::ScrollIntoView top tests. It's assumed that
+ // the browser has already loaded an HTML document's accessibility tree.
+ // Assert the text range generated for an accessibility node is scrolled to be
+ // flush with the top of the viewport.
+ // expected_start_role: the expected accessibility role of the text range
+ // start node under test
+ // fstart: the function to retrieve the accessibility text
+ // range start node under test from the root
+ // accessibility node
+ // fstart_arg: an index argument for fstart
+ // expected_end_role: the expected accessibility role of the text range
+ // end node under test
+ // fend: the function to retrieve the accessibility text
+ // range end node under test from the root
+ // accessibility node
+ // fend_arg: an index argument for fend
+ // align_to_top: true to test top viewport alignment, otherwise test
+ // bottom viewport alignment
+ void ScrollIntoViewBrowserTestTemplate(
+ const ax::mojom::Role expected_start_role,
+ BrowserAccessibility* (BrowserAccessibility::*fstart)(uint32_t) const,
+ const uint32_t fstart_arg,
+ const ax::mojom::Role expected_end_role,
+ BrowserAccessibility* (BrowserAccessibility::*fend)(uint32_t) const,
+ const uint32_t fend_arg,
+ const bool align_to_top) {
+ BrowserAccessibility* root_browser_accessibility =
+ GetRootAndAssertNonNull();
+
+ BrowserAccessibility* browser_accessibility_start =
+ (root_browser_accessibility->*fstart)(fstart_arg);
+ ASSERT_NE(nullptr, browser_accessibility_start);
+ ASSERT_EQ(expected_start_role, browser_accessibility_start->GetRole());
+
+ BrowserAccessibility* browser_accessibility_end =
+ (root_browser_accessibility->*fend)(fend_arg);
+ ASSERT_NE(nullptr, browser_accessibility_end);
+ ASSERT_EQ(expected_end_role, browser_accessibility_end->GetRole());
+
+ AssertScrollIntoView(root_browser_accessibility,
+ browser_accessibility_start, browser_accessibility_end,
+ align_to_top);
+ }
+
+ void ScrollIntoViewFromIframeBrowserTestTemplate(
+ const ax::mojom::Role expected_start_role,
+ BrowserAccessibility* (BrowserAccessibility::*fstart)() const,
+ const ax::mojom::Role expected_end_role,
+ BrowserAccessibility* (BrowserAccessibility::*fend)() const,
+ const bool align_to_top) {
+ BrowserAccessibility* root_browser_accessibility =
+ GetRootAndAssertNonNull();
+ BrowserAccessibility* leaf_iframe_browser_accessibility =
+ root_browser_accessibility->InternalDeepestLastChild();
+ ASSERT_NE(nullptr, leaf_iframe_browser_accessibility);
+ ASSERT_EQ(ax::mojom::Role::kIframe,
+ leaf_iframe_browser_accessibility->GetRole());
+
+ AXTreeID iframe_tree_id = AXTreeID::FromString(
+ leaf_iframe_browser_accessibility->GetStringAttribute(
+ ax::mojom::StringAttribute::kChildTreeId));
+ BrowserAccessibilityManager* iframe_browser_accessibility_manager =
+ BrowserAccessibilityManager::FromID(iframe_tree_id);
+ ASSERT_NE(nullptr, iframe_browser_accessibility_manager);
+ BrowserAccessibility* root_iframe_browser_accessibility =
+ iframe_browser_accessibility_manager->GetRoot();
+ ASSERT_NE(nullptr, root_iframe_browser_accessibility);
+ ASSERT_EQ(ax::mojom::Role::kRootWebArea,
+ root_iframe_browser_accessibility->GetRole());
+
+ BrowserAccessibility* browser_accessibility_start =
+ (root_iframe_browser_accessibility->*fstart)();
+ ASSERT_NE(nullptr, browser_accessibility_start);
+ ASSERT_EQ(expected_start_role, browser_accessibility_start->GetRole());
+
+ BrowserAccessibility* browser_accessibility_end =
+ (root_iframe_browser_accessibility->*fend)();
+ ASSERT_NE(nullptr, browser_accessibility_end);
+ ASSERT_EQ(expected_end_role, browser_accessibility_end->GetRole());
+
+ AssertScrollIntoView(root_iframe_browser_accessibility,
+ browser_accessibility_start, browser_accessibility_end,
+ align_to_top);
+ }
+
+ void AssertScrollIntoView(BrowserAccessibility* root_browser_accessibility,
+ BrowserAccessibility* browser_accessibility_start,
+ BrowserAccessibility* browser_accessibility_end,
+ const bool align_to_top) {
+ ui::AXNodePosition::AXPositionInstance start =
+ browser_accessibility_start->CreateTextPositionAt(0);
+ ui::AXNodePosition::AXPositionInstance end =
+ browser_accessibility_end->CreateTextPositionAt(0)
+ ->CreatePositionAtEndOfAnchor();
+
+ BrowserAccessibilityComWin* start_browser_accessibility_com_win =
+ ToBrowserAccessibilityWin(browser_accessibility_start)->GetCOM();
+ ASSERT_NE(nullptr, start_browser_accessibility_com_win);
+
+ CComPtr<ITextRangeProvider> text_range_provider =
+ ui::AXPlatformNodeTextRangeProviderWin::CreateTextRangeProvider(
+ start_browser_accessibility_com_win, std::move(start),
+ std::move(end));
+ ASSERT_NE(nullptr, text_range_provider);
+
+ gfx::Rect previous_range_bounds =
+ align_to_top ? browser_accessibility_start->GetBoundsRect(
+ ui::AXCoordinateSystem::kFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ : browser_accessibility_end->GetBoundsRect(
+ ui::AXCoordinateSystem::kFrame,
+ ui::AXClippingBehavior::kUnclipped);
+
+ AccessibilityNotificationWaiter location_changed_waiter(
+ GetWebContentsAndAssertNonNull(), ui::kAXModeComplete,
+ ax::mojom::Event::kLocationChanged);
+ ASSERT_HRESULT_SUCCEEDED(text_range_provider->ScrollIntoView(align_to_top));
+ location_changed_waiter.WaitForNotification();
+
+ gfx::Rect root_page_bounds = root_browser_accessibility->GetBoundsRect(
+ ui::AXCoordinateSystem::kFrame, ui::AXClippingBehavior::kUnclipped);
+ if (align_to_top) {
+ gfx::Rect range_bounds = browser_accessibility_start->GetBoundsRect(
+ ui::AXCoordinateSystem::kFrame, ui::AXClippingBehavior::kUnclipped);
+ ASSERT_NE(previous_range_bounds.y(), range_bounds.y());
+ ASSERT_NEAR(root_page_bounds.y(), range_bounds.y(), 1);
+ } else {
+ gfx::Rect range_bounds = browser_accessibility_end->GetBoundsRect(
+ ui::AXCoordinateSystem::kFrame, ui::AXClippingBehavior::kUnclipped);
+ gfx::Size viewport_size =
+ gfx::Size(root_page_bounds.width(), root_page_bounds.height());
+ ASSERT_NE(previous_range_bounds.y(), range_bounds.y());
+ ASSERT_NEAR(root_page_bounds.y() + viewport_size.height(),
+ range_bounds.y() + range_bounds.height(), 1);
+ }
+ }
+
+ void ScrollIntoViewTopBrowserTestTemplate(
+ const ax::mojom::Role expected_role,
+ BrowserAccessibility* (BrowserAccessibility::*f)() const) {
+ ScrollIntoViewBrowserTestTemplate(expected_role, f, expected_role, f, true);
+ }
+
+ void ScrollIntoViewTopBrowserTestTemplate(
+ const ax::mojom::Role expected_role_start,
+ BrowserAccessibility* (BrowserAccessibility::*fstart)() const,
+ const ax::mojom::Role expected_role_end,
+ BrowserAccessibility* (BrowserAccessibility::*fend)() const) {
+ ScrollIntoViewBrowserTestTemplate(expected_role_start, fstart,
+ expected_role_end, fend, true);
+ }
+
+ void ScrollIntoViewTopBrowserTestTemplate(
+ const ax::mojom::Role expected_role_start,
+ BrowserAccessibility* (BrowserAccessibility::*fstart)(uint32_t) const,
+ const uint32_t fstart_arg,
+ const ax::mojom::Role expected_role_end,
+ BrowserAccessibility* (BrowserAccessibility::*fend)(uint32_t) const,
+ const uint32_t fend_arg) {
+ ScrollIntoViewBrowserTestTemplate(expected_role_start, fstart, fstart_arg,
+ expected_role_end, fend, fend_arg, true);
+ }
+
+ void ScrollIntoViewBottomBrowserTestTemplate(
+ const ax::mojom::Role expected_role,
+ BrowserAccessibility* (BrowserAccessibility::*f)() const) {
+ ScrollIntoViewBrowserTestTemplate(expected_role, f, expected_role, f,
+ false);
+ }
+
+ void ScrollIntoViewBottomBrowserTestTemplate(
+ const ax::mojom::Role expected_role_start,
+ BrowserAccessibility* (BrowserAccessibility::*fstart)() const,
+ const ax::mojom::Role expected_role_end,
+ BrowserAccessibility* (BrowserAccessibility::*fend)() const) {
+ ScrollIntoViewBrowserTestTemplate(expected_role_start, fstart,
+ expected_role_end, fend, false);
+ }
+
+ void ScrollIntoViewBottomBrowserTestTemplate(
+ const ax::mojom::Role expected_role_start,
+ BrowserAccessibility* (BrowserAccessibility::*fstart)(uint32_t) const,
+ const uint32_t fstart_arg,
+ const ax::mojom::Role expected_role_end,
+ BrowserAccessibility* (BrowserAccessibility::*fend)(uint32_t) const,
+ const uint32_t fend_arg) {
+ ScrollIntoViewBrowserTestTemplate(expected_role_start, fstart, fstart_arg,
+ expected_role_end, fend, fend_arg, false);
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ GetBoundingRectangles) {
+ LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <style>
+ .break_word {
+ width: 50px;
+ word-wrap: break-word;
+ }
+ </style>
+ </head>
+ <body>
+ <p class="break_word">AsdfAsdfAsdf</p>
+ </body>
+ </html>
+ )HTML"));
+
+ auto* node = FindNode(ax::mojom::Role::kStaticText, "AsdfAsdfAsdf");
+ ASSERT_NE(nullptr, node);
+ EXPECT_TRUE(node->PlatformIsLeaf());
+ EXPECT_EQ(0u, node->PlatformChildCount());
+
+ ComPtr<ITextRangeProvider> text_range_provider;
+ GetTextRangeProviderFromTextNode(text_range_provider, node);
+ ASSERT_NE(nullptr, text_range_provider.Get());
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"AsdfAsdfAsdf");
+
+ base::win::ScopedSafearray rectangles;
+ EXPECT_HRESULT_SUCCEEDED(
+ text_range_provider->GetBoundingRectangles(rectangles.Receive()));
+
+ // |view_offset| is necessary to account for differences in the shell
+ // between platforms (e.g. title bar height) because the results of
+ // |GetBoundingRectangles| are in screen coordinates.
+ gfx::Vector2d view_offset =
+ node->manager()->GetViewBounds().OffsetFromOrigin();
+ std::vector<double> expected_values = {
+ 8 + view_offset.x(), 16 + view_offset.y(), 49, 17,
+ 8 + view_offset.x(), 34 + view_offset.y(), 44, 17};
+ EXPECT_UIA_DOUBLE_SAFEARRAY_EQ(rectangles.Get(), expected_values);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewTopStaticText) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/text.html");
+ ScrollIntoViewTopBrowserTestTemplate(
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestFirstChild);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewBottomStaticText) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/text.html");
+ ScrollIntoViewBottomBrowserTestTemplate(
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestFirstChild);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewTopEmbeddedText) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/embedded-text.html");
+ ScrollIntoViewTopBrowserTestTemplate(
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestLastChild);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewBottomEmbeddedText) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/embedded-text.html");
+ ScrollIntoViewBottomBrowserTestTemplate(
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestLastChild);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewTopEmbeddedTextCrossNode) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/embedded-text.html");
+ ScrollIntoViewTopBrowserTestTemplate(
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestFirstChild,
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestLastChild);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewBottomEmbeddedTextCrossNode) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/embedded-text.html");
+ ScrollIntoViewBottomBrowserTestTemplate(
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestFirstChild,
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestLastChild);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewTopTable) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/table.html");
+ ScrollIntoViewTopBrowserTestTemplate(
+ ax::mojom::Role::kTable, &BrowserAccessibility::PlatformGetChild, 0,
+ ax::mojom::Role::kTable, &BrowserAccessibility::PlatformGetChild, 0);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewBottomTable) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/table.html");
+ ScrollIntoViewBottomBrowserTestTemplate(
+ ax::mojom::Role::kTable, &BrowserAccessibility::PlatformGetChild, 0,
+ ax::mojom::Role::kTable, &BrowserAccessibility::PlatformGetChild, 0);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewTopTableText) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/table.html");
+ ScrollIntoViewTopBrowserTestTemplate(
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestLastChild);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewBottomTableText) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/table.html");
+ ScrollIntoViewBottomBrowserTestTemplate(
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestLastChild);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewTopLinkText) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/link.html");
+ ScrollIntoViewTopBrowserTestTemplate(
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestLastChild);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewBottomLinkText) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/link.html");
+ ScrollIntoViewBottomBrowserTestTemplate(
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestLastChild);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewTopLinkContainer) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/link.html");
+ ScrollIntoViewTopBrowserTestTemplate(ax::mojom::Role::kGenericContainer,
+ &BrowserAccessibility::PlatformGetChild,
+ 0, ax::mojom::Role::kGenericContainer,
+ &BrowserAccessibility::PlatformGetChild,
+ 0);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewBottomLinkContainer) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/link.html");
+ ScrollIntoViewBottomBrowserTestTemplate(
+ ax::mojom::Role::kGenericContainer,
+ &BrowserAccessibility::PlatformGetChild, 0,
+ ax::mojom::Role::kGenericContainer,
+ &BrowserAccessibility::PlatformGetChild, 0);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewTopTextFromIFrame) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/iframe-text.html");
+ WaitForAccessibilityTreeToContainNodeWithName(
+ shell()->web_contents(),
+ "Game theory is \"the study of Mathematical model mathematical models of "
+ "conflict and cooperation between intelligent rational decision-makers."
+ "\"");
+ ScrollIntoViewFromIframeBrowserTestTemplate(
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestFirstChild,
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestLastChild, true);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ScrollIntoViewBottomTextFromIFrame) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/iframe-text.html");
+ WaitForAccessibilityTreeToContainNodeWithName(
+ shell()->web_contents(),
+ "Game theory is \"the study of Mathematical model mathematical models of "
+ "conflict and cooperation between intelligent rational decision-makers."
+ "\"");
+ ScrollIntoViewFromIframeBrowserTestTemplate(
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestFirstChild,
+ ax::mojom::Role::kStaticText,
+ &BrowserAccessibility::PlatformDeepestLastChild, false);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ MoveEndpointByUnitFormat) {
+ LoadInitialAccessibilityTreeFromHtml(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <div>plain 1</div><div>plain 2</div>
+ <div style="font-style: italic">italic 1</div>
+ <div style="font-style: italic">italic 2</div>
+ <div style="font-weight: bold">bold 1</div>
+ <div style="font-weight: bold">bold 2</div>
+ </body>
+ </html>)HTML");
+ auto* node = FindNode(ax::mojom::Role::kStaticText, "plain 1");
+ ASSERT_NE(nullptr, node);
+ EXPECT_TRUE(node->PlatformIsLeaf());
+ EXPECT_EQ(0u, node->PlatformChildCount());
+
+ ComPtr<ITextRangeProvider> text_range_provider;
+ GetTextRangeProviderFromTextNode(text_range_provider, node);
+ ASSERT_NE(nullptr, text_range_provider.Get());
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"plain 1");
+
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 1,
+ /*expected_text*/ L"plain 1plain 2",
+ /*expected_count*/ 1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 1,
+ /*expected_text*/
+ L"plain 1plain 2italic 1italic 2",
+ /*expected_count*/ 1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ -1,
+ /*expected_text*/ L"plain 1plain 2",
+ /*expected_count*/ -1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 1,
+ /*expected_text*/
+ L"plain 1plain 2italic 1italic 2",
+ /*expected_count*/ 1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 5,
+ /*expected_text*/
+ L"plain 1plain 2italic 1italic 2bold 1bold 2",
+ /*expected_count*/ 1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ -4,
+ /*expected_text*/ L"",
+ /*expected_count*/ -3);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 1,
+ /*expected_text*/ L"plain 1plain 2",
+ /*expected_count*/ 1);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ MoveEndpointByUnitFormatAllFormats) {
+ LoadInitialAccessibilityTreeFromHtml(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <div>plain 1</div><div>plain 2</div>
+ <div style="background-color: red">background-color 1</div>
+ <div style="background-color: red">background-color 2</div>
+ <div style="color: blue">color 1</div>
+ <div style="color: blue">color 2</div>
+ <div style="text-decoration: overline">overline 1</div>
+ <div style="text-decoration: overline">overline 2</div>
+ <div style="text-decoration: line-through">line-through 1</div>
+ <div style="text-decoration: line-through">line-through 2</div>
+ <div style="vertical-align:super">sup 1</div>
+ <div style="vertical-align:super">sup 2</div>
+ <div style="font-weight: bold">bold 1</div>
+ <div style="font-weight: bold">bold 2</div>
+ <div style="font-family: sans-serif">font-family 1</div>
+ <div style="font-family: sans-serif">font-family 2</div>
+ </body>
+ </html>)HTML");
+ auto* node = FindNode(ax::mojom::Role::kStaticText, "plain 1");
+ ASSERT_NE(nullptr, node);
+ EXPECT_TRUE(node->PlatformIsLeaf());
+ EXPECT_EQ(0u, node->PlatformChildCount());
+
+ ComPtr<ITextRangeProvider> text_range_provider;
+ GetTextRangeProviderFromTextNode(text_range_provider, node);
+ ASSERT_NE(nullptr, text_range_provider.Get());
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"plain 1");
+
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 1,
+ /*expected_text*/ L"plain 1plain 2",
+ /*expected_count*/ 1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 1,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2",
+ /*expected_count*/ 1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ -1,
+ /*expected_text*/ L"plain 1plain 2",
+ /*expected_count*/ -1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 2,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2color 1color 2",
+ /*expected_count*/ 2);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ -1,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2",
+ /*expected_count*/ -1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 2,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2color 1color "
+ L"2overline 1overline 2",
+ /*expected_count*/ 2);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ -1,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2color 1color 2",
+ /*expected_count*/ -1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 2,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2color 1color "
+ L"2overline 1overline 2line-through 1line-through 2",
+ /*expected_count*/ 2);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ -1,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2color 1color "
+ L"2overline 1overline 2",
+ /*expected_count*/ -1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 2,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2color 1color "
+ L"2overline 1overline 2line-through 1line-through 2sup 1sup 2",
+ /*expected_count*/ 2);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ -1,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2color 1color "
+ L"2overline 1overline 2line-through 1line-through 2",
+ /*expected_count*/ -1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 2,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2color 1color "
+ L"2overline 1overline 2line-through 1line-through 2sup 1sup 2bold 1bold "
+ L"2",
+ /*expected_count*/ 2);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ -1,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2color 1color "
+ L"2overline 1overline 2line-through 1line-through 2sup 1sup 2",
+ /*expected_count*/ -1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ 2,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2color 1color "
+ L"2overline 1overline 2line-through 1line-through 2sup 1sup 2bold 1bold "
+ L"2font-family 1font-family 2",
+ /*expected_count*/ 2);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Format,
+ /*count*/ -1,
+ /*expected_text*/
+ L"plain 1plain 2background-color 1background-color 2color 1color "
+ L"2overline 1overline 2line-through 1line-through 2sup 1sup 2bold 1bold "
+ L"2",
+ /*expected_count*/ -1);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ IFrameTraversal) {
+ LoadInitialAccessibilityTreeFromUrl(embedded_test_server()->GetURL(
+ "/accessibility/html/iframe-cross-process.html"));
+
+ WaitForAccessibilityTreeToContainNodeWithName(shell()->web_contents(),
+ "Text in iframe");
+
+ auto* node = FindNode(ax::mojom::Role::kStaticText, "After frame");
+ ASSERT_NE(nullptr, node);
+ EXPECT_TRUE(node->PlatformIsLeaf());
+ EXPECT_EQ(0u, node->PlatformChildCount());
+
+ ComPtr<ITextRangeProvider> text_range_provider;
+ GetTextRangeProviderFromTextNode(text_range_provider, node);
+ ASSERT_NE(nullptr, text_range_provider.Get());
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"After frame");
+
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Word,
+ /*count*/ -1,
+ /*expected_text*/ L"iframeAfter frame",
+ /*expected_count*/ -1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Word,
+ /*count*/ -2,
+ /*expected_text*/ L"Text in iframeAfter frame",
+ /*expected_count*/ -2);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(text_range_provider,
+ TextPatternRangeEndpoint_End, TextUnit_Word,
+ /*count*/ -3,
+ /*expected_text*/ L"Text in",
+ /*expected_count*/ -3);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(text_range_provider,
+ TextPatternRangeEndpoint_End, TextUnit_Word,
+ /*count*/ 2,
+ /*expected_text*/ L"Text in iframeAfter",
+ /*expected_count*/ 2);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Line,
+ /*count*/ 1,
+ /*expected_text*/ L"Text in iframeAfter frame",
+ /*expected_count*/ 1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Document,
+ /*count*/ 1,
+ /*expected_text*/ L"",
+ /*expected_count*/ 1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Character,
+ /*count*/ -17,
+ /*expected_text*/ L"iframeAfter frame",
+ /*expected_count*/ -17);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(text_range_provider,
+ TextPatternRangeEndpoint_End, TextUnit_Line,
+ /*count*/ -1,
+ /*expected_text*/ L"iframe",
+ /*expected_count*/ -1);
+
+ text_range_provider->ExpandToEnclosingUnit(TextUnit_Line);
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"Text in iframe");
+
+ text_range_provider->ExpandToEnclosingUnit(TextUnit_Document);
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider,
+ L"Before frameText in iframeAfter frame");
+
+ EXPECT_UIA_MOVE(text_range_provider, TextUnit_Word,
+ /*count*/ 2,
+ /*expected_text*/ L"Text",
+ /*expected_count*/ 2);
+ EXPECT_UIA_MOVE(text_range_provider, TextUnit_Word,
+ /*count*/ -1,
+ /*expected_text*/ L"frame",
+ /*expected_count*/ -1);
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Character,
+ /*count*/ 1,
+ /*expected_text*/ L"frameT",
+ /*expected_count*/ 1);
+ EXPECT_UIA_MOVE(text_range_provider, TextUnit_Character,
+ /*count*/ 6,
+ /*expected_text*/ L"e",
+ /*expected_count*/ 6);
+ EXPECT_UIA_MOVE(text_range_provider, TextUnit_Character,
+ /*count*/ 19,
+ /*expected_text*/ L"f",
+ /*expected_count*/ 19);
+ EXPECT_UIA_MOVE(text_range_provider, TextUnit_Character,
+ /*count*/ -7,
+ /*expected_text*/ L"e",
+ /*expected_count*/ -7);
+ EXPECT_UIA_MOVE(text_range_provider, TextUnit_Line,
+ /*count*/ 1,
+ /*expected_text*/ L"After frame",
+ /*expected_count*/ 1);
+
+ text_range_provider->ExpandToEnclosingUnit(TextUnit_Document);
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider,
+ L"Before frameText in iframeAfter frame");
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ ExpandToEnclosingFormat) {
+ LoadInitialAccessibilityTreeFromHtml(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <div>plain</div>
+ <div>text</div>
+ <div style="font-style: italic">italic<div>
+ <div style="font-style: italic">text<div>
+ </body>
+ </html>)HTML");
+
+ auto* node = FindNode(ax::mojom::Role::kStaticText, "plain");
+ ASSERT_NE(nullptr, node);
+ EXPECT_TRUE(node->PlatformIsLeaf());
+ EXPECT_EQ(0u, node->PlatformChildCount());
+
+ ComPtr<ITextRangeProvider> text_range_provider;
+ GetTextRangeProviderFromTextNode(text_range_provider, node);
+ ASSERT_NE(nullptr, text_range_provider.Get());
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"plain");
+
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Character,
+ /*count*/ 3,
+ /*expected_text*/ L"in",
+ /*expected_count*/ 3);
+
+ ASSERT_HRESULT_SUCCEEDED(
+ text_range_provider->ExpandToEnclosingUnit(TextUnit_Format));
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"plaintext");
+
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Character,
+ /*count*/ 3,
+ /*expected_text*/ L"plaintextita",
+ /*expected_count*/ 3);
+
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Character,
+ /*count*/ 10,
+ /*expected_text*/ L"ta",
+ /*expected_count*/ 10);
+
+ ASSERT_HRESULT_SUCCEEDED(
+ text_range_provider->ExpandToEnclosingUnit(TextUnit_Format));
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"italictext");
+}
+} // namespace content
diff --git a/chromium/content/browser/accessibility/ax_platform_node_win_browsertest.cc b/chromium/content/browser/accessibility/ax_platform_node_win_browsertest.cc
index 1a9cb7b9ae5..72878a880a7 100644
--- a/chromium/content/browser/accessibility/ax_platform_node_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/ax_platform_node_win_browsertest.cc
@@ -5,83 +5,45 @@
#include "ui/accessibility/platform/ax_platform_node_win.h"
#include "base/win/scoped_variant.h"
+#include "content/browser/accessibility/accessibility_content_browsertest.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_com_win.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 "net/base/escape.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
using Microsoft::WRL::ComPtr;
namespace content {
-class AXPlatformNodeWinBrowserTest : public ContentBrowserTest {
+class AXPlatformNodeWinBrowserTest : public AccessibilityContentBrowserTest {
protected:
- void LoadInitialAccessibilityTreeFromUrl(
- const GURL& url,
- ui::AXMode accessibility_mode = ui::kAXModeComplete) {
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- accessibility_mode,
- ax::mojom::Event::kLoadComplete);
- NavigateToURL(shell(), url);
- waiter.WaitForNotification();
+ template <typename T>
+ ComPtr<T> QueryInterfaceFromNode(
+ BrowserAccessibility* browser_accessibility) {
+ ComPtr<T> result;
+ EXPECT_HRESULT_SUCCEEDED(
+ browser_accessibility->GetNativeViewAccessible()->QueryInterface(
+ __uuidof(T), &result));
+ return result;
}
- void LoadInitialAccessibilityTreeFromHtmlFilePath(
- const std::string& html_file_path,
- ui::AXMode accessibility_mode = ui::kAXModeComplete) {
- if (!embedded_test_server()->Started())
- ASSERT_TRUE(embedded_test_server()->Start());
- ASSERT_TRUE(embedded_test_server()->Started());
- LoadInitialAccessibilityTreeFromUrl(
- embedded_test_server()->GetURL(html_file_path), accessibility_mode);
+ ComPtr<IAccessible> IAccessibleFromNode(
+ BrowserAccessibility* browser_accessibility) {
+ return QueryInterfaceFromNode<IAccessible>(browser_accessibility);
}
- void LoadInitialAccessibilityTreeFromHtml(
- const std::string& html,
- ui::AXMode accessibility_mode = ui::kAXModeComplete) {
- LoadInitialAccessibilityTreeFromUrl(
- GURL("data:text/html," + net::EscapeQueryParamValue(html, false)),
- accessibility_mode);
- }
-
- BrowserAccessibilityManager* GetManagerAndAssertNonNull() {
- auto GetManagerAndAssertNonNull =
- [this](BrowserAccessibilityManager** result) {
- WebContentsImpl* web_contents_impl =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- ASSERT_NE(nullptr, web_contents_impl);
- BrowserAccessibilityManager* browser_accessibility_manager =
- web_contents_impl->GetRootBrowserAccessibilityManager();
- ASSERT_NE(nullptr, browser_accessibility_manager);
- *result = browser_accessibility_manager;
- };
-
- BrowserAccessibilityManager* browser_accessibility_manager;
- GetManagerAndAssertNonNull(&browser_accessibility_manager);
- return browser_accessibility_manager;
- }
-
- BrowserAccessibility* GetRootAndAssertNonNull() {
- auto GetRootAndAssertNonNull = [this](BrowserAccessibility** result) {
- BrowserAccessibility* root_browser_accessibility =
- GetManagerAndAssertNonNull()->GetRoot();
- ASSERT_NE(nullptr, result);
- *result = root_browser_accessibility;
- };
-
- BrowserAccessibility* root_browser_accessibility;
- GetRootAndAssertNonNull(&root_browser_accessibility);
- return root_browser_accessibility;
- }
-
- BrowserAccessibility* FindNode(ax::mojom::Role role,
- const std::string& name_or_value) {
- return FindNodeInSubtree(*GetRootAndAssertNonNull(), role, name_or_value);
+ ComPtr<IAccessible2> ToIAccessible2(ComPtr<IAccessible> accessible) {
+ CHECK(accessible);
+ ComPtr<IServiceProvider> service_provider;
+ accessible.As(&service_provider);
+ ComPtr<IAccessible2> result;
+ CHECK(SUCCEEDED(service_provider->QueryService(IID_IAccessible2,
+ IID_PPV_ARGS(&result))));
+ return result;
}
void UIAGetPropertyValueFlowsFromBrowserTestTemplate(
@@ -164,38 +126,60 @@ class AXPlatformNodeWinBrowserTest : public ContentBrowserTest {
ASSERT_EQ(nullptr, window_provider.Get());
}
}
-
- private:
- BrowserAccessibility* FindNodeInSubtree(BrowserAccessibility& node,
- ax::mojom::Role role,
- const std::string& name_or_value) {
- const auto& name =
- node.GetStringAttribute(ax::mojom::StringAttribute::kName);
- const auto& value =
- node.GetStringAttribute(ax::mojom::StringAttribute::kValue);
- if (node.GetRole() == role &&
- (name == name_or_value || value == name_or_value)) {
- return &node;
- }
-
- for (unsigned int i = 0; i < node.PlatformChildCount(); ++i) {
- BrowserAccessibility* result =
- FindNodeInSubtree(*node.PlatformGetChild(i), role, name_or_value);
- if (result)
- return result;
- }
-
- return nullptr;
- }
};
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
+ IA2ScrollToPointIframeText) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/scrolling/iframe-text.html");
+ WaitForAccessibilityTreeToContainNodeWithName(
+ shell()->web_contents(),
+ "Game theory is \"the study of Mathematical model mathematical models of "
+ "conflict and cooperation between intelligent rational decision-makers."
+ "\"");
+
+ BrowserAccessibility* browser_accessibility =
+ GetRootAndAssertNonNull()->PlatformDeepestLastChild();
+ ASSERT_NE(nullptr, browser_accessibility);
+ ASSERT_EQ(ax::mojom::Role::kStaticText, browser_accessibility->GetRole());
+
+ BrowserAccessibility* iframe_browser_accessibility =
+ browser_accessibility->manager()->GetRoot();
+ ASSERT_NE(nullptr, iframe_browser_accessibility);
+ ASSERT_EQ(ax::mojom::Role::kRootWebArea,
+ iframe_browser_accessibility->GetRole());
+
+ gfx::Rect iframe_screen_bounds = iframe_browser_accessibility->GetBoundsRect(
+ ui::AXCoordinateSystem::kScreen, ui::AXClippingBehavior::kUnclipped);
+
+ AccessibilityNotificationWaiter location_changed_waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kLocationChanged);
+ ComPtr<IAccessible2> root_iaccessible2 =
+ ToIAccessible2(IAccessibleFromNode(browser_accessibility));
+ ASSERT_EQ(S_OK, root_iaccessible2->scrollToPoint(
+ IA2_COORDTYPE_SCREEN_RELATIVE, iframe_screen_bounds.x(),
+ iframe_screen_bounds.y()));
+ location_changed_waiter.WaitForNotification();
+
+ gfx::Rect bounds = browser_accessibility->GetBoundsRect(
+ ui::AXCoordinateSystem::kScreen, ui::AXClippingBehavior::kUnclipped);
+ ASSERT_EQ(iframe_screen_bounds.y(), bounds.y());
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAGetPropertyValueFlowsFromNone) {
LoadInitialAccessibilityTreeFromHtmlFilePath(
"/accessibility/aria/aria-label.html");
- UIAGetPropertyValueFlowsFromBrowserTestTemplate(
- FindNode(ax::mojom::Role::kCheckBox, "aria label"), {});
+ base::win::ScopedVariant flows_from_variant;
+ ComPtr<IRawElementProviderSimple> node_provider =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(
+ FindNode(ax::mojom::Role::kCheckBox, "aria label"));
+ node_provider->GetPropertyValue(UIA_FlowsFromPropertyId,
+ flows_from_variant.Receive());
+ ASSERT_EQ(VT_ARRAY | VT_UNKNOWN, flows_from_variant.type());
+ ASSERT_EQ(nullptr, V_ARRAY(flows_from_variant.ptr()));
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
@@ -409,4 +393,37 @@ IN_PROC_BROWSER_TEST_F(
ax::mojom::Role::kAlertDialog, &BrowserAccessibility::PlatformGetChild, 0,
true, true);
}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
+ UIAGetPropertyValueAutomationId) {
+ LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+ <!DOCTYPE html>
+ <html>
+ </body>
+ <div id="id"></div>
+ </body>
+ </html>
+ )HTML"));
+
+ BrowserAccessibility* root_browser_accessibility = GetRootAndAssertNonNull();
+ BrowserAccessibilityComWin* root_browser_accessibility_com_win =
+ ToBrowserAccessibilityWin(root_browser_accessibility)->GetCOM();
+ ASSERT_NE(nullptr, root_browser_accessibility_com_win);
+
+ BrowserAccessibility* browser_accessibility =
+ root_browser_accessibility->PlatformDeepestLastChild();
+ ASSERT_NE(nullptr, browser_accessibility);
+ ASSERT_EQ(ax::mojom::Role::kGenericContainer,
+ browser_accessibility->GetRole());
+ BrowserAccessibilityComWin* browser_accessibility_com_win =
+ ToBrowserAccessibilityWin(browser_accessibility)->GetCOM();
+ ASSERT_NE(nullptr, browser_accessibility_com_win);
+
+ base::win::ScopedVariant expected_scoped_variant;
+ expected_scoped_variant.Set(SysAllocString(L"id"));
+ base::win::ScopedVariant scoped_variant;
+ EXPECT_HRESULT_SUCCEEDED(browser_accessibility_com_win->GetPropertyValue(
+ UIA_AutomationIdPropertyId, scoped_variant.Receive()));
+ EXPECT_EQ(0, expected_scoped_variant.Compare(scoped_variant));
+}
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility.cc b/chromium/content/browser/accessibility/browser_accessibility.cc
index b5f678588b5..40da99607ba 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -21,6 +21,7 @@
#include "ui/accessibility/ax_node_position.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/ax_text_utils.h"
+#include "ui/accessibility/ax_tree_id.h"
#include "ui/accessibility/platform/ax_unique_id.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -39,6 +40,27 @@ BrowserAccessibility::BrowserAccessibility()
BrowserAccessibility::~BrowserAccessibility() {}
+namespace {
+
+int GetBoundaryTextOffsetInsideBaseAnchor(
+ ui::TextBoundaryDirection direction,
+ const BrowserAccessibilityPosition::AXPositionInstance& base,
+ const BrowserAccessibilityPosition::AXPositionInstance& position) {
+ if (base->GetAnchor() == position->GetAnchor())
+ return position->text_offset();
+
+ // If the position is outside the anchor of the base position, then return
+ // the first or last position in the same direction.
+ switch (direction) {
+ case ui::BACKWARDS_DIRECTION:
+ return base->CreatePositionAtStartOfAnchor()->text_offset();
+ case ui::FORWARDS_DIRECTION:
+ return base->CreatePositionAtEndOfAnchor()->text_offset();
+ }
+}
+
+} // namespace
+
void BrowserAccessibility::Init(BrowserAccessibilityManager* manager,
ui::AXNode* node) {
manager_ = manager;
@@ -307,7 +329,7 @@ BrowserAccessibility* BrowserAccessibility::InternalDeepestLastChild() const {
uint32_t BrowserAccessibility::InternalChildCount() const {
if (!node_ || !manager_)
return 0;
- return static_cast<uint32_t>(node_->child_count());
+ return uint32_t{node_->children().size()};
}
BrowserAccessibility* BrowserAccessibility::InternalGetChild(
@@ -315,7 +337,7 @@ BrowserAccessibility* BrowserAccessibility::InternalGetChild(
if (!node_ || !manager_ || child_index >= InternalChildCount())
return nullptr;
- auto* child_node = node_->ChildAtIndex(child_index);
+ auto* child_node = node_->children()[child_index];
DCHECK(child_node);
return manager_->GetFromAXNode(child_node);
}
@@ -381,20 +403,29 @@ gfx::Rect BrowserAccessibility::GetClippedFrameBoundsRect(
ui::AXClippingBehavior::kUnclipped, offscreen_result);
}
-gfx::Rect BrowserAccessibility::GetUnclippedScreenRangeBoundsRect(
+gfx::Rect BrowserAccessibility::GetUnclippedRootFrameHypertextRangeBoundsRect(
+ const int start_offset,
+ const int end_offset,
+ ui::AXOffscreenResult* offscreen_result) const {
+ return GetHypertextRangeBoundsRect(
+ start_offset, end_offset, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped, offscreen_result);
+}
+
+gfx::Rect BrowserAccessibility::GetUnclippedScreenInnerTextRangeBoundsRect(
const int start_offset,
const int end_offset,
ui::AXOffscreenResult* offscreen_result) const {
- return GetRangeBoundsRect(
+ return GetInnerTextRangeBoundsRect(
start_offset, end_offset, ui::AXCoordinateSystem::kScreen,
ui::AXClippingBehavior::kUnclipped, offscreen_result);
}
-gfx::Rect BrowserAccessibility::GetUnclippedRootFrameRangeBoundsRect(
+gfx::Rect BrowserAccessibility::GetUnclippedRootFrameInnerTextRangeBoundsRect(
const int start_offset,
const int end_offset,
ui::AXOffscreenResult* offscreen_result) const {
- return GetRangeBoundsRect(
+ return GetInnerTextRangeBoundsRect(
start_offset, end_offset, ui::AXCoordinateSystem::kRootFrame,
ui::AXClippingBehavior::kUnclipped, offscreen_result);
}
@@ -407,7 +438,7 @@ gfx::Rect BrowserAccessibility::GetBoundsRect(
clipping_behavior, offscreen_result);
}
-gfx::Rect BrowserAccessibility::GetRangeBoundsRect(
+gfx::Rect BrowserAccessibility::GetHypertextRangeBoundsRect(
const int start_offset,
const int end_offset,
const ui::AXCoordinateSystem coordinate_system,
@@ -421,7 +452,7 @@ gfx::Rect BrowserAccessibility::GetRangeBoundsRect(
if (effective_start_offset > effective_end_offset)
std::swap(effective_start_offset, effective_end_offset);
- const base::string16& text_str = GetText();
+ const base::string16& text_str = GetHypertext();
if (effective_start_offset < 0 ||
effective_start_offset >= static_cast<int>(text_str.size()))
return gfx::Rect();
@@ -431,14 +462,14 @@ gfx::Rect BrowserAccessibility::GetRangeBoundsRect(
switch (coordinate_system) {
case ui::AXCoordinateSystem::kScreen: {
- gfx::Rect bounds = GetRootFrameRangeBoundsRect(
+ gfx::Rect bounds = GetRootFrameHypertextRangeBoundsRect(
effective_start_offset, effective_end_offset - effective_start_offset,
clipping_behavior, offscreen_result);
bounds.Offset(manager_->GetViewBounds().OffsetFromOrigin());
return bounds;
}
case ui::AXCoordinateSystem::kRootFrame:
- return GetRootFrameRangeBoundsRect(
+ return GetRootFrameHypertextRangeBoundsRect(
effective_start_offset, effective_end_offset - effective_start_offset,
clipping_behavior, offscreen_result);
case ui::AXCoordinateSystem::kFrame:
@@ -447,7 +478,7 @@ gfx::Rect BrowserAccessibility::GetRangeBoundsRect(
}
}
-gfx::Rect BrowserAccessibility::GetRootFrameRangeBoundsRect(
+gfx::Rect BrowserAccessibility::GetRootFrameHypertextRangeBoundsRect(
int start,
int len,
const ui::AXClippingBehavior clipping_behavior,
@@ -459,7 +490,7 @@ gfx::Rect BrowserAccessibility::GetRootFrameRangeBoundsRect(
// holds all the text.
// TODO(nektar): This is fragile! Replace with code that flattens tree.
if (IsPlainTextField() && InternalChildCount() == 1) {
- return InternalGetChild(0)->GetRootFrameRangeBoundsRect(
+ return InternalGetChild(0)->GetRootFrameHypertextRangeBoundsRect(
start, len, clipping_behavior, offscreen_result);
}
@@ -471,16 +502,16 @@ gfx::Rect BrowserAccessibility::GetRootFrameRangeBoundsRect(
// embedded object character. The exception is text-only objects.
int child_length_in_parent = 1;
if (child->IsTextOnlyObject())
- child_length_in_parent = static_cast<int>(child->GetText().size());
+ child_length_in_parent = static_cast<int>(child->GetHypertext().size());
if (start < child_length_in_parent) {
gfx::Rect child_rect;
if (child->IsTextOnlyObject()) {
- child_rect = child->GetRootFrameRangeBoundsRect(
+ child_rect = child->GetRootFrameHypertextRangeBoundsRect(
start, len, clipping_behavior, offscreen_result);
} else {
- child_rect = child->GetRootFrameRangeBoundsRect(
- 0, static_cast<int>(child->GetText().size()), clipping_behavior,
- offscreen_result);
+ child_rect = child->GetRootFrameHypertextRangeBoundsRect(
+ 0, static_cast<int>(child->GetHypertext().size()),
+ clipping_behavior, offscreen_result);
}
bounds.Union(child_rect);
len -= (child_length_in_parent - start);
@@ -492,8 +523,8 @@ gfx::Rect BrowserAccessibility::GetRootFrameRangeBoundsRect(
}
// When past the end of text, the area will be 0.
// In this case, use bounds provided for the caret.
- return bounds.IsEmpty() ? GetRootFrameBoundsPastEndOfText(clipping_behavior,
- offscreen_result)
+ return bounds.IsEmpty() ? GetRootFrameHypertextBoundsPastEndOfText(
+ clipping_behavior, offscreen_result)
: bounds;
}
@@ -509,7 +540,7 @@ gfx::Rect BrowserAccessibility::GetRootFrameRangeBoundsRect(
continue;
}
- int child_length = static_cast<int>(child->GetText().size());
+ int child_length = static_cast<int>(child->GetHypertext().size());
child_start = child_end;
child_end += child_length;
@@ -528,61 +559,12 @@ gfx::Rect BrowserAccessibility::GetRootFrameRangeBoundsRect(
DCHECK_GE(local_end, 0);
DCHECK_LE(local_end, child_length);
- const std::vector<int32_t>& character_offsets = child->GetIntListAttribute(
- ax::mojom::IntListAttribute::kCharacterOffsets);
- int character_offsets_length = static_cast<int>(character_offsets.size());
- if (character_offsets_length < child_length) {
- // Blink might not return pixel offsets for all characters.
- // Clamp the character range to be within the number of provided pixels.
- local_start = std::min(local_start, character_offsets_length);
- local_end = std::min(local_end, character_offsets_length);
- }
- int start_pixel_offset =
- local_start > 0 ? character_offsets[local_start - 1] : 0;
- int end_pixel_offset = local_end > 0 ? character_offsets[local_end - 1] : 0;
- int max_pixel_offset = character_offsets_length > 0
- ? character_offsets[character_offsets_length - 1]
- : 0;
-
- auto text_direction = static_cast<ax::mojom::TextDirection>(
- child->GetIntAttribute(ax::mojom::IntAttribute::kTextDirection));
- gfx::RectF child_overlap_rect;
- switch (text_direction) {
- case ax::mojom::TextDirection::kNone:
- case ax::mojom::TextDirection::kLtr: {
- 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 = 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 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 = 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;
- }
- }
-
// Don't clip bounds. Some screen magnifiers (e.g. ZoomText) prefer to
// get unclipped bounds so that they can make smooth scrolling calculations.
gfx::Rect absolute_child_rect = child->RelativeToAbsoluteBounds(
- child_overlap_rect, ui::AXCoordinateSystem::kRootFrame,
- clipping_behavior, offscreen_result);
+ child->GetInlineTextRect(local_start, local_end, child_length),
+ ui::AXCoordinateSystem::kRootFrame, clipping_behavior,
+ offscreen_result);
if (bounds.width() == 0 && bounds.height() == 0) {
bounds = absolute_child_rect;
} else {
@@ -593,13 +575,13 @@ gfx::Rect BrowserAccessibility::GetRootFrameRangeBoundsRect(
return bounds;
}
-gfx::Rect BrowserAccessibility::GetScreenRangeBoundsRect(
+gfx::Rect BrowserAccessibility::GetScreenHypertextRangeBoundsRect(
int start,
int len,
const ui::AXClippingBehavior clipping_behavior,
ui::AXOffscreenResult* offscreen_result) const {
- gfx::Rect bounds = GetRootFrameRangeBoundsRect(start, len, clipping_behavior,
- offscreen_result);
+ gfx::Rect bounds = GetRootFrameHypertextRangeBoundsRect(
+ start, len, clipping_behavior, offscreen_result);
// Adjust the bounds by the top left corner of the containing view's bounds
// in screen coordinates.
@@ -608,7 +590,7 @@ gfx::Rect BrowserAccessibility::GetScreenRangeBoundsRect(
return bounds;
}
-gfx::Rect BrowserAccessibility::GetRootFrameBoundsPastEndOfText(
+gfx::Rect BrowserAccessibility::GetRootFrameHypertextBoundsPastEndOfText(
const ui::AXClippingBehavior clipping_behavior,
ui::AXOffscreenResult* offscreen_result) const {
// Step 1: get approximate caret bounds. The thickness may not yet be correct.
@@ -617,8 +599,8 @@ gfx::Rect BrowserAccessibility::GetRootFrameBoundsPastEndOfText(
// When past the end of text, use bounds provided by a last child if
// available, and then correct for thickness of caret.
BrowserAccessibility* child = InternalGetChild(InternalChildCount() - 1);
- int child_text_len = child->GetText().size();
- bounds = child->GetRootFrameRangeBoundsRect(
+ int child_text_len = child->GetHypertext().size();
+ bounds = child->GetRootFrameHypertextRangeBoundsRect(
child_text_len, child_text_len, clipping_behavior, offscreen_result);
if (bounds.width() == 0 && bounds.height() == 0)
return bounds; // Inline text boxes info not yet available.
@@ -656,6 +638,136 @@ gfx::Rect BrowserAccessibility::GetRootFrameBoundsPastEndOfText(
return bounds;
}
+gfx::Rect BrowserAccessibility::GetInnerTextRangeBoundsRect(
+ const int start_offset,
+ const int end_offset,
+ const ui::AXCoordinateSystem coordinate_system,
+ const ui::AXClippingBehavior clipping_behavior,
+ ui::AXOffscreenResult* offscreen_result) const {
+ const int inner_text_length = GetInnerText().length();
+ if (start_offset < 0 || end_offset > inner_text_length ||
+ start_offset > end_offset)
+ return gfx::Rect();
+
+ return GetInnerTextRangeBoundsRectInSubtree(
+ start_offset, end_offset, coordinate_system, clipping_behavior,
+ offscreen_result);
+}
+
+gfx::Rect BrowserAccessibility::GetInnerTextRangeBoundsRectInSubtree(
+ const int start_offset,
+ const int end_offset,
+ const ui::AXCoordinateSystem coordinate_system,
+ const ui::AXClippingBehavior clipping_behavior,
+ ui::AXOffscreenResult* offscreen_result) const {
+ if (GetRole() == ax::mojom::Role::kInlineTextBox) {
+ return RelativeToAbsoluteBounds(
+ GetInlineTextRect(start_offset, end_offset, GetInnerText().length()),
+ coordinate_system, clipping_behavior, offscreen_result);
+ }
+
+ const uint32_t internal_child_count = InternalChildCount();
+ if (IsPlainTextField() && internal_child_count == 1) {
+ return InternalGetChild(0)->RelativeToAbsoluteBounds(
+ GetInlineTextRect(start_offset, end_offset, GetInnerText().length()),
+ coordinate_system, clipping_behavior, offscreen_result);
+ }
+
+ gfx::Rect bounds;
+ int child_offset_in_parent = 0;
+ for (uint32_t i = 0; i < internal_child_count; ++i) {
+ const BrowserAccessibility* browser_accessibility_child =
+ InternalGetChild(i);
+ const int child_inner_text_length =
+ browser_accessibility_child->GetInnerText().length();
+
+ // The text bounds queried are not in this subtree; skip it and continue.
+ const int child_start_offset =
+ std::max(start_offset - child_offset_in_parent, 0);
+ if (child_start_offset > child_inner_text_length) {
+ child_offset_in_parent += child_inner_text_length;
+ continue;
+ }
+
+ // The text bounds queried have already been gathered; short circuit.
+ const int child_end_offset =
+ std::min(end_offset - child_offset_in_parent, child_inner_text_length);
+ if (child_end_offset < 0)
+ return bounds;
+
+ // Increase the text bounds by the subtree text bounds.
+ const gfx::Rect child_bounds =
+ browser_accessibility_child->GetInnerTextRangeBoundsRectInSubtree(
+ child_start_offset, child_end_offset, coordinate_system,
+ clipping_behavior, offscreen_result);
+ if (bounds.IsEmpty())
+ bounds = child_bounds;
+ else
+ bounds.Union(child_bounds);
+
+ child_offset_in_parent += child_inner_text_length;
+ }
+
+ return bounds;
+}
+
+gfx::RectF BrowserAccessibility::GetInlineTextRect(const int start_offset,
+ const int end_offset,
+ const int max_length) const {
+ DCHECK(start_offset >= 0 && end_offset >= 0 && start_offset <= end_offset);
+ int local_start_offset = start_offset, local_end_offset = end_offset;
+ const std::vector<int32_t>& character_offsets =
+ GetIntListAttribute(ax::mojom::IntListAttribute::kCharacterOffsets);
+ const int character_offsets_length = character_offsets.size();
+ if (character_offsets_length < max_length) {
+ // Blink might not return pixel offsets for all characters. Clamp the
+ // character range to be within the number of provided pixels.
+ local_start_offset = std::min(local_start_offset, character_offsets_length);
+ local_end_offset = std::min(local_end_offset, character_offsets_length);
+ }
+
+ const int start_pixel_offset =
+ local_start_offset > 0 ? character_offsets[local_start_offset - 1] : 0;
+ const int end_pixel_offset =
+ local_end_offset > 0 ? character_offsets[local_end_offset - 1] : 0;
+ const int max_pixel_offset =
+ character_offsets_length > 0
+ ? character_offsets[character_offsets_length - 1]
+ : 0;
+ const gfx::RectF location = GetLocation();
+ const int location_width = location.width();
+ const int location_height = location.height();
+
+ gfx::RectF bounds;
+ switch (static_cast<ax::mojom::TextDirection>(
+ GetIntAttribute(ax::mojom::IntAttribute::kTextDirection))) {
+ case ax::mojom::TextDirection::kNone:
+ case ax::mojom::TextDirection::kLtr:
+ bounds =
+ gfx::RectF(start_pixel_offset, 0,
+ end_pixel_offset - start_pixel_offset, location_height);
+ break;
+ case ax::mojom::TextDirection::kRtl: {
+ const int left = max_pixel_offset - end_pixel_offset;
+ const int right = max_pixel_offset - start_pixel_offset;
+ bounds = gfx::RectF(left, 0, right - left, location_height);
+ break;
+ }
+ case ax::mojom::TextDirection::kTtb:
+ bounds = gfx::RectF(0, start_pixel_offset, location_width,
+ end_pixel_offset - start_pixel_offset);
+ break;
+ case ax::mojom::TextDirection::kBtt: {
+ const int top = max_pixel_offset - end_pixel_offset;
+ const int bottom = max_pixel_offset - start_pixel_offset;
+ bounds = gfx::RectF(0, top, location_width, bottom - top);
+ break;
+ }
+ }
+
+ return bounds;
+}
+
base::string16 BrowserAccessibility::GetValue() const {
base::string16 value =
GetString16Attribute(ax::mojom::StringAttribute::kValue);
@@ -663,7 +775,7 @@ base::string16 BrowserAccessibility::GetValue() const {
// text fields with rich content, even though the same information is
// available on the children.
if (value.empty() && IsRichTextField())
- return GetInnerText();
+ return BrowserAccessibility::GetInnerText();
return value;
}
@@ -843,10 +955,6 @@ bool BrowserAccessibility::GetHtmlAttribute(const char* html_attr,
return GetData().GetHtmlAttribute(html_attr, value);
}
-base::string16 BrowserAccessibility::GetText() const {
- return GetInnerText();
-}
-
bool BrowserAccessibility::HasState(ax::mojom::State state_enum) const {
return GetData().HasState(state_enum);
}
@@ -985,7 +1093,23 @@ BrowserAccessibility::CreatePositionForSelectionAt(int offset) const {
return position;
}
+base::string16 BrowserAccessibility::GetText() const {
+ // Default to inner text for non-native accessibility implementations.
+ return GetInnerText();
+}
+
+base::string16 BrowserAccessibility::GetHypertext() const {
+ // Overloaded by platforms which require a hypertext accessibility text
+ // implementation.
+ return base::string16();
+}
+
base::string16 BrowserAccessibility::GetInnerText() const {
+ base::string16 value =
+ GetString16Attribute(ax::mojom::StringAttribute::kValue);
+ if (!value.empty())
+ return value;
+
if (IsTextOnlyObject())
return GetString16Attribute(ax::mojom::StringAttribute::kName);
@@ -1103,6 +1227,12 @@ std::set<ui::AXPlatformNode*> BrowserAccessibility::GetReverseRelations(
manager_->ax_tree()->GetReverseRelations(attr, GetData().id));
}
+base::string16 BrowserAccessibility::GetAuthorUniqueId() const {
+ base::string16 html_id;
+ GetData().GetHtmlAttribute("id", &html_id);
+ return html_id;
+}
+
const ui::AXUniqueId& BrowserAccessibility::GetUniqueId() const {
// This is not the same as GetData().id which comes from Blink, because
// those ids are only unique within the Blink process. We need one that is
@@ -1111,52 +1241,65 @@ const ui::AXUniqueId& BrowserAccessibility::GetUniqueId() const {
}
base::Optional<int> BrowserAccessibility::FindTextBoundary(
- ui::TextBoundaryType boundary_type,
+ ui::AXTextBoundary boundary,
int offset,
ui::TextBoundaryDirection direction,
ax::mojom::TextAffinity affinity) const {
- switch (boundary_type) {
- case ui::WORD_BOUNDARY: {
+ switch (boundary) {
+ case ui::AXTextBoundary::kWordStart: {
+ BrowserAccessibilityPositionInstance position =
+ CreatePositionAt(static_cast<int>(offset), affinity);
+ switch (direction) {
+ case ui::BACKWARDS_DIRECTION:
+ return GetBoundaryTextOffsetInsideBaseAnchor(
+ direction, position,
+ position->CreatePreviousWordStartPosition(
+ ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary));
+ case ui::FORWARDS_DIRECTION:
+ return GetBoundaryTextOffsetInsideBaseAnchor(
+ direction, position,
+ position->CreateNextWordStartPosition(
+ ui::AXBoundaryBehavior::StopAtAnchorBoundary));
+ }
+ }
+ case ui::AXTextBoundary::kWordStartOrEnd: {
BrowserAccessibilityPositionInstance position =
CreatePositionAt(static_cast<int>(offset), affinity);
switch (direction) {
case ui::BACKWARDS_DIRECTION:
- return position
- ->CreatePreviousWordStartPosition(
- ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary)
- ->text_offset();
+ return GetBoundaryTextOffsetInsideBaseAnchor(
+ direction, position,
+ position->CreatePreviousWordStartPosition(
+ ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary));
case ui::FORWARDS_DIRECTION:
- return position
- ->CreateNextWordStartPosition(
- ui::AXBoundaryBehavior::StopAtAnchorBoundary)
- ->text_offset();
+ return GetBoundaryTextOffsetInsideBaseAnchor(
+ direction, position,
+ position->CreateNextWordEndPosition(
+ ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary));
}
}
- case ui::LINE_BOUNDARY: {
+ case ui::AXTextBoundary::kLineStart: {
BrowserAccessibilityPositionInstance position =
CreatePositionAt(static_cast<int>(offset), affinity);
switch (direction) {
case ui::BACKWARDS_DIRECTION:
- return position
- ->CreatePreviousLineStartPosition(
- ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary)
- ->text_offset();
+ return GetBoundaryTextOffsetInsideBaseAnchor(
+ direction, position,
+ position->CreatePreviousLineStartPosition(
+ ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary));
case ui::FORWARDS_DIRECTION:
- return position
- ->CreateNextLineStartPosition(
- ui::AXBoundaryBehavior::StopAtAnchorBoundary)
- ->text_offset();
+ return GetBoundaryTextOffsetInsideBaseAnchor(
+ direction, position,
+ position->CreateNextLineStartPosition(
+ ui::AXBoundaryBehavior::StopAtAnchorBoundary));
}
}
- case ui::CHAR_BOUNDARY:
- case ui::SENTENCE_BOUNDARY:
- case ui::PARAGRAPH_BOUNDARY:
- case ui::ALL_BOUNDARY:
+ default:
// TODO(nektar): |AXPosition| can handle other types of boundaries as
// well.
- return ui::FindAccessibleTextBoundary(GetText(), GetLineStartOffsets(),
- boundary_type, offset, direction,
- affinity);
+ return ui::FindAccessibleTextBoundary(GetHypertext(),
+ GetLineStartOffsets(), boundary,
+ offset, direction, affinity);
}
}
@@ -1220,13 +1363,13 @@ gfx::NativeViewAccessible BrowserAccessibility::GetNSWindow() {
}
gfx::NativeViewAccessible BrowserAccessibility::GetParent() {
- auto* parent = PlatformGetParent();
+ if (!instance_active())
+ return nullptr;
+
+ BrowserAccessibility* parent = PlatformGetParent();
if (parent)
return parent->GetNativeViewAccessible();
- if (!manager_)
- return nullptr;
-
BrowserAccessibilityDelegate* delegate =
manager_->GetDelegateFromRootManager();
if (!delegate)
@@ -1256,7 +1399,7 @@ gfx::NativeViewAccessible BrowserAccessibility::HitTestSync(int x, int y) {
}
gfx::NativeViewAccessible BrowserAccessibility::GetFocus() {
- auto* focused = manager()->GetFocus();
+ BrowserAccessibility* focused = manager()->GetFocus();
if (!focused)
return nullptr;
@@ -1270,7 +1413,7 @@ ui::AXPlatformNode* BrowserAccessibility::GetFromNodeID(int32_t id) {
}
int BrowserAccessibility::GetIndexInParent() const {
- return node_ ? node_->index_in_parent() : -1;
+ return node_ ? int{node_->index_in_parent()} : -1;
}
gfx::AcceleratedWidget
@@ -1413,12 +1556,11 @@ bool BrowserAccessibility::AccessibilityPerformAction(
manager_->SetFocus(*this);
return true;
case ax::mojom::Action::kScrollToPoint: {
- // target_point is in screen coordinates. We need to convert this to
- // frame coordinates because that's what BrowserAccessiblity cares about.
+ // Convert the target point from screen coordinates to frame coordinates.
gfx::Point target =
- data.target_point -
- manager_->GetRootManager()->GetViewBounds().OffsetFromOrigin();
-
+ data.target_point - manager_->GetRoot()
+ ->GetUnclippedScreenBoundsRect()
+ .OffsetFromOrigin();
manager_->ScrollToPoint(*this, target);
return true;
}
@@ -1434,6 +1576,9 @@ bool BrowserAccessibility::AccessibilityPerformAction(
case ax::mojom::Action::kSetValue:
manager_->SetValue(*this, data.value);
return true;
+ case ax::mojom::Action::kSetSequentialFocusNavigationStartingPoint:
+ manager_->SetSequentialFocusNavigationStartingPoint(*this);
+ return true;
case ax::mojom::Action::kShowContextMenu:
manager_->ShowContextMenu(*this);
return true;
@@ -1462,7 +1607,9 @@ base::string16 BrowserAccessibility::GetLocalizedStringForImageAnnotationStatus(
message_id = IDS_AX_IMAGE_ANNOTATION_NO_DESCRIPTION;
break;
case ax::mojom::ImageAnnotationStatus::kNone:
+ case ax::mojom::ImageAnnotationStatus::kWillNotAnnotateDueToScheme:
case ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation:
+ case ax::mojom::ImageAnnotationStatus::kSilentlyEligibleForAnnotation:
case ax::mojom::ImageAnnotationStatus::kAnnotationSucceeded:
return base::string16();
}
@@ -1539,4 +1686,12 @@ int32_t BrowserAccessibility::GetSetSize() const {
return node()->GetSetSize();
}
+bool BrowserAccessibility::SetHypertextSelection(int start_offset,
+ int end_offset) {
+ manager()->SetSelection(
+ AXPlatformRange(CreatePositionForSelectionAt(start_offset),
+ CreatePositionForSelectionAt(end_offset)));
+ return true;
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility.h b/chromium/content/browser/accessibility/browser_accessibility.h
index ceacbc0f4c4..574447bbe87 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.h
+++ b/chromium/content/browser/accessibility/browser_accessibility.h
@@ -26,6 +26,7 @@
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_node_position.h"
#include "ui/accessibility/ax_range.h"
+#include "ui/accessibility/ax_text_boundary.h"
#include "ui/accessibility/ax_text_utils.h"
#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
@@ -171,19 +172,25 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
gfx::Rect GetClippedFrameBoundsRect(
ui::AXOffscreenResult* offscreen_result = nullptr) const;
- // Derivative utils for AXPlatformNodeDelegate::GetRangeBoundsRect
- gfx::Rect GetUnclippedScreenRangeBoundsRect(
+ // Derivative utils for AXPlatformNodeDelegate::GetHypertextRangeBoundsRect
+ gfx::Rect GetUnclippedRootFrameHypertextRangeBoundsRect(
const int start_offset,
const int end_offset,
ui::AXOffscreenResult* offscreen_result = nullptr) const;
- gfx::Rect GetUnclippedRootFrameRangeBoundsRect(
+
+ // Derivative utils for AXPlatformNodeDelegate::GetInnerTextRangeBoundsRect
+ gfx::Rect GetUnclippedScreenInnerTextRangeBoundsRect(
+ const int start_offset,
+ const int end_offset,
+ ui::AXOffscreenResult* offscreen_result = nullptr) const;
+ gfx::Rect GetUnclippedRootFrameInnerTextRangeBoundsRect(
const int start_offset,
const int end_offset,
ui::AXOffscreenResult* offscreen_result = nullptr) const;
// DEPRECATED: Prefer using the interfaces provided by AXPlatformNodeDelegate
// when writing new code.
- gfx::Rect GetScreenRangeBoundsRect(
+ gfx::Rect GetScreenHypertextRangeBoundsRect(
int start,
int len,
const ui::AXClippingBehavior clipping_behavior,
@@ -194,7 +201,7 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
// WebAXRoleStaticText.
// DEPRECATED (for public use): Prefer using the interfaces provided by
// AXPlatformNodeDelegate when writing new non-private code.
- gfx::Rect GetRootFrameRangeBoundsRect(
+ gfx::Rect GetRootFrameHypertextRangeBoundsRect(
int start,
int len,
const ui::AXClippingBehavior clipping_behavior,
@@ -313,8 +320,6 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
bool GetHtmlAttribute(const char* attr, std::string* value) const;
bool GetHtmlAttribute(const char* attr, base::string16* value) const;
- virtual base::string16 GetText() const;
-
// Returns true if the bit corresponding to the given enum is 1.
bool HasState(ax::mojom::State state_enum) const;
bool HasAction(ax::mojom::Action action_enum) const;
@@ -357,7 +362,17 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
virtual gfx::NativeViewAccessible GetNativeViewAccessible();
+ // AXPosition Support
+
+ // Returns the text that is present inside this node, where the representation
+ // of text found in descendant nodes depends on the platform. For example some
+ // platforms may include descendant text while while other platforms may use a
+ // special character to represent descendant text. Prefer either GetHypertext
+ // or GetInnerText so it's clear which API is called.
+ virtual base::string16 GetText() const;
+
// AXPlatformNodeDelegate.
+ base::string16 GetAuthorUniqueId() const override;
const ui::AXNodeData& GetData() const override;
const ui::AXTreeData& GetTreeData() const override;
ui::AXNodePosition::AXPositionInstance CreateTextPositionAt(
@@ -368,11 +383,20 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
gfx::NativeViewAccessible GetParent() override;
int GetChildCount() override;
gfx::NativeViewAccessible ChildAtIndex(int index) override;
+ base::string16 GetHypertext() const override;
+ bool SetHypertextSelection(int start_offset, int end_offset) override;
+ base::string16 GetInnerText() const override;
gfx::Rect GetBoundsRect(
const ui::AXCoordinateSystem coordinate_system,
const ui::AXClippingBehavior clipping_behavior,
ui::AXOffscreenResult* offscreen_result = nullptr) const override;
- gfx::Rect GetRangeBoundsRect(
+ gfx::Rect GetHypertextRangeBoundsRect(
+ const int start_offset,
+ const int end_offset,
+ const ui::AXCoordinateSystem coordinate_system,
+ const ui::AXClippingBehavior clipping_behavior,
+ ui::AXOffscreenResult* offscreen_result = nullptr) const override;
+ gfx::Rect GetInnerTextRangeBoundsRect(
const int start_offset,
const int end_offset,
const ui::AXCoordinateSystem coordinate_system,
@@ -385,7 +409,7 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
base::Optional<int> FindTextBoundary(
- ui::TextBoundaryType boundary_type,
+ ui::AXTextBoundary boundary,
int offset,
ui::TextBoundaryDirection direction,
ax::mojom::TextAffinity affinity) const override;
@@ -466,12 +490,6 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
const ui::AXUniqueId& GetUniqueId() const override;
private:
- // |GetInnerText| recursively includes all the text from descendants such as
- // text found in any embedded object. In contrast, |GetText| might include a
- // special character in the place of every embedded object instead of its
- // text, depending on the platform.
- base::string16 GetInnerText() const;
-
// Return the bounds after converting from this node's coordinate system
// (which is relative to its nearest scrollable ancestor) to the coordinate
// system specified. If the clipping behavior is set to clipped, clipping is
@@ -490,10 +508,24 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
// ATs expect when getting the character extents past the last character in a
// line, and equals what the caret bounds would be when past the end of the
// text.
- gfx::Rect GetRootFrameBoundsPastEndOfText(
+ gfx::Rect GetRootFrameHypertextBoundsPastEndOfText(
const ui::AXClippingBehavior clipping_behavior,
ui::AXOffscreenResult* offscreen_result = nullptr) const;
+ // Return the bounds of inline text in this node's coordinate system (which is
+ // relative to its container node specified in AXRelativeBounds).
+ gfx::RectF GetInlineTextRect(const int start_offset,
+ const int end_offset,
+ const int max_length) const;
+
+ // Recursive helper function for GetInnerTextRangeBounds.
+ gfx::Rect GetInnerTextRangeBoundsRectInSubtree(
+ const int start_offset,
+ const int end_offset,
+ const ui::AXCoordinateSystem coordinate_system,
+ const ui::AXClippingBehavior clipping_behavior,
+ ui::AXOffscreenResult* offscreen_result) const;
+
// Given a set of node ids, return the nodes in this delegate's tree to
// which they correspond.
std::set<ui::AXPlatformNode*> GetNodesForNodeIdSet(
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.cc b/chromium/content/browser/accessibility/browser_accessibility_android.cc
index 1e076ad33da..be8019d352b 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.cc
@@ -192,7 +192,7 @@ bool BrowserAccessibilityAndroid::PlatformIsLeaf() const {
static_cast<BrowserAccessibilityManagerAndroid*>(manager());
if (manager_android->prune_tree_for_screen_reader()) {
// Headings with text can drop their children.
- base::string16 name = GetText();
+ base::string16 name = GetInnerText();
if (GetRole() == ax::mojom::Role::kHeading && !name.empty())
return true;
@@ -367,7 +367,7 @@ bool BrowserAccessibilityAndroid::IsVisibleToUser() const {
bool BrowserAccessibilityAndroid::IsInterestingOnAndroid() const {
// The root is not interesting if it doesn't have a title, even
// though it's focusable.
- if (GetRole() == ax::mojom::Role::kRootWebArea && GetText().empty())
+ if (GetRole() == ax::mojom::Role::kRootWebArea && GetInnerText().empty())
return false;
// Mark as uninteresting if it's hidden, even if it is focusable.
@@ -394,7 +394,7 @@ bool BrowserAccessibilityAndroid::IsInterestingOnAndroid() const {
// Otherwise, the interesting nodes are leaf nodes with non-whitespace text.
return PlatformIsLeaf() &&
- !base::ContainsOnlyChars(GetText(), base::kWhitespaceUTF16);
+ !base::ContainsOnlyChars(GetInnerText(), base::kWhitespaceUTF16);
}
const BrowserAccessibilityAndroid*
@@ -450,7 +450,7 @@ const char* BrowserAccessibilityAndroid::GetClassName() const {
return ui::AXRoleToAndroidClassName(role, PlatformGetParent() != nullptr);
}
-base::string16 BrowserAccessibilityAndroid::GetText() const {
+base::string16 BrowserAccessibilityAndroid::GetInnerText() const {
if (IsIframe() || GetRole() == ax::mojom::Role::kWebArea) {
return base::string16();
}
@@ -490,7 +490,7 @@ base::string16 BrowserAccessibilityAndroid::GetText() const {
(IsFocusable() && HasOnlyTextAndImageChildren()))) {
for (uint32_t i = 0; i < InternalChildCount(); i++) {
BrowserAccessibility* child = InternalGetChild(i);
- text += static_cast<BrowserAccessibilityAndroid*>(child)->GetText();
+ text += static_cast<BrowserAccessibilityAndroid*>(child)->GetInnerText();
}
}
@@ -1511,9 +1511,9 @@ void BrowserAccessibilityAndroid::GetLineBoundaries(
std::vector<int32_t>* line_ends,
int offset) {
// If this node has no children, treat it as all one line.
- if (GetText().size() > 0 && !InternalChildCount()) {
+ if (GetInnerText().size() > 0 && !InternalChildCount()) {
line_starts->push_back(offset);
- line_ends->push_back(offset + GetText().size());
+ line_ends->push_back(offset + GetInnerText().size());
}
// If this is a static text node, get the line boundaries from the
@@ -1533,7 +1533,7 @@ void BrowserAccessibilityAndroid::GetLineBoundaries(
line_ends->push_back(offset);
line_starts->push_back(offset);
}
- offset += child->GetText().size();
+ offset += child->GetInnerText().size();
last_y = y;
}
line_ends->push_back(offset);
@@ -1545,7 +1545,7 @@ void BrowserAccessibilityAndroid::GetLineBoundaries(
BrowserAccessibilityAndroid* child =
static_cast<BrowserAccessibilityAndroid*>(InternalGetChild(i));
child->GetLineBoundaries(line_starts, line_ends, offset);
- offset += child->GetText().size();
+ offset += child->GetInnerText().size();
}
}
@@ -1569,11 +1569,11 @@ void BrowserAccessibilityAndroid::GetWordBoundaries(
for (uint32_t i = 0; i < InternalChildCount(); i++) {
BrowserAccessibilityAndroid* child =
static_cast<BrowserAccessibilityAndroid*>(InternalGetChild(i));
- base::string16 child_text = child->GetText();
- concatenated_text += child->GetText();
+ base::string16 child_text = child->GetInnerText();
+ concatenated_text += child->GetInnerText();
}
- base::string16 text = GetText();
+ base::string16 text = GetInnerText();
if (text.empty() || concatenated_text == text) {
// Great - this node is just the concatenation of its children, so
// we can get the word boundaries recursively.
@@ -1581,7 +1581,7 @@ void BrowserAccessibilityAndroid::GetWordBoundaries(
BrowserAccessibilityAndroid* child =
static_cast<BrowserAccessibilityAndroid*>(InternalGetChild(i));
child->GetWordBoundaries(word_starts, word_ends, offset);
- offset += child->GetText().size();
+ offset += child->GetInnerText().size();
}
} else {
// This node has its own accessible text that doesn't match its
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.h b/chromium/content/browser/accessibility/browser_accessibility_android.h
index a8ea72aeda1..cdd15c646ca 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.h
@@ -80,7 +80,7 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
bool HasImage() const;
const char* GetClassName() const;
- base::string16 GetText() const override;
+ base::string16 GetInnerText() const override;
base::string16 GetHint() const;
std::string GetRoleString() const;
@@ -139,13 +139,13 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
int offset);
// Append line start and end indices for the text of this node
- // (as returned by GetText()), adding |offset| to each one.
+ // (as returned by GetInnerText()), adding |offset| to each one.
void GetLineBoundaries(std::vector<int32_t>* line_starts,
std::vector<int32_t>* line_ends,
int offset);
// Append word start and end indices for the text of this node
- // (as returned by GetText()) to |word_starts| and |word_ends|,
+ // (as returned by GetInnerText()) to |word_starts| and |word_ends|,
// adding |offset| to each one.
void GetWordBoundaries(std::vector<int32_t>* word_starts,
std::vector<int32_t>* word_ends,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc b/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
index ad27587491c..0738544854e 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
@@ -40,6 +40,10 @@ BrowserAccessibilityAuraLinux::GetNativeViewAccessible() {
return node_->GetNativeViewAccessible();
}
+void BrowserAccessibilityAuraLinux::UpdatePlatformAttributes() {
+ GetNode()->UpdateHypertext();
+}
+
void BrowserAccessibilityAuraLinux::OnDataChanged() {
BrowserAccessibility::OnDataChanged();
@@ -47,16 +51,16 @@ void BrowserAccessibilityAuraLinux::OnDataChanged() {
node_->DataChanged();
}
-void BrowserAccessibilityAuraLinux::UpdatePlatformAttributes() {
- GetNode()->UpdateHypertext();
-}
-
bool BrowserAccessibilityAuraLinux::IsNative() const {
return true;
}
base::string16 BrowserAccessibilityAuraLinux::GetText() const {
- return GetNode()->AXPlatformNodeAuraLinux::GetText();
+ return GetHypertext();
+}
+
+base::string16 BrowserAccessibilityAuraLinux::GetHypertext() const {
+ return GetNode()->AXPlatformNodeAuraLinux::GetHypertext();
}
ui::AXPlatformNode* BrowserAccessibilityAuraLinux::GetFromNodeID(int32_t id) {
diff --git a/chromium/content/browser/accessibility/browser_accessibility_auralinux.h b/chromium/content/browser/accessibility/browser_accessibility_auralinux.h
index b644c7f2bab..182dc13c45a 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_auralinux.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_auralinux.h
@@ -32,6 +32,7 @@ class BrowserAccessibilityAuraLinux : public BrowserAccessibility {
void OnDataChanged() override;
bool IsNative() const override;
base::string16 GetText() const override;
+ base::string16 GetHypertext() const override;
gfx::NativeViewAccessible GetNativeViewAccessible() override;
ui::AXPlatformNode* GetFromNodeID(int32_t id) override;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
index d38fa48b8b8..743d1364bcd 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -33,7 +33,7 @@ struct AXTextEdit {
// object. The renderer converts webkit's accessibility tree into a
// WebAccessibility tree and passes it to the browser process over IPC.
// This class converts it into a format Cocoa can query.
-@interface BrowserAccessibilityCocoa : NSObject {
+@interface BrowserAccessibilityCocoa : NSAccessibilityElement {
@private
content::BrowserAccessibility* owner_;
base::scoped_nsobject<NSMutableArray> children_;
@@ -98,7 +98,7 @@ struct AXTextEdit {
@property(nonatomic, readonly) NSArray* columns;
@property(nonatomic, readonly) NSArray* columnHeaders;
@property(nonatomic, readonly) NSValue* columnIndexRange;
-@property(nonatomic, readonly) NSString* description;
+@property(nonatomic, readonly) NSString* descriptionForAccessibility;
@property(nonatomic, readonly) NSNumber* disclosing;
@property(nonatomic, readonly) id disclosedByRow;
@property(nonatomic, readonly) NSNumber* disclosureLevel;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
index 57595784222..444bb384d84 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -322,8 +322,9 @@ NSAttributedString* GetAttributedTextForTextMarkerRange(
int trim_length = 0;
if ((end_object->IsPlainTextField() || end_object->IsTextOnlyObject()) &&
- end_offset < static_cast<int>(end_object->GetText().length())) {
- trim_length = static_cast<int>(end_object->GetText().length()) - end_offset;
+ end_offset < static_cast<int>(end_object->GetInnerText().length())) {
+ trim_length =
+ static_cast<int>(end_object->GetInnerText().length()) - end_offset;
}
int range_length = [text length] - start_offset - trim_length;
@@ -601,7 +602,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
{NSAccessibilityColumnHeaderUIElementsAttribute, @"columnHeaders"},
{NSAccessibilityColumnIndexRangeAttribute, @"columnIndexRange"},
{NSAccessibilityContentsAttribute, @"contents"},
- {NSAccessibilityDescriptionAttribute, @"description"},
+ {NSAccessibilityDescriptionAttribute, @"descriptionForAccessibility"},
{NSAccessibilityDisclosingAttribute, @"disclosing"},
{NSAccessibilityDisclosedByRowAttribute, @"disclosedByRow"},
{NSAccessibilityDisclosureLevelAttribute, @"disclosureLevel"},
@@ -936,7 +937,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return table;
}
-- (NSString*)description {
+- (NSString*)descriptionForAccessibility {
if (![self instanceActive])
return nil;
@@ -974,7 +975,9 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
break;
case ax::mojom::ImageAnnotationStatus::kNone:
+ case ax::mojom::ImageAnnotationStatus::kWillNotAnnotateDueToScheme:
case ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation:
+ case ax::mojom::ImageAnnotationStatus::kSilentlyEligibleForAnnotation:
break;
}
@@ -1574,7 +1577,9 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return true;
case ax::mojom::ImageAnnotationStatus::kNone:
+ case ax::mojom::ImageAnnotationStatus::kWillNotAnnotateDueToScheme:
case ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation:
+ case ax::mojom::ImageAnnotationStatus::kSilentlyEligibleForAnnotation:
break;
}
@@ -1723,7 +1728,9 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
if (owner_->GetData().GetImageAnnotationStatus() ==
- ax::mojom::ImageAnnotationStatus::kEligibleForAnnotation) {
+ ax::mojom::ImageAnnotationStatus::kEligibleForAnnotation ||
+ owner_->GetData().GetImageAnnotationStatus() ==
+ ax::mojom::ImageAnnotationStatus::kSilentlyEligibleForAnnotation) {
return base::SysUTF16ToNSString(
owner_->GetLocalizedRoleDescriptionForUnlabeledImage());
}
@@ -1909,8 +1916,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
- if ([self internalRole] == ax::mojom::Role::kTable ||
- [self internalRole] == ax::mojom::Role::kGrid) {
+ if (ui::IsTableLike(owner_->GetRole())) {
for (BrowserAccessibilityCocoa* child in [self children]) {
if ([[child role] isEqualToString:NSAccessibilityRowRole])
[ret addObject:child];
@@ -1942,7 +1948,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
BrowserAccessibilityManager* manager = owner_->manager();
BrowserAccessibility* focusedChild = manager->GetFocus();
- if (!focusedChild->IsDescendantOf(owner_))
+ if (focusedChild && !focusedChild->IsDescendantOf(owner_))
focusedChild = nullptr;
// If it's not multiselectable, try to skip iterating over the
@@ -2393,7 +2399,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
base::string16 text = owner_->GetValue();
if (owner_->IsTextOnlyObject() && text.empty())
- text = owner_->GetText();
+ text = owner_->GetInnerText();
// We need to get the whole text because a spelling mistake might start or end
// outside our range.
@@ -2470,10 +2476,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if ([attribute
isEqualToString:
NSAccessibilityCellForColumnAndRowParameterizedAttribute]) {
- if ([self internalRole] != ax::mojom::Role::kTable &&
- [self internalRole] != ax::mojom::Role::kGrid) {
+ if (!ui::IsTableLike([self internalRole]))
return nil;
- }
if (![parameter isKindOfClass:[NSArray class]])
return nil;
if (2 != [parameter count])
@@ -2674,8 +2678,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if ([self internalRole] != ax::mojom::Role::kStaticText)
return nil;
NSRange range = [(NSValue*)parameter rangeValue];
- gfx::Rect rect =
- owner_->GetUnclippedScreenRangeBoundsRect(range.location, range.length);
+ gfx::Rect rect = owner_->GetUnclippedScreenInnerTextRangeBoundsRect(
+ range.location, range.location + range.length);
NSRect nsrect = [self rectInScreen:rect];
return [NSValue valueWithRect:nsrect];
}
@@ -2734,8 +2738,9 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
DCHECK_GE(startOffset, 0);
DCHECK_GE(endOffset, 0);
- gfx::Rect rect = BrowserAccessibilityManager::GetRootFrameRangeBoundsRect(
- *startObject, startOffset, *endObject, endOffset);
+ gfx::Rect rect =
+ BrowserAccessibilityManager::GetRootFrameInnerTextRangeBoundsRect(
+ *startObject, startOffset, *endObject, endOffset);
NSRect nsrect = [self rectInScreen:rect];
return [NSValue valueWithRect:nsrect];
}
@@ -2891,49 +2896,6 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return actions;
}
-// TODO(crbug.com/921109): Migrate from the NSObject accessibility interface to
-// the NSAccessibility one, then remove this suppression.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-
-// Returns a sub-array of values for the given attribute value, starting at
-// index, with up to maxCount items. If the given index is out of bounds,
-// or there are no values for the given attribute, it will return nil.
-// This method is used for querying subsets of values, without having to
-// return a large set of data, such as elements with a large number of
-// children.
-- (NSArray*)accessibilityArrayAttributeValues:(NSString*)attribute
- index:(NSUInteger)index
- maxCount:(NSUInteger)maxCount {
- if (![self instanceActive])
- return nil;
-
- NSArray* fullArray = [self accessibilityAttributeValue:attribute];
- if (!fullArray)
- return nil;
- NSUInteger arrayCount = [fullArray count];
- if (index >= arrayCount)
- return nil;
- NSRange subRange;
- if ((index + maxCount) > arrayCount) {
- subRange = NSMakeRange(index, arrayCount - index);
- } else {
- subRange = NSMakeRange(index, maxCount);
- }
- return [fullArray subarrayWithRange:subRange];
-}
-
-// Returns the count of the specified accessibility array attribute.
-- (NSUInteger)accessibilityArrayAttributeCount:(NSString*)attribute {
- if (![self instanceActive])
- return 0;
-
- NSArray* fullArray = [self accessibilityAttributeValue:attribute];
- return [fullArray count];
-}
-
-#pragma clang diagnostic pop
-
// Returns the list of accessibility attributes that this object supports.
- (NSArray*)accessibilityAttributeNames {
if (![self instanceActive])
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm
index c90657b61f9..f4bf30e3390 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm
@@ -21,11 +21,6 @@
#include "testing/gtest_mac.h"
#include "url/gurl.h"
-// This file uses the deprecated NSObject accessibility APIs:
-// https://crbug.com/921109
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-
namespace content {
namespace {
@@ -103,44 +98,54 @@ IN_PROC_BROWSER_TEST_F(BrowserAccessibilityCocoaBrowserTest,
// Test AXCellForColumnAndRow for four coordinates
for (unsigned col = 0; col < 2; col++) {
for (unsigned row = 0; row < 2; row++) {
- id parameter = [[[NSMutableArray alloc] initWithCapacity:2] autorelease];
- [parameter addObject:[NSNumber numberWithInt:col]];
- [parameter addObject:[NSNumber numberWithInt:row]];
base::scoped_nsobject<BrowserAccessibilityCocoa> cell(
- [[cocoa_table accessibilityAttributeValue:@"AXCellForColumnAndRow"
- forParameter:parameter] retain]);
+ [[cocoa_table accessibilityCellForColumn:col row:row] retain]);
// It should be a cell.
- EXPECT_NSEQ(@"AXCell", [cell role]);
+ EXPECT_NSEQ(@"AXCell", [cell accessibilityRole]);
// The column index and row index of the cell should match what we asked
// for.
- EXPECT_EQ(col, [[cell accessibilityAttributeValue:@"AXColumnIndexRange"]
- rangeValue]
- .location);
- EXPECT_EQ(row, [[cell accessibilityAttributeValue:@"AXRowIndexRange"]
- rangeValue]
- .location);
+ EXPECT_NSEQ(NSMakeRange(col, 1), [cell accessibilityColumnIndexRange]);
+ EXPECT_NSEQ(NSMakeRange(row, 1), [cell accessibilityRowIndexRange]);
}
}
}
IN_PROC_BROWSER_TEST_F(BrowserAccessibilityCocoaBrowserTest,
TestUnlabeledImageRoleDescription) {
- ui::AXNodeData image;
- image.id = 1;
- image.role = ax::mojom::Role::kImage;
- image.AddStringAttribute(ax::mojom::StringAttribute::kRoleDescription, "bar");
- image.SetImageAnnotationStatus(
+ ui::AXTreeUpdate tree;
+ tree.root_id = 1;
+ tree.nodes.resize(3);
+ tree.nodes[0].id = 1;
+ tree.nodes[0].child_ids = {2, 3};
+
+ tree.nodes[1].id = 2;
+ tree.nodes[1].role = ax::mojom::Role::kImage;
+ tree.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kRoleDescription,
+ "foo");
+ tree.nodes[1].SetImageAnnotationStatus(
ax::mojom::ImageAnnotationStatus::kEligibleForAnnotation);
+ tree.nodes[2].id = 3;
+ tree.nodes[2].role = ax::mojom::Role::kImage;
+ tree.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kRoleDescription,
+ "bar");
+ tree.nodes[2].SetImageAnnotationStatus(
+ ax::mojom::ImageAnnotationStatus::kSilentlyEligibleForAnnotation);
+
std::unique_ptr<BrowserAccessibilityManagerMac> manager(
- new BrowserAccessibilityManagerMac(MakeAXTreeUpdate(image), nullptr));
+ new BrowserAccessibilityManagerMac(tree, nullptr));
- base::scoped_nsobject<BrowserAccessibilityCocoa> ax_node(
- [ToBrowserAccessibilityCocoa(manager->GetRoot()) retain]);
+ for (int child_index = 0; child_index < int{tree.nodes[0].child_ids.size()};
+ ++child_index) {
+ BrowserAccessibility* child =
+ manager->GetRoot()->PlatformGetChild(child_index);
+ base::scoped_nsobject<BrowserAccessibilityCocoa> child_obj(
+ [ToBrowserAccessibilityCocoa(child) retain]);
- EXPECT_NSEQ(@"Unlabeled image", [ax_node roleDescription]);
+ EXPECT_NSEQ(@"Unlabeled image", [child_obj roleDescription]);
+ }
}
IN_PROC_BROWSER_TEST_F(BrowserAccessibilityCocoaBrowserTest,
@@ -149,9 +154,9 @@ IN_PROC_BROWSER_TEST_F(BrowserAccessibilityCocoaBrowserTest,
ui::AXTreeUpdate tree;
tree.root_id = 1;
- tree.nodes.resize(10);
+ tree.nodes.resize(11);
tree.nodes[0].id = 1;
- tree.nodes[0].child_ids = {2, 3, 4, 5, 6, 7, 8, 9, 10};
+ tree.nodes[0].child_ids = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
// If the status is EligibleForAnnotation and there's no existing label,
// the description should be the discoverability string.
@@ -177,71 +182,70 @@ IN_PROC_BROWSER_TEST_F(BrowserAccessibilityCocoaBrowserTest,
"ExistingLabel. To get missing image descriptions, open the context "
"menu.");
- // If the status is IneligibleForAnnotation, nothing should be appended.
+ // If the status is SilentlyEligibleForAnnotation, the discoverability string
+ // should not be appended to the existing name.
tree.nodes[3].id = 4;
tree.nodes[3].role = ax::mojom::Role::kImage;
tree.nodes[3].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
"Annotation");
tree.nodes[3].SetName("ExistingLabel");
tree.nodes[3].SetImageAnnotationStatus(
- ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation);
+ ax::mojom::ImageAnnotationStatus::kSilentlyEligibleForAnnotation);
expected_descriptions.push_back("ExistingLabel");
- // If the status is AnnotationPending, pending text should be appended
- // to the name.
+ // If the status is IneligibleForAnnotation, nothing should be appended.
tree.nodes[4].id = 5;
tree.nodes[4].role = ax::mojom::Role::kImage;
tree.nodes[4].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
"Annotation");
tree.nodes[4].SetName("ExistingLabel");
tree.nodes[4].SetImageAnnotationStatus(
- ax::mojom::ImageAnnotationStatus::kAnnotationPending);
- expected_descriptions.push_back("ExistingLabel. Getting description…");
+ ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation);
+ expected_descriptions.push_back("ExistingLabel");
- // If the status is AnnotationSucceeded, and there's no annotation,
- // nothing should be appended. (Ideally this shouldn't happen.)
+ // If the status is AnnotationPending, pending text should be appended
+ // to the name.
tree.nodes[5].id = 6;
tree.nodes[5].role = ax::mojom::Role::kImage;
+ tree.nodes[5].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
+ "Annotation");
tree.nodes[5].SetName("ExistingLabel");
tree.nodes[5].SetImageAnnotationStatus(
- ax::mojom::ImageAnnotationStatus::kAnnotationSucceeded);
- expected_descriptions.push_back("ExistingLabel");
+ ax::mojom::ImageAnnotationStatus::kAnnotationPending);
+ expected_descriptions.push_back("ExistingLabel. Getting description…");
- // If the status is AnnotationSucceeded, the annotation should be appended
- // to the existing label.
+ // If the status is AnnotationSucceeded, and there's no annotation,
+ // nothing should be appended. (Ideally this shouldn't happen.)
tree.nodes[6].id = 7;
tree.nodes[6].role = ax::mojom::Role::kImage;
- tree.nodes[6].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
- "Annotation");
tree.nodes[6].SetName("ExistingLabel");
tree.nodes[6].SetImageAnnotationStatus(
ax::mojom::ImageAnnotationStatus::kAnnotationSucceeded);
- expected_descriptions.push_back("ExistingLabel. Annotation");
+ expected_descriptions.push_back("ExistingLabel");
- // If the status is AnnotationEmpty, failure text should be added to the
- // name.
+ // If the status is AnnotationSucceeded, the annotation should be appended
+ // to the existing label.
tree.nodes[7].id = 8;
tree.nodes[7].role = ax::mojom::Role::kImage;
tree.nodes[7].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
"Annotation");
tree.nodes[7].SetName("ExistingLabel");
tree.nodes[7].SetImageAnnotationStatus(
- ax::mojom::ImageAnnotationStatus::kAnnotationEmpty);
- expected_descriptions.push_back("ExistingLabel. No description available.");
+ ax::mojom::ImageAnnotationStatus::kAnnotationSucceeded);
+ expected_descriptions.push_back("ExistingLabel. Annotation");
- // If the status is AnnotationAdult, appropriate text should be appended
- // to the name.
+ // If the status is AnnotationEmpty, failure text should be added to the
+ // name.
tree.nodes[8].id = 9;
tree.nodes[8].role = ax::mojom::Role::kImage;
tree.nodes[8].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
"Annotation");
tree.nodes[8].SetName("ExistingLabel");
tree.nodes[8].SetImageAnnotationStatus(
- ax::mojom::ImageAnnotationStatus::kAnnotationAdult);
- expected_descriptions.push_back("ExistingLabel. Appears to contain adult "
- "content. No description available.");
+ ax::mojom::ImageAnnotationStatus::kAnnotationEmpty);
+ expected_descriptions.push_back("ExistingLabel. No description available.");
- // If the status is AnnotationProcessFailed, failure text should be added
+ // If the status is AnnotationAdult, appropriate text should be appended
// to the name.
tree.nodes[9].id = 10;
tree.nodes[9].role = ax::mojom::Role::kImage;
@@ -249,6 +253,18 @@ IN_PROC_BROWSER_TEST_F(BrowserAccessibilityCocoaBrowserTest,
"Annotation");
tree.nodes[9].SetName("ExistingLabel");
tree.nodes[9].SetImageAnnotationStatus(
+ ax::mojom::ImageAnnotationStatus::kAnnotationAdult);
+ expected_descriptions.push_back("ExistingLabel. Appears to contain adult "
+ "content. No description available.");
+
+ // If the status is AnnotationProcessFailed, failure text should be added
+ // to the name.
+ tree.nodes[10].id = 11;
+ tree.nodes[10].role = ax::mojom::Role::kImage;
+ tree.nodes[10].AddStringAttribute(
+ ax::mojom::StringAttribute::kImageAnnotation, "Annotation");
+ tree.nodes[10].SetName("ExistingLabel");
+ tree.nodes[10].SetImageAnnotationStatus(
ax::mojom::ImageAnnotationStatus::kAnnotationProcessFailed);
expected_descriptions.push_back("ExistingLabel. No description available.");
@@ -266,10 +282,8 @@ IN_PROC_BROWSER_TEST_F(BrowserAccessibilityCocoaBrowserTest,
[ToBrowserAccessibilityCocoa(child) retain]);
EXPECT_NSEQ(base::SysUTF8ToNSString(expected_descriptions[child_index]),
- [child_obj description]);
+ [child_obj descriptionForAccessibility]);
}
}
} // namespace content
-
-#pragma clang diagnostic pop
diff --git a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
index 6a70ee34978..ad93db51aa4 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -242,17 +242,17 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_characterExtents(
if (!out_x || !out_y || !out_width || !out_height)
return E_INVALIDARG;
- const base::string16& text_str = GetText();
+ const base::string16& text_str = GetHypertext();
HandleSpecialTextOffset(&offset);
if (offset < 0 || offset > static_cast<LONG>(text_str.size()))
return E_INVALIDARG;
gfx::Rect character_bounds;
if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) {
- character_bounds = owner()->GetScreenRangeBoundsRect(
+ character_bounds = owner()->GetScreenHypertextRangeBoundsRect(
offset, 1, ui::AXClippingBehavior::kUnclipped);
} else if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) {
- character_bounds = owner()->GetRootFrameRangeBoundsRect(
+ character_bounds = owner()->GetRootFrameHypertextRangeBoundsRect(
offset, 1, ui::AXClippingBehavior::kUnclipped);
if (owner()->PlatformGetParent()) {
character_bounds -= owner()
@@ -294,7 +294,7 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_text(LONG start_offset,
if (!text)
return E_INVALIDARG;
- const base::string16& text_str = GetText();
+ const base::string16& text_str = GetHypertext();
HandleSpecialTextOffset(&start_offset);
HandleSpecialTextOffset(&end_offset);
@@ -341,7 +341,7 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_textAtOffset(
if (offset < 0)
return E_INVALIDARG;
- const base::string16& text_str = GetText();
+ const base::string16& text_str = GetHypertext();
LONG text_len = text_str.length();
if (offset > text_len)
return E_INVALIDARG;
@@ -385,7 +385,7 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_textBeforeOffset(
*end_offset = 0;
*text = NULL;
- const base::string16& text_str = GetText();
+ const base::string16& text_str = GetHypertext();
LONG text_len = text_str.length();
if (offset > text_len)
return E_INVALIDARG;
@@ -420,7 +420,7 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_textAfterOffset(
*end_offset = 0;
*text = NULL;
- const base::string16& text_str = GetText();
+ const base::string16& text_str = GetHypertext();
LONG text_len = text_str.length();
if (offset > text_len)
return E_INVALIDARG;
@@ -453,7 +453,7 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_newText(
if (new_len == 0)
return E_FAIL;
- base::string16 substr = GetText().substr(start, new_len);
+ base::string16 substr = GetHypertext().substr(start, new_len);
new_text->text = SysAllocString(substr.c_str());
new_text->start = static_cast<LONG>(start);
new_text->end = static_cast<LONG>(start + new_len);
@@ -535,7 +535,7 @@ IFACEMETHODIMP BrowserAccessibilityComWin::scrollSubstringToPoint(
LONG length = end_index - start_index + 1;
DCHECK_GE(length, 0);
- gfx::Rect string_bounds = owner()->GetRootFrameRangeBoundsRect(
+ gfx::Rect string_bounds = owner()->GetRootFrameHypertextRangeBoundsRect(
start_index, length, ui::AXClippingBehavior::kUnclipped);
string_bounds -=
owner()->GetUnclippedRootFrameBoundsRect().OffsetFromOrigin();
@@ -594,7 +594,7 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_attributes(
if (!owner())
return E_FAIL;
- const base::string16 text = GetText();
+ const base::string16 text = GetHypertext();
HandleSpecialTextOffset(&offset);
if (offset < 0 || offset > static_cast<LONG>(text.size()))
return E_INVALIDARG;
@@ -670,7 +670,8 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_hyperlinkIndex(
if (!hyperlink_index)
return E_INVALIDARG;
- if (char_index < 0 || char_index >= static_cast<LONG>(GetText().size())) {
+ if (char_index < 0 ||
+ char_index >= static_cast<LONG>(GetHypertext().size())) {
return E_INVALIDARG;
}
@@ -701,7 +702,7 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_anchor(LONG index,
if (index != 0 || !anchor)
return E_INVALIDARG;
- BSTR ia2_hypertext = SysAllocString(GetText().c_str());
+ BSTR ia2_hypertext = SysAllocString(GetHypertext().c_str());
DCHECK(ia2_hypertext);
anchor->vt = VT_BSTR;
anchor->bstrVal = ia2_hypertext;
@@ -1473,13 +1474,13 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_unclippedSubstringBounds(
if (!out_x || !out_y || !out_width || !out_height)
return E_INVALIDARG;
- unsigned int text_length = static_cast<unsigned int>(GetText().size());
+ unsigned int text_length = static_cast<unsigned int>(GetHypertext().size());
if (start_index > text_length || end_index > text_length ||
start_index > end_index) {
return E_INVALIDARG;
}
- gfx::Rect bounds = owner()->GetScreenRangeBoundsRect(
+ gfx::Rect bounds = owner()->GetScreenHypertextRangeBoundsRect(
start_index, end_index - start_index, ui::AXClippingBehavior::kUnclipped);
*out_x = bounds.x();
*out_y = bounds.y();
@@ -1501,16 +1502,16 @@ IFACEMETHODIMP BrowserAccessibilityComWin::scrollToSubstring(
if (!manager)
return E_FAIL;
- unsigned int text_length = static_cast<unsigned int>(GetText().size());
+ unsigned int text_length = static_cast<unsigned int>(GetHypertext().size());
if (start_index > text_length || end_index > text_length ||
start_index > end_index) {
return E_INVALIDARG;
}
- manager->ScrollToMakeVisible(
- *owner(),
- owner()->GetRootFrameRangeBoundsRect(start_index, end_index - start_index,
- ui::AXClippingBehavior::kUnclipped));
+ manager->ScrollToMakeVisible(*owner(),
+ owner()->GetRootFrameHypertextRangeBoundsRect(
+ start_index, end_index - start_index,
+ ui::AXClippingBehavior::kUnclipped));
return S_OK;
}
@@ -1629,8 +1630,8 @@ STDMETHODIMP BrowserAccessibilityComWin::InternalQueryInterface(
}
}
- return CComObjectRootBase::InternalQueryInterface(this_ptr, entries, iid,
- object);
+ return AXPlatformNodeWin::InternalQueryInterface(this_ptr, entries, iid,
+ object);
}
void BrowserAccessibilityComWin::ComputeStylesIfNeeded() {
@@ -1675,7 +1676,7 @@ void BrowserAccessibilityComWin::ComputeStylesIfNeeded() {
child->GetSpellingAttributes();
MergeSpellingIntoTextAttributes(spelling_attributes, start_offset,
&attributes_map);
- start_offset += child->GetText().length();
+ start_offset += child->GetHypertext().length();
} else {
start_offset += 1;
}
@@ -2028,7 +2029,7 @@ BrowserAccessibilityComWin::GetSpellingAttributes() {
spelling_attributes[start_offset + attribute.first] =
std::move(attribute.second);
}
- start_offset += static_cast<int>(text_win->GetText().length());
+ start_offset += static_cast<int>(text_win->GetHypertext().length());
}
}
}
@@ -2140,12 +2141,7 @@ void BrowserAccessibilityComWin::SetIA2HypertextSelection(LONG start_offset,
LONG end_offset) {
HandleSpecialTextOffset(&start_offset);
HandleSpecialTextOffset(&end_offset);
- BrowserAccessibilityPositionInstance start_position =
- owner()->CreatePositionForSelectionAt(static_cast<int>(start_offset));
- BrowserAccessibilityPositionInstance end_position =
- owner()->CreatePositionForSelectionAt(static_cast<int>(end_offset));
- Manager()->SetSelection(
- AXPlatformRange(std::move(start_position), std::move(end_position)));
+ SetHypertextSelection(start_offset, end_offset);
}
LONG BrowserAccessibilityComWin::FindIA2Boundary(
@@ -2162,7 +2158,7 @@ LONG BrowserAccessibilityComWin::FindIA2Boundary(
if (selection_end >= 0 && start_offset == selection_end)
affinity = Manager()->GetTreeData().sel_focus_affinity;
- ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary);
+ ui::AXTextBoundary boundary = ui::FromIA2TextBoundary(ia2_boundary);
return static_cast<LONG>(
FindTextBoundary(boundary, start_offset, direction, affinity));
}
@@ -2170,7 +2166,7 @@ LONG BrowserAccessibilityComWin::FindIA2Boundary(
LONG BrowserAccessibilityComWin::FindStartOfStyle(
LONG start_offset,
ui::TextBoundaryDirection direction) {
- LONG text_length = static_cast<LONG>(GetText().length());
+ LONG text_length = static_cast<LONG>(GetHypertext().length());
DCHECK_GE(start_offset, 0);
DCHECK_LE(start_offset, text_length);
diff --git a/chromium/content/browser/accessibility/browser_accessibility_com_win.h b/chromium/content/browser/accessibility/browser_accessibility_com_win.h
index a292ee891fb..2560c375ab6 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_com_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_com_win.h
@@ -38,8 +38,9 @@ const GUID GUID_IAccessibleContentDocument = {
{0x95, 0x21, 0x07, 0xed, 0x28, 0xfb, 0x07, 0x2e}};
namespace ui {
+
enum TextBoundaryDirection;
-enum TextBoundaryType;
+
} // namespace ui
namespace content {
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm b/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
index 4ba51bfe1e0..d9be35fdbda 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
@@ -115,7 +115,7 @@ class BrowserAccessibilityMacTest : public ui::CocoaTest {
AXEventNotificationDetails event_bundle;
event_bundle.updates.resize(1);
event_bundle.updates[0].nodes.push_back(root_);
- manager_->OnAccessibilityEvents(event_bundle);
+ ASSERT_TRUE(manager_->OnAccessibilityEvents(event_bundle));
}
ui::AXNodeData root_;
@@ -123,29 +123,18 @@ class BrowserAccessibilityMacTest : public ui::CocoaTest {
std::unique_ptr<BrowserAccessibilityManager> manager_;
};
-// The next few tests all use the deprecated NSObject accessibility APIs:
-// https://crbug.com/921109.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-
// Standard hit test.
TEST_F(BrowserAccessibilityMacTest, HitTestTest) {
BrowserAccessibilityCocoa* firstChild =
[accessibility_ accessibilityHitTest:NSMakePoint(50, 50)];
- EXPECT_NSEQ(
- @"Child1",
- [firstChild
- accessibilityAttributeValue:NSAccessibilityDescriptionAttribute]);
+ EXPECT_NSEQ(@"Child1", firstChild.descriptionForAccessibility);
}
// Test doing a hit test on the edge of a child.
TEST_F(BrowserAccessibilityMacTest, EdgeHitTest) {
BrowserAccessibilityCocoa* firstChild =
[accessibility_ accessibilityHitTest:NSZeroPoint];
- EXPECT_NSEQ(
- @"Child1",
- [firstChild
- accessibilityAttributeValue:NSAccessibilityDescriptionAttribute]);
+ EXPECT_NSEQ(@"Child1", firstChild.descriptionForAccessibility);
}
// This will test a hit test with invalid coordinates. It is assumed that
@@ -159,26 +148,14 @@ TEST_F(BrowserAccessibilityMacTest, InvalidHitTestCoordsTest) {
// Test to ensure querying standard attributes works.
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(BrowserAccessibilityMacTest, InvalidAttributeTest) {
- NSString* shouldBeNil =
- [accessibility_ accessibilityAttributeValue:@"NSAnInvalidAttribute"];
- EXPECT_TRUE(shouldBeNil == nil);
+ EXPECT_NSEQ(@"HelpText", [accessibility_ accessibilityHelp]);
}
TEST_F(BrowserAccessibilityMacTest, RetainedDetachedObjectsReturnNil) {
// Get the first child.
BrowserAccessibilityCocoa* retainedFirstChild =
[accessibility_ accessibilityHitTest:NSMakePoint(50, 50)];
- EXPECT_NSEQ(
- @"Child1",
- [retainedFirstChild
- accessibilityAttributeValue:NSAccessibilityDescriptionAttribute]);
+ EXPECT_NSEQ(@"Child1", retainedFirstChild.descriptionForAccessibility);
// Retain it. This simulates what the system might do with an
// accessibility object.
@@ -188,17 +165,12 @@ TEST_F(BrowserAccessibilityMacTest, RetainedDetachedObjectsReturnNil) {
RebuildAccessibilityTree();
// Now any attributes we query should return nil.
- EXPECT_EQ(
- nil,
- [retainedFirstChild
- accessibilityAttributeValue:NSAccessibilityDescriptionAttribute]);
+ EXPECT_NSEQ(nil, retainedFirstChild.descriptionForAccessibility);
// Don't leak memory in the test.
[retainedFirstChild release];
}
-#pragma clang diagnostic pop
-
TEST_F(BrowserAccessibilityMacTest, TestComputeTextEdit) {
BrowserAccessibility* owner = [accessibility_ owner];
ASSERT_NE(nullptr, owner);
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index 5d268628afa..a5cf72f7dd0 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
@@ -181,6 +181,10 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
}
BrowserAccessibilityManager::~BrowserAccessibilityManager() {
+ if (last_focused_node_tree_id_ &&
+ ax_tree_id_ == *last_focused_node_tree_id_) {
+ SetLastFocusedNode(nullptr);
+ }
tree_.reset(nullptr);
event_generator_.ReleaseTree();
ui::AXTreeManagerMap::GetInstance().RemoveTreeManager(ax_tree_id_);
@@ -228,26 +232,37 @@ ui::AXTreeUpdate BrowserAccessibilityManager::GetEmptyDocument() {
void BrowserAccessibilityManager::FireFocusEventsIfNeeded() {
BrowserAccessibility* focus = GetFocus();
+ // If |focus| is nullptr it means that we have no way of knowing where the
+ // focus is.
+ //
+ // One case when this would happen is when the current tree hasn't connected
+ // to its parent tree yet. That would mean that we have no way of getting to
+ // the top document which holds global focus information for the whole page.
+ //
+ // Note that if there is nothing focused on the page, then the focus should
+ // not be nullptr. The rootnode of the top document should be focused instead.
+ if (!focus)
+ return;
+ DCHECK(focus->instance_active());
// Don't fire focus events if the window itself doesn't have focus.
// Bypass this check for some tests.
if (!never_suppress_or_delay_events_for_testing_ &&
!g_focus_change_callback_for_testing.Get()) {
if (delegate_ && !delegate_->AccessibilityViewHasFocus())
- focus = nullptr;
-
+ return;
if (!CanFireEvents())
- focus = nullptr;
+ return;
}
- // Don't allow the document to be focused if it has no children and
- // hasn't finished loading yet. Wait for at least a tiny bit of content,
- // or for the document to actually finish loading.
- if (focus && focus == focus->manager()->GetRoot() &&
+ // Don't allow the top document to be focused if it has no children and hasn't
+ // finished loading yet. Wait for at least a tiny bit of content, or for the
+ // document to actually finish loading.
+ if (focus == focus->manager()->GetRoot() &&
focus->PlatformChildCount() == 0 &&
!focus->GetBoolAttribute(ax::mojom::BoolAttribute::kBusy) &&
!focus->manager()->GetTreeData().loaded) {
- focus = nullptr;
+ return;
}
BrowserAccessibility* last_focused_node = GetLastFocusedNode();
@@ -260,7 +275,7 @@ void BrowserAccessibilityManager::FireFocusEventsIfNeeded() {
SetLastFocusedNode(focus);
}
-bool BrowserAccessibilityManager::CanFireEvents() {
+bool BrowserAccessibilityManager::CanFireEvents() const {
return true;
}
@@ -278,13 +293,8 @@ void BrowserAccessibilityManager::FireGeneratedEvent(
}
}
-BrowserAccessibility* BrowserAccessibilityManager::GetRoot() {
- // tree_ can be null during destruction.
- if (!tree_)
- return nullptr;
-
- // tree_->root() can be null during AXTreeObserver callbacks.
- ui::AXNode* root = tree_->root();
+BrowserAccessibility* BrowserAccessibilityManager::GetRoot() const {
+ ui::AXNode* root = GetRootAsAXNode();
return root ? GetFromAXNode(root) : nullptr;
}
@@ -303,39 +313,16 @@ BrowserAccessibility* BrowserAccessibilityManager::GetFromID(int32_t id) const {
return nullptr;
}
-BrowserAccessibility*
-BrowserAccessibilityManager::GetParentNodeFromParentTree() {
- if (!GetRoot())
- return nullptr;
-
- ui::AXTreeID parent_tree_id = GetTreeData().parent_tree_id;
+BrowserAccessibility* BrowserAccessibilityManager::GetParentNodeFromParentTree()
+ const {
+ ui::AXNode* parent = GetParentNodeFromParentTreeAsAXNode();
+ ui::AXTreeID parent_tree_id = GetParentTreeID();
BrowserAccessibilityManager* parent_manager =
BrowserAccessibilityManager::FromID(parent_tree_id);
- if (!parent_manager)
- return nullptr;
-
- std::set<int32_t> host_node_ids =
- parent_manager->ax_tree()->GetNodeIdsForChildTreeId(ax_tree_id_);
-
-#if !defined(NDEBUG)
- if (host_node_ids.size() > 1)
- DLOG(WARNING) << "Multiple nodes claim the same child tree id.";
-#endif
-
- for (int32_t host_node_id : host_node_ids) {
- BrowserAccessibility* parent_node = parent_manager->GetFromID(host_node_id);
- if (parent_node) {
- DCHECK_EQ(ax_tree_id_,
- AXTreeID::FromString(parent_node->GetStringAttribute(
- ax::mojom::StringAttribute::kChildTreeId)));
- return parent_node;
- }
- }
-
- return nullptr;
+ return parent ? parent_manager->GetFromAXNode(parent) : nullptr;
}
-const ui::AXTreeData& BrowserAccessibilityManager::GetTreeData() {
+const ui::AXTreeData& BrowserAccessibilityManager::GetTreeData() const {
return tree_->data();
}
@@ -373,7 +360,7 @@ bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() {
return true;
}
-void BrowserAccessibilityManager::OnAccessibilityEvents(
+bool BrowserAccessibilityManager::OnAccessibilityEvents(
const AXEventNotificationDetails& details) {
TRACE_EVENT0("accessibility",
"BrowserAccessibilityManager::OnAccessibilityEvents");
@@ -391,21 +378,22 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
// Process all changes to the accessibility tree first.
for (uint32_t index = 0; index < tree_updates->size(); ++index) {
if (!tree_->Unserialize((*tree_updates)[index])) {
+ // This is a fatal error, but if there is a delegate, it will handle the
+ // error result and recover by re-creating the manager.
if (delegate_) {
LOG(ERROR) << tree_->error();
- delegate_->AccessibilityFatalError();
} else {
CHECK(false) << tree_->error();
}
- return;
+ return false;
}
}
// If this page is hidden by an interstitial, suppress all events.
BrowserAccessibilityManager* root_manager = GetRootManager();
- if (root_manager->hidden_by_interstitial_page()) {
+ if (root_manager && root_manager->hidden_by_interstitial_page()) {
event_generator_.ClearEvents();
- return;
+ return true;
}
// If the root's parent is in another accessibility tree but it wasn't
@@ -426,7 +414,7 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
// Screen readers might not do the right thing if they're not aware of what
// has focus, so always try that first. Nothing will be fired if the window
// itself isn't focused or if focus hasn't changed.
- root_manager->FireFocusEventsIfNeeded();
+ FireFocusEventsIfNeeded();
// Fire any events related to changes to the tree.
for (auto targeted_event : event_generator_) {
@@ -457,13 +445,19 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
if (!event_target || !event_target->CanFireEvents())
continue;
- if (event.event_type == ax::mojom::Event::kHover)
+ if (root_manager && event.event_type == ax::mojom::Event::kHover)
root_manager->CacheHitTestResult(event_target);
FireBlinkEvent(event.event_type, event_target);
}
+
+ // Allow derived classes to do event post-processing.
+ FinalizeAccessibilityEvents();
+ return true;
}
+void BrowserAccessibilityManager::FinalizeAccessibilityEvents() {}
+
void BrowserAccessibilityManager::OnLocationChanges(
const std::vector<AccessibilityHostMsg_LocationChangeParams>& params) {
for (size_t i = 0; i < params.size(); ++i) {
@@ -522,7 +516,7 @@ void BrowserAccessibilityManager::ActivateFindInPageResult(int request_id) {
}
BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendant(
- BrowserAccessibility* focus) {
+ BrowserAccessibility* focus) const {
if (!focus)
return nullptr;
@@ -559,40 +553,50 @@ BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendant(
return focus;
}
-bool BrowserAccessibilityManager::NativeViewHasFocus() {
+bool BrowserAccessibilityManager::NativeViewHasFocus() const {
BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager();
return delegate && delegate->AccessibilityViewHasFocus();
}
-BrowserAccessibility* BrowserAccessibilityManager::GetFocus() {
+BrowserAccessibility* BrowserAccessibilityManager::GetFocus() const {
BrowserAccessibilityManager* root_manager = GetRootManager();
- if (!root_manager)
- root_manager = this;
- ui::AXTreeID focused_tree_id = root_manager->GetTreeData().focused_tree_id;
+ if (!root_manager) {
+ // We can't retrieved the globally focused object since we don't have access
+ // to the top document. If we return the focus in the current or a
+ // descendent tree, it might be wrong, since the top document might have
+ // another frame as the tree with the focus.
+ return nullptr;
+ }
+ ui::AXTreeID focused_tree_id = root_manager->GetTreeData().focused_tree_id;
BrowserAccessibilityManager* focused_manager = nullptr;
if (focused_tree_id != ui::AXTreeIDUnknown())
focused_manager = BrowserAccessibilityManager::FromID(focused_tree_id);
- // BrowserAccessibilityManager::FromID(focused_tree_id) may return nullptr
- // if the tree is not created or has been destroyed.
+ // BrowserAccessibilityManager::FromID(focused_tree_id) may return nullptr if
+ // the tree is not created or has been destroyed. In this case, we don't
+ // really know where the focus is, so we should return nullptr. However, due
+ // to a bug in RenderFrameHostImpl this is currently not possible.
+ //
+ // TODO(nektar): Fix All the issues identified in crbug.com/956748
if (!focused_manager)
- focused_manager = root_manager;
+ return GetFocusFromThisOrDescendantFrame();
return focused_manager->GetFocusFromThisOrDescendantFrame();
}
BrowserAccessibility*
-BrowserAccessibilityManager::GetFocusFromThisOrDescendantFrame() {
+BrowserAccessibilityManager::GetFocusFromThisOrDescendantFrame() const {
int32_t focus_id = GetTreeData().focus_id;
BrowserAccessibility* obj = GetFromID(focus_id);
+ // If nothing is focused, then the top document has the focus.
if (!obj)
return GetRoot();
if (obj->HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId)) {
AXTreeID child_tree_id = AXTreeID::FromString(
obj->GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId));
- BrowserAccessibilityManager* child_manager =
+ const BrowserAccessibilityManager* child_manager =
BrowserAccessibilityManager::FromID(child_tree_id);
if (child_manager)
return child_manager->GetFocusFromThisOrDescendantFrame();
@@ -611,6 +615,18 @@ void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) {
delegate_->AccessibilityPerformAction(action_data);
}
+void BrowserAccessibilityManager::SetSequentialFocusNavigationStartingPoint(
+ const BrowserAccessibility& node) {
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.action =
+ ax::mojom::Action::kSetSequentialFocusNavigationStartingPoint;
+ action_data.target_node_id = node.GetId();
+ delegate_->AccessibilityPerformAction(action_data);
+}
+
void BrowserAccessibilityManager::SetFocusLocallyForTesting(
BrowserAccessibility* node) {
ui::AXTreeData data = GetTreeData();
@@ -1017,7 +1033,7 @@ base::string16 BrowserAccessibilityManager::GetTextForRange(
const BrowserAccessibility& start_object,
const BrowserAccessibility& end_object) {
return GetTextForRange(start_object, 0, end_object,
- end_object.GetText().length());
+ end_object.GetInnerText().length());
}
// static
@@ -1033,13 +1049,14 @@ base::string16 BrowserAccessibilityManager::GetTextForRange(
if (start_offset > end_offset)
std::swap(start_offset, end_offset);
- if (start_offset >= static_cast<int>(start_object.GetText().length()) ||
- end_offset > static_cast<int>(start_object.GetText().length())) {
+ if (start_offset >=
+ static_cast<int>(start_object.GetInnerText().length()) ||
+ end_offset > static_cast<int>(start_object.GetInnerText().length())) {
return base::string16();
}
- return start_object.GetText().substr(start_offset,
- end_offset - start_offset);
+ return start_object.GetInnerText().substr(start_offset,
+ end_offset - start_offset);
}
std::vector<const BrowserAccessibility*> text_only_objects =
@@ -1053,12 +1070,12 @@ base::string16 BrowserAccessibilityManager::GetTextForRange(
std::swap(start_offset, end_offset);
const BrowserAccessibility* text_object = text_only_objects[0];
- if (start_offset < static_cast<int>(text_object->GetText().length()) &&
- end_offset <= static_cast<int>(text_object->GetText().length())) {
- return text_object->GetText().substr(start_offset,
- end_offset - start_offset);
+ if (start_offset < static_cast<int>(text_object->GetInnerText().length()) &&
+ end_offset <= static_cast<int>(text_object->GetInnerText().length())) {
+ return text_object->GetInnerText().substr(start_offset,
+ end_offset - start_offset);
}
- return text_object->GetText();
+ return text_object->GetInnerText();
}
base::string16 text;
@@ -1070,28 +1087,30 @@ base::string16 BrowserAccessibilityManager::GetTextForRange(
if (!first_object || first_object != start_text_object)
std::swap(start_offset, end_offset);
- if (start_offset < static_cast<int>(start_text_object->GetText().length())) {
- text += start_text_object->GetText().substr(start_offset);
+ if (start_offset <
+ static_cast<int>(start_text_object->GetInnerText().length())) {
+ text += start_text_object->GetInnerText().substr(start_offset);
} else {
- text += start_text_object->GetText();
+ text += start_text_object->GetInnerText();
}
for (size_t i = 1; i < text_only_objects.size() - 1; ++i) {
- text += text_only_objects[i]->GetText();
+ text += text_only_objects[i]->GetInnerText();
}
const BrowserAccessibility* end_text_object = text_only_objects.back();
- if (end_offset <= static_cast<int>(end_text_object->GetText().length())) {
- text += end_text_object->GetText().substr(0, end_offset);
+ if (end_offset <=
+ static_cast<int>(end_text_object->GetInnerText().length())) {
+ text += end_text_object->GetInnerText().substr(0, end_offset);
} else {
- text += end_text_object->GetText();
+ text += end_text_object->GetInnerText();
}
return text;
}
// static
-gfx::Rect BrowserAccessibilityManager::GetRootFrameRangeBoundsRect(
+gfx::Rect BrowserAccessibilityManager::GetRootFrameInnerTextRangeBoundsRect(
const BrowserAccessibility& start_object,
int start_offset,
const BrowserAccessibility& end_object,
@@ -1103,14 +1122,14 @@ gfx::Rect BrowserAccessibilityManager::GetRootFrameRangeBoundsRect(
if (start_offset > end_offset)
std::swap(start_offset, end_offset);
- if (start_offset >= static_cast<int>(start_object.GetText().length()) ||
- end_offset > static_cast<int>(start_object.GetText().length())) {
+ if (start_offset >=
+ static_cast<int>(start_object.GetInnerText().length()) ||
+ end_offset > static_cast<int>(start_object.GetInnerText().length())) {
return gfx::Rect();
}
- return start_object.GetRootFrameRangeBoundsRect(
- start_offset, end_offset - start_offset,
- ui::AXClippingBehavior::kUnclipped);
+ return start_object.GetUnclippedRootFrameInnerTextRangeBoundsRect(
+ start_offset, end_offset);
}
gfx::Rect result;
@@ -1132,16 +1151,15 @@ gfx::Rect BrowserAccessibilityManager::GetRootFrameRangeBoundsRect(
const BrowserAccessibility* current = first;
do {
if (current->IsTextOnlyObject()) {
- int len = static_cast<int>(current->GetText().size());
+ int len = static_cast<int>(current->GetInnerText().size());
int start_char_index = 0;
int end_char_index = len;
if (current == first)
start_char_index = start_offset;
if (current == last)
end_char_index = end_offset;
- result.Union(current->GetRootFrameRangeBoundsRect(
- start_char_index, end_char_index - start_char_index,
- ui::AXClippingBehavior::kUnclipped));
+ result.Union(current->GetUnclippedRootFrameInnerTextRangeBoundsRect(
+ start_char_index, end_char_index));
} else {
result.Union(current->GetClippedRootFrameBoundsRect());
}
@@ -1205,30 +1223,49 @@ void BrowserAccessibilityManager::OnAtomicUpdateFinished(
ui::AXTree* tree,
bool root_changed,
const std::vector<ui::AXTreeObserver::Change>& changes) {
- // When the root changes and this is the root manager, we may need to
- // fire a new focus event.
- if (root_changed && last_focused_node_tree_id_ &&
- ax_tree_id_ == last_focused_node_tree_id_.value())
+ const bool ax_tree_id_changed =
+ GetTreeData().tree_id != ui::AXTreeIDUnknown() &&
+ GetTreeData().tree_id != ax_tree_id_;
+ // When the tree that contains the focus is destroyed and re-created, we
+ // should fire a new focus event. Also, whenever the tree ID or the root of
+ // this tree changes we may need to fire an event on our parent node in the
+ // parent tree to ensure that we're properly connected.
+ if (ax_tree_id_changed && last_focused_node_tree_id_ &&
+ ax_tree_id_ == *last_focused_node_tree_id_) {
SetLastFocusedNode(nullptr);
+ }
+ if (ax_tree_id_changed || root_changed)
+ connected_to_parent_tree_node_ = false;
- bool ax_tree_id_changed = false;
- if (GetTreeData().tree_id != ui::AXTreeIDUnknown() &&
- GetTreeData().tree_id != ax_tree_id_) {
+ if (ax_tree_id_changed) {
ui::AXTreeManagerMap::GetInstance().RemoveTreeManager(ax_tree_id_);
ax_tree_id_ = GetTreeData().tree_id;
ui::AXTreeManagerMap::GetInstance().AddTreeManager(ax_tree_id_, this);
- ax_tree_id_changed = true;
}
- // Whenever the tree ID or the root of this tree changes we may need to
- // fire an event on our parent node in the parent tree to ensure that
- // we're properly connected.
- if (ax_tree_id_changed || root_changed)
- connected_to_parent_tree_node_ = false;
+ // Calls OnDataChanged on newly created or reparented nodes.
+ for (const auto change : changes) {
+ ui::AXNode* node = change.node;
+ BrowserAccessibility* wrapper = GetFromAXNode(node);
+ if (wrapper) {
+ switch (change.type) {
+ case NODE_CREATED:
+ case NODE_REPARENTED:
+ wrapper->OnDataChanged();
+ break;
+ // Unhandled.
+ case NODE_CHANGED:
+ case SUBTREE_CREATED:
+ case SUBTREE_REPARENTED:
+ break;
+ }
+ }
+ }
}
-ui::AXNode* BrowserAccessibilityManager::GetNodeFromTree(ui::AXTreeID tree_id,
- int32_t node_id) {
+ui::AXNode* BrowserAccessibilityManager::GetNodeFromTree(
+ const ui::AXTreeID tree_id,
+ const int32_t node_id) const {
auto* manager = BrowserAccessibilityManager::FromID(tree_id);
if (!manager)
return nullptr;
@@ -1241,8 +1278,8 @@ ui::AXNode* BrowserAccessibilityManager::GetNodeFromTree(ui::AXTreeID tree_id,
}
ui::AXPlatformNodeDelegate* BrowserAccessibilityManager::GetDelegate(
- ui::AXTreeID tree_id,
- int32_t node_id) {
+ const ui::AXTreeID tree_id,
+ const int32_t node_id) const {
auto* manager = BrowserAccessibilityManager::FromID(tree_id);
if (!manager)
return nullptr;
@@ -1254,24 +1291,94 @@ ui::AXPlatformNodeDelegate* BrowserAccessibilityManager::GetDelegate(
return nullptr;
}
-BrowserAccessibilityManager* BrowserAccessibilityManager::GetRootManager() {
+AXTreeID BrowserAccessibilityManager::GetTreeID() const {
+ return ax_tree_id();
+}
+
+AXTreeID BrowserAccessibilityManager::GetParentTreeID() const {
+ return GetTreeData().parent_tree_id;
+}
+
+ui::AXNode* BrowserAccessibilityManager::GetRootAsAXNode() const {
+ // tree_ can be null during destruction.
+ if (!tree_)
+ return nullptr;
+
+ // tree_->root() can be null during AXTreeObserver callbacks.
+ return tree_->root();
+}
+
+ui::AXNode* BrowserAccessibilityManager::GetParentNodeFromParentTreeAsAXNode()
+ const {
+ if (!GetRootAsAXNode())
+ return nullptr;
+
+ ui::AXTreeID parent_tree_id = GetParentTreeID();
+ BrowserAccessibilityManager* parent_manager =
+ BrowserAccessibilityManager::FromID(parent_tree_id);
+ if (!parent_manager)
+ return nullptr;
+
+ std::set<int32_t> host_node_ids =
+ parent_manager->ax_tree()->GetNodeIdsForChildTreeId(ax_tree_id_);
+
+#if !defined(NDEBUG)
+ if (host_node_ids.size() > 1)
+ DLOG(WARNING) << "Multiple nodes claim the same child tree id.";
+#endif
+
+ for (int32_t host_node_id : host_node_ids) {
+ ui::AXNode* parent_node =
+ parent_manager->GetNodeFromTree(parent_tree_id, host_node_id);
+ if (parent_node) {
+ DCHECK_EQ(ax_tree_id_,
+ AXTreeID::FromString(parent_node->GetStringAttribute(
+ ax::mojom::StringAttribute::kChildTreeId)));
+ return parent_node;
+ }
+ }
+
+ return nullptr;
+}
+
+ui::AXPlatformNodeDelegate* BrowserAccessibilityManager::GetRootDelegate(
+ const ui::AXTreeID tree_id) const {
+ auto* manager = BrowserAccessibilityManager::FromID(tree_id);
+ if (!manager)
+ return nullptr;
+
+ return manager->GetRoot();
+}
+
+BrowserAccessibilityManager* BrowserAccessibilityManager::GetRootManager()
+ const {
BrowserAccessibility* parent = GetParentNodeFromParentTree();
- if (!parent)
- return this;
+ if (parent) {
+ DCHECK(parent->instance_active())
+ << "The BrowserAccessibility object in the parent tree that is hosting "
+ "this tree should not have been destroyed before its child tree.";
+ return parent->manager() ? parent->manager()->GetRootManager() : nullptr;
+ }
- return parent->manager()->GetRootManager();
+ if (IsRootTree())
+ return const_cast<BrowserAccessibilityManager*>(this);
+
+ // The current tree is disconnected from its parent, so we can't retrieve the
+ // root manager yet.
+ return nullptr;
}
BrowserAccessibilityDelegate*
-BrowserAccessibilityManager::GetDelegateFromRootManager() {
+BrowserAccessibilityManager::GetDelegateFromRootManager() const {
BrowserAccessibilityManager* root_manager = GetRootManager();
if (root_manager)
return root_manager->delegate();
return nullptr;
}
-bool BrowserAccessibilityManager::IsRootTree() {
- return delegate()->AccessibilityIsMainFrame();
+bool BrowserAccessibilityManager::IsRootTree() const {
+ return delegate_ && delegate_->AccessibilityIsMainFrame() &&
+ GetTreeData().parent_tree_id == ui::AXTreeIDUnknown();
}
// static
@@ -1326,7 +1433,7 @@ BrowserAccessibility* BrowserAccessibilityManager::CachingAsyncHitTest(
if (root_manager && root_manager != this)
return root_manager->CachingAsyncHitTest(scaled_point);
- if (delegate()) {
+ if (delegate_) {
// This triggers an asynchronous request to compute the true object that's
// under |scaled_point|.
HitTest(scaled_point - GetViewBounds().OffsetFromOrigin());
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.h b/chromium/content/browser/accessibility/browser_accessibility_manager.h
index b1e8eaf63bc..0df11c6077e 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -91,7 +91,7 @@ class CONTENT_EXPORT BrowserAccessibilityDelegate {
// Returns true if this delegate represents the main (topmost) frame in a
// tree of frames.
- virtual bool AccessibilityIsMainFrame() = 0;
+ virtual bool AccessibilityIsMainFrame() const = 0;
};
class CONTENT_EXPORT BrowserAccessibilityFactory {
@@ -164,10 +164,10 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeObserver,
virtual void OnFocusLost(BrowserAccessibility* node) {}
// Return whether or not we are currently able to fire events.
- virtual bool CanFireEvents();
+ virtual bool CanFireEvents() const;
- // Return a pointer to the root of the tree, does not make a new reference.
- BrowserAccessibility* GetRoot();
+ // Return a pointer to the root of the tree.
+ BrowserAccessibility* GetRoot() const;
// Returns a pointer to the BrowserAccessibility object for a given AXNode.
BrowserAccessibility* GetFromAXNode(const ui::AXNode* node) const;
@@ -177,10 +177,10 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeObserver,
BrowserAccessibility* GetFromID(int32_t id) const;
// If this tree has a parent tree, return the parent node in that tree.
- BrowserAccessibility* GetParentNodeFromParentTree();
+ BrowserAccessibility* GetParentNodeFromParentTree() const;
// Get the AXTreeData for this frame.
- const ui::AXTreeData& GetTreeData();
+ const ui::AXTreeData& GetTreeData() const;
// Called to notify the accessibility manager that its associated native
// view got focused.
@@ -244,6 +244,8 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeObserver,
void ScrollToPoint(const BrowserAccessibility& node, gfx::Point point);
void SetAccessibilityFocus(const BrowserAccessibility& node);
void SetFocus(const BrowserAccessibility& node);
+ void SetSequentialFocusNavigationStartingPoint(
+ const BrowserAccessibility& node);
void SetScrollOffset(const BrowserAccessibility& node, gfx::Point offset);
void SetValue(const BrowserAccessibility& node, const std::string& value);
void SetSelection(const ui::AXActionData& action_data);
@@ -258,8 +260,14 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeObserver,
// given find in page result.
void ActivateFindInPageResult(int request_id, int match_index);
- // Called when the renderer process has notified us of about tree changes.
- virtual void OnAccessibilityEvents(const AXEventNotificationDetails& details);
+ // Called when the renderer process has notified us of tree changes. Returns
+ // false in fatal-error conditions, in which case the caller should destroy
+ // the manager.
+ virtual bool OnAccessibilityEvents(const AXEventNotificationDetails& details)
+ WARN_UNUSED_RESULT;
+
+ // Allows derived classes to do event post-processing.
+ virtual void FinalizeAccessibilityEvents();
// Called when the renderer process updates the location of accessibility
// objects. Calls SendLocationChangeEvents(), which can be overridden.
@@ -300,19 +308,20 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeObserver,
BrowserAccessibilityManagerMac* ToBrowserAccessibilityManagerMac();
#endif
- // Return the object that has focus, starting at the top of the frame tree.
- virtual BrowserAccessibility* GetFocus();
+ // Returns the object that has focus, starting at the top of the frame tree,
+ // or returns nullptr if this manager doesn't have access to the top document.
+ virtual BrowserAccessibility* GetFocus() const;
// Return the object that has focus, only considering this frame and
// descendants.
- BrowserAccessibility* GetFocusFromThisOrDescendantFrame();
+ BrowserAccessibility* GetFocusFromThisOrDescendantFrame() const;
// Given a focused node |focus|, returns a descendant of that node if it
// has an active descendant, otherwise returns |focus|.
- BrowserAccessibility* GetActiveDescendant(BrowserAccessibility* focus);
+ BrowserAccessibility* GetActiveDescendant(BrowserAccessibility* focus) const;
// Returns true if native focus is anywhere in this WebContents or not.
- bool NativeViewHasFocus();
+ bool NativeViewHasFocus() const;
// True by default, but some platforms want to treat the root
// scroll offsets separately.
@@ -361,7 +370,9 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeObserver,
const BrowserAccessibility& end_object,
int end_offset);
- static gfx::Rect GetRootFrameRangeBoundsRect(
+ // DEPRECATED: Prefer using AXPlatformNodeDelegate bounds interfaces when
+ // writing new code.
+ static gfx::Rect GetRootFrameInnerTextRangeBoundsRect(
const BrowserAccessibility& start_object,
int start_offset,
const BrowserAccessibility& end_object,
@@ -384,22 +395,32 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeObserver,
const std::vector<ui::AXTreeObserver::Change>& changes) override;
// AXTreeManager implementation.
- ui::AXNode* GetNodeFromTree(ui::AXTreeID tree_id, int32_t node_id) override;
- ui::AXPlatformNodeDelegate* GetDelegate(ui::AXTreeID tree_id,
- int32_t node_id) override;
+ ui::AXNode* GetNodeFromTree(ui::AXTreeID tree_id,
+ int32_t node_id) const override;
+ ui::AXPlatformNodeDelegate* GetDelegate(const ui::AXTreeID tree_id,
+ const int32_t node_id) const override;
+ ui::AXPlatformNodeDelegate* GetRootDelegate(
+ const ui::AXTreeID tree_id) const override;
+ AXTreeID GetTreeID() const override;
+ AXTreeID GetParentTreeID() const override;
+ ui::AXNode* GetRootAsAXNode() const override;
+ ui::AXNode* GetParentNodeFromParentTreeAsAXNode() const override;
BrowserAccessibilityDelegate* delegate() const { return delegate_; }
// If this BrowserAccessibilityManager is a child frame or guest frame,
- // return the BrowserAccessibilityManager from the highest ancestor frame
- // in the frame tree.
- BrowserAccessibilityManager* GetRootManager();
+ // returns the BrowserAccessibilityManager from the top document in the frame
+ // tree. If the current frame is not connected to its parent frame yet, or if
+ // it got disconnected after being reparented, return nullptr to indicate that
+ // we don't have access to the root manager yet.
+ BrowserAccessibilityManager* GetRootManager() const;
- // Returns the BrowserAccessibilityDelegate from |GetRootManager|, above.
- BrowserAccessibilityDelegate* GetDelegateFromRootManager();
+ // Returns the BrowserAccessibilityDelegate from |GetRootManager| above, or
+ // returns nullptr in case we don't have access to the root manager yet.
+ BrowserAccessibilityDelegate* GetDelegateFromRootManager() const;
// Returns whether this is the top document.
- bool IsRootTree();
+ bool IsRootTree() const;
// Get a snapshot of the current tree as an AXTreeUpdate.
ui::AXTreeUpdate SnapshotAXTreeForTesting();
@@ -434,7 +455,6 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeObserver,
static void SetLastFocusedNode(BrowserAccessibility* node);
static BrowserAccessibility* GetLastFocusedNode();
- protected:
// The object that can perform actions on our behalf.
BrowserAccessibilityDelegate* delegate_;
@@ -445,7 +465,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeObserver,
std::unique_ptr<ui::AXSerializableTree> tree_;
// A mapping from a node id to its wrapper of type BrowserAccessibility.
- std::unordered_map<int32_t, BrowserAccessibility*> id_wrapper_map_;
+ std::map<int32_t, BrowserAccessibility*> id_wrapper_map_;
// True if the user has initiated a navigation to another page.
bool user_is_navigating_away_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
index 35f791b09af..1e8f80cd333 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -63,9 +63,9 @@ bool BrowserAccessibilityManagerAndroid::ShouldExposePasswordText() {
return wcax ? wcax->ShouldExposePasswordText() : false;
}
-BrowserAccessibility* BrowserAccessibilityManagerAndroid::GetFocus() {
+BrowserAccessibility* BrowserAccessibilityManagerAndroid::GetFocus() const {
BrowserAccessibility* focus = BrowserAccessibilityManager::GetFocus();
- if (!focus->IsPlainTextField())
+ if (focus && !focus->IsPlainTextField())
return GetActiveDescendant(focus);
return focus;
}
@@ -160,7 +160,8 @@ void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
if (node->manager() == GetRootManager()) {
auto* android_focused =
static_cast<BrowserAccessibilityAndroid*>(GetFocus());
- wcax->HandlePageLoaded(android_focused->unique_id());
+ if (android_focused)
+ wcax->HandlePageLoaded(android_focused->unique_id());
}
break;
case ui::AXEventGenerator::Event::CHECKED_STATE_CHANGED:
@@ -176,7 +177,7 @@ void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
case ui::AXEventGenerator::Event::LIVE_REGION_NODE_CHANGED: {
// This event is fired when an object appears in a live region.
// Speak its text.
- base::string16 text = android_node->GetText();
+ base::string16 text = android_node->GetInnerText();
wcax->AnnounceLiveRegionText(text);
break;
}
@@ -199,6 +200,8 @@ void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
break;
case ui::AXEventGenerator::Event::ACCESS_KEY_CHANGED:
case ui::AXEventGenerator::Event::ACTIVE_DESCENDANT_CHANGED:
+ case ui::AXEventGenerator::Event::ATOMIC_CHANGED:
+ case ui::AXEventGenerator::Event::BUSY_CHANGED:
case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED:
case ui::AXEventGenerator::Event::CHILDREN_CHANGED:
case ui::AXEventGenerator::Event::CLASS_NAME_CHANGED:
@@ -207,10 +210,13 @@ void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
case ui::AXEventGenerator::Event::DESCRIBED_BY_CHANGED:
case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
+ case ui::AXEventGenerator::Event::DROPEFFECT_CHANGED:
case ui::AXEventGenerator::Event::EXPANDED:
case ui::AXEventGenerator::Event::ENABLED_CHANGED:
case ui::AXEventGenerator::Event::FLOW_FROM_CHANGED:
case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
+ case ui::AXEventGenerator::Event::GRABBED_CHANGED:
+ case ui::AXEventGenerator::Event::HASPOPUP_CHANGED:
case ui::AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
case ui::AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
@@ -220,8 +226,11 @@ void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
case ui::AXEventGenerator::Event::LAYOUT_INVALIDATED:
case ui::AXEventGenerator::Event::LIVE_REGION_CHANGED:
case ui::AXEventGenerator::Event::LIVE_REGION_CREATED:
+ case ui::AXEventGenerator::Event::LIVE_RELEVANT_CHANGED:
+ case ui::AXEventGenerator::Event::LIVE_STATUS_CHANGED:
case ui::AXEventGenerator::Event::LOAD_START:
case ui::AXEventGenerator::Event::MENU_ITEM_SELECTED:
+ case ui::AXEventGenerator::Event::MULTILINE_STATE_CHANGED:
case ui::AXEventGenerator::Event::MULTISELECTABLE_STATE_CHANGED:
case ui::AXEventGenerator::Event::NAME_CHANGED:
case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
@@ -235,6 +244,7 @@ void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
case ui::AXEventGenerator::Event::SELECTED_CHANGED:
case ui::AXEventGenerator::Event::SELECTED_CHILDREN_CHANGED:
case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
+ case ui::AXEventGenerator::Event::SORT_CHANGED:
case ui::AXEventGenerator::Event::STATE_CHANGED:
case ui::AXEventGenerator::Event::SUBTREE_CREATED:
case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
@@ -270,7 +280,7 @@ bool BrowserAccessibilityManagerAndroid::NextAtGranularity(
int32_t* end_index) {
switch (granularity) {
case ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_CHARACTER: {
- base::string16 text = node->GetText();
+ base::string16 text = node->GetInnerText();
if (cursor_index >= static_cast<int32_t>(text.length()))
return false;
base::i18n::UTF16CharIterator iter(text.data(), text.size());
@@ -316,7 +326,7 @@ bool BrowserAccessibilityManagerAndroid::PreviousAtGranularity(
case ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_CHARACTER: {
if (cursor_index <= 0)
return false;
- base::string16 text = node->GetText();
+ base::string16 text = node->GetInnerText();
base::i18n::UTF16CharIterator iter(text.data(), text.size());
int previous_index = 0;
while (!iter.end() && iter.array_pos() < cursor_index) {
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
index 9a55289fa64..33a098ca360 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -70,7 +70,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
bool OnHoverEvent(const ui::MotionEventAndroid& event);
// BrowserAccessibilityManager overrides.
- BrowserAccessibility* GetFocus() override;
+ BrowserAccessibility* GetFocus() const override;
void SendLocationChangeEvents(
const std::vector<AccessibilityHostMsg_LocationChangeParams>& params)
override;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
index 253c7db2f75..b5846a5e7fe 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -119,6 +119,13 @@ void BrowserAccessibilityManagerAuraLinux::FireDescriptionChangedEvent(
ToBrowserAccessibilityAuraLinux(node)->GetNode()->OnDescriptionChanged();
}
+void BrowserAccessibilityManagerAuraLinux::FireSubtreeCreatedEvent(
+ BrowserAccessibility* node) {
+ // Sending events during a load would create a lot of spam, don't do that.
+ if (GetTreeData().loaded)
+ ToBrowserAccessibilityAuraLinux(node)->GetNode()->OnSubtreeCreated();
+}
+
void BrowserAccessibilityManagerAuraLinux::FireGeneratedEvent(
ui::AXEventGenerator::Event event_type,
BrowserAccessibility* node) {
@@ -132,6 +139,9 @@ void BrowserAccessibilityManagerAuraLinux::FireGeneratedEvent(
FireEvent(focus_object, ax::mojom::Event::kTextSelectionChanged);
break;
}
+ case ui::AXEventGenerator::Event::ACTIVE_DESCENDANT_CHANGED:
+ FireEvent(node, ax::mojom::Event::kActiveDescendantChanged);
+ break;
case ui::AXEventGenerator::Event::CHECKED_STATE_CHANGED:
FireEvent(node, ax::mojom::Event::kCheckedStateChanged);
break;
@@ -158,6 +168,9 @@ void BrowserAccessibilityManagerAuraLinux::FireGeneratedEvent(
case ui::AXEventGenerator::Event::SELECTED_CHANGED:
FireSelectedEvent(node);
break;
+ case ui::AXEventGenerator::Event::SUBTREE_CREATED:
+ FireSubtreeCreatedEvent(node);
+ break;
case ui::AXEventGenerator::Event::VALUE_CHANGED:
FireEvent(node, ax::mojom::Event::kValueChanged);
break;
@@ -209,6 +222,19 @@ static void EstablishEmbeddedRelationship(AtkObject* document_object) {
document_platform_node->SetEmbeddingWindow(window);
}
+void BrowserAccessibilityManagerAuraLinux::OnSubtreeWillBeDeleted(
+ ui::AXTree* tree,
+ ui::AXNode* node) {
+ BrowserAccessibilityManager::OnSubtreeWillBeDeleted(tree, node);
+ // Sending events on load/destruction would create a lot of spam, avoid that.
+ if (!GetTreeData().loaded)
+ return;
+
+ BrowserAccessibility* obj = GetFromAXNode(node);
+ if (obj && obj->IsNative())
+ ToBrowserAccessibilityAuraLinux(obj)->GetNode()->OnSubtreeWillBeDeleted();
+}
+
void BrowserAccessibilityManagerAuraLinux::OnAtomicUpdateFinished(
ui::AXTree* tree,
bool root_changed,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
index 9019341319b..18e932fd7e5 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
@@ -38,9 +38,11 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAuraLinux
void FireLoadingEvent(BrowserAccessibility* node, bool is_loading);
void FireNameChangedEvent(BrowserAccessibility* node);
void FireDescriptionChangedEvent(BrowserAccessibility* node);
+ void FireSubtreeCreatedEvent(BrowserAccessibility* node);
protected:
// AXTreeObserver methods.
+ void OnSubtreeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
void OnAtomicUpdateFinished(
ui::AXTree* tree,
bool root_changed,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
index 31a11ed9ec5..18480924c58 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -31,7 +31,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
static ui::AXTreeUpdate GetEmptyDocument();
- BrowserAccessibility* GetFocus() override;
+ BrowserAccessibility* GetFocus() const override;
// Implementation of BrowserAccessibilityManager.
void FireFocusEvent(BrowserAccessibility* node) override;
@@ -40,7 +40,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
void FireGeneratedEvent(ui::AXEventGenerator::Event event_type,
BrowserAccessibility* node) override;
- void OnAccessibilityEvents(
+ bool OnAccessibilityEvents(
const AXEventNotificationDetails& details) override;
id GetParentView();
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
index eb2f9c29b30..0c9de0ce250 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -140,7 +140,7 @@ ui::AXTreeUpdate BrowserAccessibilityManagerMac::GetEmptyDocument() {
return update;
}
-BrowserAccessibility* BrowserAccessibilityManagerMac::GetFocus() {
+BrowserAccessibility* BrowserAccessibilityManagerMac::GetFocus() const {
BrowserAccessibility* focus = BrowserAccessibilityManager::GetFocus();
// For editable combo boxes, focus should stay on the combo box so the user
@@ -372,16 +372,21 @@ void BrowserAccessibilityManagerMac::FireGeneratedEvent(
mac_notification = NSAccessibilityMenuItemSelectedNotification;
break;
case ui::AXEventGenerator::Event::ACCESS_KEY_CHANGED:
+ case ui::AXEventGenerator::Event::ATOMIC_CHANGED:
case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED:
+ case ui::AXEventGenerator::Event::BUSY_CHANGED:
case ui::AXEventGenerator::Event::CHILDREN_CHANGED:
case ui::AXEventGenerator::Event::CONTROLS_CHANGED:
case ui::AXEventGenerator::Event::CLASS_NAME_CHANGED:
case ui::AXEventGenerator::Event::DESCRIBED_BY_CHANGED:
case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
+ case ui::AXEventGenerator::Event::DROPEFFECT_CHANGED:
case ui::AXEventGenerator::Event::ENABLED_CHANGED:
case ui::AXEventGenerator::Event::FLOW_FROM_CHANGED:
case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
+ case ui::AXEventGenerator::Event::GRABBED_CHANGED:
+ case ui::AXEventGenerator::Event::HASPOPUP_CHANGED:
case ui::AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
case ui::AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
case ui::AXEventGenerator::Event::KEY_SHORTCUTS_CHANGED:
@@ -389,7 +394,10 @@ void BrowserAccessibilityManagerMac::FireGeneratedEvent(
case ui::AXEventGenerator::Event::LANGUAGE_CHANGED:
case ui::AXEventGenerator::Event::LAYOUT_INVALIDATED:
case ui::AXEventGenerator::Event::LIVE_REGION_NODE_CHANGED:
+ case ui::AXEventGenerator::Event::LIVE_RELEVANT_CHANGED:
+ case ui::AXEventGenerator::Event::LIVE_STATUS_CHANGED:
case ui::AXEventGenerator::Event::LOAD_START:
+ case ui::AXEventGenerator::Event::MULTILINE_STATE_CHANGED:
case ui::AXEventGenerator::Event::MULTISELECTABLE_STATE_CHANGED:
case ui::AXEventGenerator::Event::NAME_CHANGED:
case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
@@ -403,6 +411,7 @@ void BrowserAccessibilityManagerMac::FireGeneratedEvent(
case ui::AXEventGenerator::Event::SCROLL_VERTICAL_POSITION_CHANGED:
case ui::AXEventGenerator::Event::SELECTED_CHANGED:
case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
+ case ui::AXEventGenerator::Event::SORT_CHANGED:
case ui::AXEventGenerator::Event::STATE_CHANGED:
case ui::AXEventGenerator::Event::SUBTREE_CREATED:
case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
@@ -428,12 +437,10 @@ void BrowserAccessibilityManagerMac::FireNativeMacNotification(
NSAccessibilityPostNotification(native_node, mac_notification);
}
-void BrowserAccessibilityManagerMac::OnAccessibilityEvents(
+bool BrowserAccessibilityManagerMac::OnAccessibilityEvents(
const AXEventNotificationDetails& details) {
text_edits_.clear();
- // Call the base method last as it might delete the tree if it receives an
- // invalid message.
- BrowserAccessibilityManager::OnAccessibilityEvents(details);
+ return BrowserAccessibilityManager::OnAccessibilityEvents(details);
}
void BrowserAccessibilityManagerMac::OnAtomicUpdateFinished(
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
index 0d2fddd951e..d72194964c9 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -30,6 +30,13 @@ class CountedBrowserAccessibility : public BrowserAccessibility {
}
~CountedBrowserAccessibility() override { global_obj_count_--; }
+ // TODO: Existing cross-platform BrowserAccessibiltity hypertext tests rely on
+ // the default behavior of inner text. Since hypertext implementations are
+ // platform specific and are unavailable here, refactor tests which rely on
+ // GetHypertext (such as GetRootFrameHypertextRangeBoundsRect) as platform
+ // unit tests.
+ base::string16 GetHypertext() const override { return GetInnerText(); }
+
void NativeAddReference() override { native_ref_count_++; }
void NativeReleaseReference() override {
@@ -252,7 +259,7 @@ TEST_F(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) {
notification.updates.resize(1);
notification.updates[0].nodes.push_back(tree2_root);
notification.updates[0].nodes.push_back(tree2_child0);
- manager->OnAccessibilityEvents(notification);
+ ASSERT_TRUE(manager->OnAccessibilityEvents(notification));
// There should be 5 objects now: the 4 from the new tree, plus the
// reference to child3 we kept.
@@ -413,7 +420,7 @@ TEST_F(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
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);
+ ASSERT_TRUE(manager->OnAccessibilityEvents(notification));
// There should be 9 objects now: the 8 from the new tree, plus the
// reference to child3 we kept.
@@ -508,7 +515,7 @@ TEST_F(BrowserAccessibilityManagerTest, TestMoveChildUp) {
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);
+ ASSERT_TRUE(manager->OnAccessibilityEvents(notification));
// There should be 4 objects now.
EXPECT_EQ(4, CountedBrowserAccessibility::global_obj_count_);
@@ -635,37 +642,37 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRange) {
EXPECT_EQ(gfx::Rect(100, 100, 6, 9).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 1, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(100, 100, 26, 9).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 5, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(100, 109, 5, 9).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
7, 1, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(100, 109, 25, 9).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
7, 5, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(100, 100, 29, 18).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
5, 3, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(100, 100, 29, 18).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 13, ui::AXClippingBehavior::kUnclipped)
.ToString());
@@ -674,7 +681,7 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRange) {
// TODO(nektar): Investigate failure on Linux.
EXPECT_EQ(gfx::Rect(100, 100, 29, 18).ToString(),
root_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 13, ui::AXClippingBehavior::kUnclipped)
.ToString());
}
@@ -739,50 +746,50 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRangeMultiElement) {
// The first line.
EXPECT_EQ(gfx::Rect(0, 20, 33, 9).ToString(),
manager
- ->GetRootFrameRangeBoundsRect(*static_text_accessible, 0,
- *static_text_accessible, 3)
+ ->GetRootFrameInnerTextRangeBoundsRect(
+ *static_text_accessible, 0, *static_text_accessible, 3)
.ToString());
// Part of the first line.
EXPECT_EQ(gfx::Rect(0, 20, 21, 9).ToString(),
manager
- ->GetRootFrameRangeBoundsRect(*static_text_accessible, 0,
- *static_text_accessible, 2)
+ ->GetRootFrameInnerTextRangeBoundsRect(
+ *static_text_accessible, 0, *static_text_accessible, 2)
.ToString());
// Part of the first line.
EXPECT_EQ(gfx::Rect(10, 20, 23, 9).ToString(),
manager
- ->GetRootFrameRangeBoundsRect(*static_text_accessible, 1,
- *static_text_accessible, 3)
+ ->GetRootFrameInnerTextRangeBoundsRect(
+ *static_text_accessible, 1, *static_text_accessible, 3)
.ToString());
// The second line.
EXPECT_EQ(gfx::Rect(10, 40, 33, 9).ToString(),
manager
- ->GetRootFrameRangeBoundsRect(*static_text_accessible2, 0,
- *static_text_accessible2, 3)
+ ->GetRootFrameInnerTextRangeBoundsRect(
+ *static_text_accessible2, 0, *static_text_accessible2, 3)
.ToString());
// All of both lines.
EXPECT_EQ(gfx::Rect(0, 20, 43, 29).ToString(),
manager
- ->GetRootFrameRangeBoundsRect(*static_text_accessible, 0,
- *static_text_accessible2, 3)
+ ->GetRootFrameInnerTextRangeBoundsRect(
+ *static_text_accessible, 0, *static_text_accessible2, 3)
.ToString());
// Part of both lines.
EXPECT_EQ(gfx::Rect(10, 20, 23, 29).ToString(),
manager
- ->GetRootFrameRangeBoundsRect(*static_text_accessible, 2,
- *static_text_accessible2, 1)
+ ->GetRootFrameInnerTextRangeBoundsRect(
+ *static_text_accessible, 2, *static_text_accessible2, 1)
.ToString());
// Part of both lines in reverse order.
EXPECT_EQ(gfx::Rect(10, 20, 23, 29).ToString(),
manager
- ->GetRootFrameRangeBoundsRect(*static_text_accessible2, 1,
- *static_text_accessible, 2)
+ ->GetRootFrameInnerTextRangeBoundsRect(
+ *static_text_accessible2, 1, *static_text_accessible, 2)
.ToString());
}
@@ -850,31 +857,31 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRangeBiDi) {
EXPECT_EQ(gfx::Rect(100, 100, 60, 20).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 6, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(100, 100, 10, 20).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 1, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(100, 100, 30, 20).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 3, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(150, 100, 10, 20).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
3, 1, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(130, 100, 30, 20).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
3, 3, ui::AXClippingBehavior::kUnclipped)
.ToString());
@@ -882,7 +889,7 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRangeBiDi) {
// the bounds are as wide as four characters.
EXPECT_EQ(gfx::Rect(120, 100, 40, 20).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
2, 2, ui::AXClippingBehavior::kUnclipped)
.ToString());
}
@@ -931,13 +938,13 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRangeScrolledWindow) {
if (manager->UseRootScrollOffsetsWhenComputingBounds()) {
EXPECT_EQ(gfx::Rect(75, 50, 16, 9).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 3, ui::AXClippingBehavior::kUnclipped)
.ToString());
} else {
EXPECT_EQ(gfx::Rect(100, 100, 16, 9).ToString(),
static_text_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 3, ui::AXClippingBehavior::kUnclipped)
.ToString());
}
@@ -1015,37 +1022,37 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRangeOnParentElement) {
EXPECT_EQ(gfx::Rect(100, 100, 20, 20).ToString(),
div_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 1, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(100, 100, 40, 20).ToString(),
div_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 2, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(100, 100, 80, 20).ToString(),
div_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 4, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(120, 100, 60, 20).ToString(),
div_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
1, 3, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(120, 100, 80, 20).ToString(),
div_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
1, 4, ui::AXClippingBehavior::kUnclipped)
.ToString());
EXPECT_EQ(gfx::Rect(100, 100, 100, 20).ToString(),
div_accessible
- ->GetRootFrameRangeBoundsRect(
+ ->GetRootFrameHypertextRangeBoundsRect(
0, 5, ui::AXClippingBehavior::kUnclipped)
.ToString());
}
@@ -1582,8 +1589,9 @@ TEST_F(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash) {
initial_state, test_browser_accessibility_delegate_.get(),
new CountedBrowserAccessibilityFactory()));
- ASSERT_EQ(1, manager->GetRoot()->GetId());
- ASSERT_EQ(2, manager->GetFocus()->GetId());
+ EXPECT_EQ(1, manager->GetRoot()->GetId());
+ ASSERT_NE(nullptr, manager->GetFocus());
+ EXPECT_EQ(2, manager->GetFocus()->GetId());
// Now replace the tree with a new tree consisting of a single root.
ui::AXNodeData root2;
@@ -1593,12 +1601,13 @@ TEST_F(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash) {
AXEventNotificationDetails events2;
events2.updates.resize(1);
events2.updates[0] = MakeAXTreeUpdate(root2);
- manager->OnAccessibilityEvents(events2);
+ ASSERT_TRUE(manager->OnAccessibilityEvents(events2));
// Make sure that the focused node was updated to the new root and
// that this doesn't crash.
- ASSERT_EQ(3, manager->GetRoot()->GetId());
- ASSERT_EQ(3, manager->GetFocus()->GetId());
+ EXPECT_EQ(3, manager->GetRoot()->GetId());
+ ASSERT_NE(nullptr, manager->GetFocus());
+ EXPECT_EQ(3, manager->GetFocus()->GetId());
}
TEST_F(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash2) {
@@ -1627,8 +1636,9 @@ TEST_F(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash2) {
initial_state, test_browser_accessibility_delegate_.get(),
new CountedBrowserAccessibilityFactory()));
- ASSERT_EQ(1, manager->GetRoot()->GetId());
- ASSERT_EQ(2, manager->GetFocus()->GetId());
+ EXPECT_EQ(1, manager->GetRoot()->GetId());
+ ASSERT_NE(nullptr, manager->GetFocus());
+ EXPECT_EQ(2, manager->GetFocus()->GetId());
// Now replace the tree with a new tree consisting of a single root.
ui::AXNodeData root2;
@@ -1640,12 +1650,13 @@ TEST_F(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash2) {
events2.updates.resize(1);
events2.updates[0] = MakeAXTreeUpdate(root2);
events2.updates[0].node_id_to_clear = 1;
- manager->OnAccessibilityEvents(events2);
+ ASSERT_TRUE(manager->OnAccessibilityEvents(events2));
// Make sure that the focused node was updated to the new root and
// that this doesn't crash.
- ASSERT_EQ(3, manager->GetRoot()->GetId());
- ASSERT_EQ(3, manager->GetFocus()->GetId());
+ EXPECT_EQ(3, manager->GetRoot()->GetId());
+ ASSERT_NE(nullptr, manager->GetFocus());
+ EXPECT_EQ(3, manager->GetFocus()->GetId());
}
TEST_F(BrowserAccessibilityManagerTest, TreeUpdatesAreMergedWhenPossible) {
@@ -1683,7 +1694,7 @@ TEST_F(BrowserAccessibilityManagerTest, TreeUpdatesAreMergedWhenPossible) {
events.updates[0].nodes[0].role = ax::mojom::Role::kMenuItemCheckBox;
events.updates[1].nodes[0].role = ax::mojom::Role::kMenuItemRadio;
events.updates[2].nodes[0].role = ax::mojom::Role::kMenuItem;
- manager->OnAccessibilityEvents(events);
+ ASSERT_TRUE(manager->OnAccessibilityEvents(events));
// These should have been merged into a single tree update.
EXPECT_EQ(1, observer.update_count());
@@ -1696,5 +1707,4 @@ TEST_F(BrowserAccessibilityManagerTest, TreeUpdatesAreMergedWhenPossible) {
// Remove the observer before the manager is destroyed.
manager->ax_tree()->RemoveObserver(&observer);
}
-
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
index 630884d8a3c..19fb7349481 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -89,7 +89,7 @@ void BrowserAccessibilityManagerWin::UserIsReloading() {
FireWinAccessibilityEvent(IA2_EVENT_DOCUMENT_RELOAD, GetRoot());
}
-BrowserAccessibility* BrowserAccessibilityManagerWin::GetFocus() {
+BrowserAccessibility* BrowserAccessibilityManagerWin::GetFocus() const {
BrowserAccessibility* focus = BrowserAccessibilityManager::GetFocus();
return GetActiveDescendant(focus);
}
@@ -98,10 +98,6 @@ void BrowserAccessibilityManagerWin::FireFocusEvent(
BrowserAccessibility* node) {
BrowserAccessibilityManager::FireFocusEvent(node);
DCHECK(node);
-
- if (node->GetRole() == ax::mojom::Role::kMenu)
- FireUiaAccessibilityEvent(UIA_MenuOpenedEventId, node);
-
FireWinAccessibilityEvent(EVENT_OBJECT_FOCUS, node);
FireUiaAccessibilityEvent(UIA_AutomationFocusChangedEventId, node);
}
@@ -182,8 +178,13 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
FireWinAccessibilityEvent(EVENT_SYSTEM_ALERT, node);
FireUiaAccessibilityEvent(UIA_SystemAlertEventId, node);
break;
+ case ui::AXEventGenerator::Event::ATOMIC_CHANGED:
+ case ui::AXEventGenerator::Event::BUSY_CHANGED:
+ aria_properties_events_.insert(node);
+ break;
case ui::AXEventGenerator::Event::CHECKED_STATE_CHANGED:
FireUiaPropertyChangedEvent(UIA_ToggleToggleStatePropertyId, node);
+ aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::CHILDREN_CHANGED:
FireWinAccessibilityEvent(EVENT_OBJECT_REORDER, node);
@@ -196,6 +197,7 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
case ui::AXEventGenerator::Event::EXPANDED:
FireUiaPropertyChangedEvent(
UIA_ExpandCollapseExpandCollapseStatePropertyId, node);
+ aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::CONTROLS_CHANGED:
FireUiaPropertyChangedEvent(UIA_ControllerForPropertyId, node);
@@ -214,8 +216,13 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
FireWinAccessibilityEvent(IA2_EVENT_TEXT_CARET_MOVED, focus_object);
break;
}
+ // aria-dropeffect is deprecated in WAI-ARIA 1.1.
+ case ui::AXEventGenerator::Event::DROPEFFECT_CHANGED:
+ aria_properties_events_.insert(node);
+ break;
case ui::AXEventGenerator::Event::ENABLED_CHANGED:
FireUiaPropertyChangedEvent(UIA_IsEnabledPropertyId, node);
+ aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::FLOW_FROM_CHANGED:
FireUiaPropertyChangedEvent(UIA_FlowsFromPropertyId, node);
@@ -223,14 +230,21 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
FireUiaPropertyChangedEvent(UIA_FlowsToPropertyId, node);
break;
+ // aria-grabbed is deprecated in WAI-ARIA 1.1.
+ case ui::AXEventGenerator::Event::GRABBED_CHANGED:
+ case ui::AXEventGenerator::Event::HASPOPUP_CHANGED:
+ aria_properties_events_.insert(node);
+ break;
case ui::AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
FireUiaPropertyChangedEvent(UIA_LevelPropertyId, node);
+ aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
FireWinAccessibilityEvent(EVENT_OBJECT_NAMECHANGE, node);
break;
case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
FireUiaPropertyChangedEvent(UIA_IsDataValidForFormPropertyId, node);
+ aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::KEY_SHORTCUTS_CHANGED:
FireUiaPropertyChangedEvent(UIA_AcceleratorKeyPropertyId, node);
@@ -242,7 +256,7 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
FireUiaPropertyChangedEvent(UIA_CulturePropertyId, node);
break;
case ui::AXEventGenerator::Event::LIVE_REGION_CREATED:
- FireUiaPropertyChangedEvent(UIA_LiveSettingPropertyId, node);
+ FireUiaAccessibilityEvent(UIA_LiveRegionChangedEventId, node);
break;
case ui::AXEventGenerator::Event::LIVE_REGION_CHANGED:
// This event is redundant with the IA2_EVENT_TEXT_INSERTED events;
@@ -257,6 +271,11 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
// Firefox live region events differently (utilizes MSAA's
// EVENT_OBJECT_SHOW).
FireWinAccessibilityEvent(EVENT_OBJECT_LIVEREGIONCHANGED, node);
+ FireUiaAccessibilityEvent(UIA_LiveRegionChangedEventId, node);
+ break;
+ case ui::AXEventGenerator::Event::LIVE_STATUS_CHANGED:
+ FireUiaPropertyChangedEvent(UIA_LiveSettingPropertyId, node);
+ aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::LOAD_COMPLETE:
FireWinAccessibilityEvent(IA2_EVENT_DOCUMENT_LOAD_COMPLETE, node);
@@ -264,9 +283,14 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
case ui::AXEventGenerator::Event::LAYOUT_INVALIDATED:
FireUiaAccessibilityEvent(UIA_LayoutInvalidatedEventId, node);
break;
+ case ui::AXEventGenerator::Event::LIVE_RELEVANT_CHANGED:
+ case ui::AXEventGenerator::Event::MULTILINE_STATE_CHANGED:
+ aria_properties_events_.insert(node);
+ break;
case ui::AXEventGenerator::Event::MULTISELECTABLE_STATE_CHANGED:
FireUiaPropertyChangedEvent(UIA_SelectionCanSelectMultiplePropertyId,
node);
+ aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::NAME_CHANGED:
FireUiaPropertyChangedEvent(UIA_NamePropertyId, node);
@@ -276,15 +300,18 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
break;
case ui::AXEventGenerator::Event::POSITION_IN_SET_CHANGED:
FireUiaPropertyChangedEvent(UIA_PositionInSetPropertyId, node);
+ aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::READONLY_CHANGED:
if (ui::IsRangeValueSupported(node->GetData()))
FireUiaPropertyChangedEvent(UIA_RangeValueIsReadOnlyPropertyId, node);
else if (ui::IsValuePatternSupported(node))
FireUiaPropertyChangedEvent(UIA_ValueIsReadOnlyPropertyId, node);
+ aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::REQUIRED_STATE_CHANGED:
FireUiaPropertyChangedEvent(UIA_IsRequiredForFormPropertyId, node);
+ aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::ROLE_CHANGED:
FireUiaPropertyChangedEvent(UIA_AriaRolePropertyId, node);
@@ -301,12 +328,17 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
break;
case ui::AXEventGenerator::Event::SELECTED_CHANGED:
HandleSelectedStateChanged(node);
+ aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::SELECTED_CHILDREN_CHANGED:
FireWinAccessibilityEvent(EVENT_OBJECT_SELECTIONWITHIN, node);
break;
case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
FireUiaPropertyChangedEvent(UIA_SizeOfSetPropertyId, node);
+ aria_properties_events_.insert(node);
+ break;
+ case ui::AXEventGenerator::Event::SORT_CHANGED:
+ aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::SUBTREE_CREATED:
FireWinAccessibilityEvent(EVENT_OBJECT_SHOW, node);
@@ -314,18 +346,24 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
break;
case ui::AXEventGenerator::Event::VALUE_CHANGED:
FireWinAccessibilityEvent(EVENT_OBJECT_VALUECHANGE, node);
- if (ui::IsRangeValueSupported(node->GetData()))
+ if (ui::IsRangeValueSupported(node->GetData())) {
FireUiaPropertyChangedEvent(UIA_RangeValueValuePropertyId, node);
- else if (ui::IsValuePatternSupported(node))
+ aria_properties_events_.insert(node);
+ } else if (ui::IsValuePatternSupported(node)) {
FireUiaPropertyChangedEvent(UIA_ValueValuePropertyId, node);
+ }
break;
case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
- if (IsRangeValueSupported(node->GetData()))
+ if (IsRangeValueSupported(node->GetData())) {
FireUiaPropertyChangedEvent(UIA_RangeValueMaximumPropertyId, node);
+ aria_properties_events_.insert(node);
+ }
break;
case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
- if (IsRangeValueSupported(node->GetData()))
+ if (IsRangeValueSupported(node->GetData())) {
FireUiaPropertyChangedEvent(UIA_RangeValueMinimumPropertyId, node);
+ aria_properties_events_.insert(node);
+ }
break;
case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
if (IsRangeValueSupported(node->GetData())) {
@@ -460,7 +498,7 @@ void BrowserAccessibilityManagerWin::FireUiaTextContainerEvent(
}
}
-bool BrowserAccessibilityManagerWin::CanFireEvents() {
+bool BrowserAccessibilityManagerWin::CanFireEvents() const {
if (!BrowserAccessibilityManager::CanFireEvents())
return false;
BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager();
@@ -580,7 +618,7 @@ void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(
}
bool BrowserAccessibilityManagerWin::ShouldFireEventForNode(
- BrowserAccessibility* node) {
+ BrowserAccessibility* node) const {
if (!node || !node->CanFireEvents())
return false;
@@ -620,12 +658,12 @@ void BrowserAccessibilityManagerWin::HandleSelectedStateChanged(
if (multiselect) {
if (is_selected) {
FireWinAccessibilityEvent(EVENT_OBJECT_SELECTIONADD, node);
- FireUiaAccessibilityEvent(
- UIA_SelectionItem_ElementAddedToSelectionEventId, node);
+ if (::switches::IsExperimentalAccessibilityPlatformUIAEnabled())
+ selection_events_[selection_container].added.push_back(node);
} else {
FireWinAccessibilityEvent(EVENT_OBJECT_SELECTIONREMOVE, node);
- FireUiaAccessibilityEvent(
- UIA_SelectionItem_ElementRemovedFromSelectionEventId, node);
+ if (::switches::IsExperimentalAccessibilityPlatformUIAEnabled())
+ selection_events_[selection_container].removed.push_back(node);
}
} else if (is_selected) {
FireWinAccessibilityEvent(EVENT_OBJECT_SELECTION, node);
@@ -633,4 +671,57 @@ void BrowserAccessibilityManagerWin::HandleSelectedStateChanged(
}
}
+void BrowserAccessibilityManagerWin::FinalizeAccessibilityEvents() {
+ BrowserAccessibilityManager::FinalizeAccessibilityEvents();
+
+ for (auto&& event_node : aria_properties_events_) {
+ FireUiaPropertyChangedEvent(UIA_AriaPropertiesPropertyId, event_node);
+ }
+ aria_properties_events_.clear();
+
+ for (auto&& selected : selection_events_) {
+ auto* container = selected.first;
+ auto&& changes = selected.second;
+
+ // Count the number of selected items
+ size_t selected_count = 0;
+ BrowserAccessibility* first_selected_child = nullptr;
+ for (size_t i = 0; i < container->InternalChildCount(); ++i) {
+ auto* child = container->InternalGetChild(i);
+ if (child->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected)) {
+ if (!first_selected_child)
+ first_selected_child = child;
+ selected_count++;
+ }
+ }
+
+ if (selected_count == 1) {
+ // Fire 'ElementSelected' on the only selected child
+ FireUiaAccessibilityEvent(UIA_SelectionItem_ElementSelectedEventId,
+ first_selected_child);
+ } else {
+ // Per UIA documentation, beyond the "invalidate limit" we're supposed to
+ // fire a 'SelectionInvalidated' event. The exact value isn't specified,
+ // but System.Windows.Automation.Provider uses a value of 20.
+ static const size_t kInvalidateLimit = 20;
+ if ((changes.added.size() + changes.removed.size()) > kInvalidateLimit) {
+ FireUiaAccessibilityEvent(UIA_Selection_InvalidatedEventId, container);
+ } else {
+ for (auto* item : changes.added) {
+ FireUiaAccessibilityEvent(
+ UIA_SelectionItem_ElementAddedToSelectionEventId, item);
+ }
+ for (auto* item : changes.removed) {
+ FireUiaAccessibilityEvent(
+ UIA_SelectionItem_ElementRemovedFromSelectionEventId, item);
+ }
+ }
+ }
+ }
+ selection_events_.clear();
+}
+
+BrowserAccessibilityManagerWin::SelectionEvents::SelectionEvents() = default;
+BrowserAccessibilityManagerWin::SelectionEvents::~SelectionEvents() = default;
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
index 3ce68d44164..a1b5f0aa340 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -7,7 +7,10 @@
#include <oleacc.h>
+#include <map>
#include <memory>
+#include <unordered_set>
+#include <vector>
#include "base/macros.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
@@ -45,8 +48,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// BrowserAccessibilityManager methods
void UserIsReloading() override;
- BrowserAccessibility* GetFocus() override;
- bool CanFireEvents() override;
+ BrowserAccessibility* GetFocus() const override;
+ bool CanFireEvents() const override;
gfx::Rect GetViewBounds() override;
void FireFocusEvent(BrowserAccessibility* node) override;
@@ -65,6 +68,9 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
BrowserAccessibility* node);
void FireUiaTextContainerEvent(LONG uia_event, BrowserAccessibility* node);
+ // Do event post-processing
+ void FinalizeAccessibilityEvents() override;
+
// Track this object and post a VISIBLE_DATA_CHANGED notification when
// its container scrolls.
// TODO(dmazzoni): remove once http://crbug.com/113483 is fixed.
@@ -80,7 +86,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
bool root_changed,
const std::vector<ui::AXTreeObserver::Change>& changes) override;
- bool ShouldFireEventForNode(BrowserAccessibility* node);
+ bool ShouldFireEventForNode(BrowserAccessibility* node) const;
private:
void HandleSelectedStateChanged(BrowserAccessibility* node);
@@ -94,6 +100,23 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// http://crbug.com/521877
bool load_complete_pending_;
+ // Since there could be multiple aria property changes on a node and we only
+ // want to fire UIA_AriaPropertiesPropertyId once for that node, we use the
+ // unordered set here to keep track of the unique nodes that had aria property
+ // changes, so we only fire the event once for every node.
+ std::unordered_set<BrowserAccessibility*> aria_properties_events_;
+
+ // Keep track of selection changes so we can optimize UIA event firing.
+ // Pointers are only stored for the duration of |OnAccessibilityEvents|, and
+ // the map is cleared in |FinalizeAccessibilityEvents|.
+ struct SelectionEvents {
+ std::vector<BrowserAccessibility*> added;
+ std::vector<BrowserAccessibility*> removed;
+ SelectionEvents();
+ ~SelectionEvents();
+ };
+ std::map<BrowserAccessibility*, SelectionEvents> selection_events_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerWin);
};
diff --git a/chromium/content/browser/accessibility/browser_accessibility_position.cc b/chromium/content/browser/accessibility/browser_accessibility_position.cc
index 9eedf6d9aec..0f556f1fd48 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_position.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_position.cc
@@ -22,7 +22,7 @@ BrowserAccessibilityPosition::Clone() const {
return AXPositionInstance(new BrowserAccessibilityPosition(*this));
}
-base::string16 BrowserAccessibilityPosition::GetInnerText() const {
+base::string16 BrowserAccessibilityPosition::GetText() const {
if (IsNullPosition())
return base::string16();
DCHECK(GetAnchor());
@@ -64,10 +64,21 @@ int BrowserAccessibilityPosition::AnchorChildCount() const {
}
int BrowserAccessibilityPosition::AnchorIndexInParent() const {
- return GetAnchor() ? static_cast<int>(GetAnchor()->GetIndexInParent())
+ return GetAnchor() ? GetAnchor()->GetIndexInParent()
: AXPosition::INVALID_INDEX;
}
+base::stack<BrowserAccessibility*>
+BrowserAccessibilityPosition::GetAncestorAnchors() const {
+ base::stack<BrowserAccessibility*> anchors;
+ BrowserAccessibility* current_anchor = GetAnchor();
+ while (current_anchor) {
+ anchors.push(current_anchor);
+ current_anchor = current_anchor->PlatformGetParent();
+ }
+ return anchors;
+}
+
void BrowserAccessibilityPosition::AnchorParent(AXTreeID* tree_id,
int32_t* parent_id) const {
DCHECK(tree_id);
@@ -123,7 +134,7 @@ bool BrowserAccessibilityPosition::IsInWhiteSpace() const {
DCHECK(GetAnchor());
return GetAnchor()->IsLineBreakObject() ||
- base::ContainsOnlyChars(GetInnerText(), base::kWhitespaceUTF16);
+ base::ContainsOnlyChars(GetText(), base::kWhitespaceUTF16);
}
std::vector<int32_t> BrowserAccessibilityPosition::GetWordStartOffsets() const {
diff --git a/chromium/content/browser/accessibility/browser_accessibility_position.h b/chromium/content/browser/accessibility/browser_accessibility_position.h
index 1cdfb286bbb..e7228502158 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_position.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_position.h
@@ -29,7 +29,7 @@ class CONTENT_EXPORT BrowserAccessibilityPosition
AXPositionInstance Clone() const override;
- base::string16 GetInnerText() const override;
+ base::string16 GetText() const override;
protected:
BrowserAccessibilityPosition(const BrowserAccessibilityPosition& other) =
@@ -39,6 +39,7 @@ class CONTENT_EXPORT BrowserAccessibilityPosition
int32_t* child_id) const override;
int AnchorChildCount() const override;
int AnchorIndexInParent() const override;
+ base::stack<BrowserAccessibility*> GetAncestorAnchors() const override;
void AnchorParent(AXTreeID* tree_id, int32_t* parent_id) const override;
BrowserAccessibility* GetNodeInTree(AXTreeID tree_id,
int32_t node_id) const override;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
index cbb9640c0b5..6a8924bc338 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -184,7 +184,7 @@ void BrowserAccessibilityStateImpl::OnAXModeAdded(ui::AXMode mode) {
AddAccessibilityModeFlags(mode);
}
-ui::AXMode BrowserAccessibilityStateImpl::GetAccessibilityMode() const {
+ui::AXMode BrowserAccessibilityStateImpl::GetAccessibilityMode() {
return accessibility_mode_;
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.h b/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
index 2af968c58e0..6c60116eee3 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
@@ -51,7 +51,7 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
void EnableAccessibility() override;
void DisableAccessibility() override;
bool IsRendererAccessibilityEnabled() override;
- ui::AXMode GetAccessibilityMode() const override;
+ ui::AXMode GetAccessibilityMode() override;
void AddAccessibilityModeFlags(ui::AXMode mode) override;
void RemoveAccessibilityModeFlags(ui::AXMode mode) override;
void ResetAccessibilityMode() override;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm
index e91b463fa69..8fee8718297 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm
@@ -31,25 +31,23 @@ void SetupAccessibilityDisplayOptionsNotifier() {
// so ensure that we setup the notification on the correct thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (@available(macOS 10.10, *)) {
- // Listen to accessibility display options changing, so that we can update
- // the renderer for the prefers reduced motion settings.
- //
- // BrowserAccessibilityStateImpl is a deliberately leaked singleton, so we
- // don't need to record the notification token for later cleanup.
- [[[NSWorkspace sharedWorkspace] notificationCenter]
- addObserverForName:
- NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification
- object:nil
- queue:nil
- usingBlock:^(NSNotification* notification) {
- gfx::Animation::UpdatePrefersReducedMotion();
- for (WebContentsImpl* wc :
- WebContentsImpl::GetAllWebContents()) {
- wc->GetRenderViewHost()->OnWebkitPreferencesChanged();
- }
- }];
- }
+ // Listen to accessibility display options changing, so that we can update
+ // the renderer for the prefers reduced motion settings.
+ //
+ // BrowserAccessibilityStateImpl is a deliberately leaked singleton, so we
+ // don't need to record the notification token for later cleanup.
+ [[[NSWorkspace sharedWorkspace] notificationCenter]
+ addObserverForName:
+ NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification
+ object:nil
+ queue:nil
+ usingBlock:^(NSNotification* notification) {
+ gfx::Animation::UpdatePrefersReducedMotion();
+ for (WebContentsImpl* wc :
+ WebContentsImpl::GetAllWebContents()) {
+ wc->GetRenderViewHost()->OnWebkitPreferencesChanged();
+ }
+ }];
}
} // namespace
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
index 2c66497e658..c311f31794c 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
@@ -148,7 +148,8 @@ void BrowserAccessibilityStateImpl::
base::string16 module_name(base::FilePath(filename).BaseName().value());
if (base::LowerCaseEqualsASCII(module_name, "fsdomsrv.dll"))
jaws = true;
- if (base::LowerCaseEqualsASCII(module_name, "vbufbackend_gecko_ia2.dll"))
+ if (base::LowerCaseEqualsASCII(module_name, "vbufbackend_gecko_ia2.dll") ||
+ base::LowerCaseEqualsASCII(module_name, "nvdahelperremote.dll"))
nvda = true;
if (base::LowerCaseEqualsASCII(module_name, "stsaw32.dll"))
satogo = true;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_unittest.cc
index d070c069c87..873b961a61f 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_unittest.cc
@@ -175,4 +175,432 @@ TEST_F(BrowserAccessibilityTest, TestGetDescendants) {
}
#endif // defined(OS_WIN) || BUILDFLAG(USE_ATK)
+TEST_F(BrowserAccessibilityTest, GetInnerTextRangeBoundsRect) {
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.relative_bounds.bounds = gfx::RectF(0, 0, 800, 600);
+
+ ui::AXNodeData static_text;
+ static_text.id = 2;
+ static_text.SetName("Hello, world.");
+ static_text.role = ax::mojom::Role::kStaticText;
+ static_text.relative_bounds.bounds = gfx::RectF(100, 100, 29, 18);
+ root.child_ids.push_back(2);
+
+ ui::AXNodeData inline_text1;
+ inline_text1.id = 3;
+ inline_text1.SetName("Hello, ");
+ inline_text1.role = ax::mojom::Role::kInlineTextBox;
+ inline_text1.relative_bounds.bounds = gfx::RectF(100, 100, 29, 9);
+ inline_text1.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ std::vector<int32_t> character_offsets1;
+ character_offsets1.push_back(6);
+ character_offsets1.push_back(11);
+ character_offsets1.push_back(16);
+ character_offsets1.push_back(21);
+ character_offsets1.push_back(26);
+ character_offsets1.push_back(29);
+ character_offsets1.push_back(29);
+ inline_text1.AddIntListAttribute(
+ ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets1);
+ static_text.child_ids.push_back(3);
+
+ ui::AXNodeData inline_text2;
+ inline_text2.id = 4;
+ inline_text2.SetName("world.");
+ inline_text2.role = ax::mojom::Role::kInlineTextBox;
+ inline_text2.relative_bounds.bounds = gfx::RectF(100, 109, 28, 9);
+ inline_text2.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ std::vector<int32_t> character_offsets2;
+ character_offsets2.push_back(5);
+ character_offsets2.push_back(10);
+ character_offsets2.push_back(15);
+ character_offsets2.push_back(20);
+ character_offsets2.push_back(25);
+ character_offsets2.push_back(28);
+ inline_text2.AddIntListAttribute(
+ ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets2);
+ static_text.child_ids.push_back(4);
+
+ std::unique_ptr<BrowserAccessibilityManager> browser_accessibility_manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(root, static_text, inline_text1, inline_text2),
+ test_browser_accessibility_delegate_.get(),
+ new BrowserAccessibilityFactory()));
+
+ BrowserAccessibility* root_accessible =
+ browser_accessibility_manager->GetRoot();
+ ASSERT_NE(nullptr, root_accessible);
+ BrowserAccessibility* static_text_accessible =
+ root_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, static_text_accessible);
+
+#ifdef OS_ANDROID
+ // Android disallows getting inner text from root accessibility nodes.
+ EXPECT_EQ(gfx::Rect(0, 0, 0, 0).ToString(),
+ root_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 1, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+#else
+ // Validate the bounding box of 'H' from root.
+ EXPECT_EQ(gfx::Rect(100, 100, 6, 9).ToString(),
+ root_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 1, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+#endif
+
+ // Validate the bounding box of 'H' from static text.
+ EXPECT_EQ(gfx::Rect(100, 100, 6, 9).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 1, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+ // Validate the bounding box of 'Hello' from static text.
+ EXPECT_EQ(gfx::Rect(100, 100, 26, 9).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 5, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+ // Validate the bounding box of 'Hello, world.' from static text.
+ EXPECT_EQ(gfx::Rect(100, 100, 29, 18).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 13, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+#ifdef OS_ANDROID
+ // Android disallows getting inner text from root accessibility nodes.
+ EXPECT_EQ(gfx::Rect(0, 0, 0, 0).ToString(),
+ root_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 13, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+#else
+ // Validate the bounding box of 'Hello, world.' from root.
+ EXPECT_EQ(gfx::Rect(100, 100, 29, 18).ToString(),
+ root_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 13, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+#endif
+}
+
+TEST_F(BrowserAccessibilityTest, GetInnerTextRangeBoundsRectMultiElement) {
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.relative_bounds.bounds = gfx::RectF(0, 0, 800, 600);
+
+ ui::AXNodeData static_text;
+ static_text.id = 2;
+ static_text.SetName("ABC");
+ static_text.role = ax::mojom::Role::kStaticText;
+ static_text.relative_bounds.bounds = gfx::RectF(0, 20, 33, 9);
+ root.child_ids.push_back(2);
+
+ ui::AXNodeData inline_text1;
+ inline_text1.id = 3;
+ inline_text1.SetName("ABC");
+ inline_text1.role = ax::mojom::Role::kInlineTextBox;
+ inline_text1.relative_bounds.bounds = gfx::RectF(0, 20, 33, 9);
+ inline_text1.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ std::vector<int32_t> character_offsets{10, 21, 33};
+ inline_text1.AddIntListAttribute(
+ ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets);
+ static_text.child_ids.push_back(3);
+
+ ui::AXNodeData static_text2;
+ static_text2.id = 4;
+ static_text2.SetName("ABC");
+ static_text2.role = ax::mojom::Role::kStaticText;
+ static_text2.relative_bounds.bounds = gfx::RectF(10, 40, 33, 9);
+ root.child_ids.push_back(4);
+
+ ui::AXNodeData inline_text2;
+ inline_text2.id = 5;
+ inline_text2.SetName("ABC");
+ inline_text2.role = ax::mojom::Role::kInlineTextBox;
+ inline_text2.relative_bounds.bounds = gfx::RectF(10, 40, 33, 9);
+ inline_text2.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text2.AddIntListAttribute(
+ ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets);
+ static_text2.child_ids.push_back(5);
+
+ std::unique_ptr<BrowserAccessibilityManager> browser_accessibility_manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(root, static_text, inline_text1, static_text2,
+ inline_text2),
+ test_browser_accessibility_delegate_.get(),
+ new BrowserAccessibilityFactory()));
+
+ BrowserAccessibility* root_accessible =
+ browser_accessibility_manager->GetRoot();
+ ASSERT_NE(nullptr, root_accessible);
+ BrowserAccessibility* static_text_accessible =
+ root_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, static_text_accessible);
+ BrowserAccessibility* static_text_accessible2 =
+ root_accessible->PlatformGetChild(1);
+ ASSERT_NE(nullptr, static_text_accessible);
+
+ // Validate the bounds of 'ABC' on the first line.
+ EXPECT_EQ(gfx::Rect(0, 20, 33, 9).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 3, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+ // Validate the bounds of only 'AB' on the first line.
+ EXPECT_EQ(gfx::Rect(0, 20, 21, 9).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 2, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+ // Validate the bounds of only 'BC' on the first line.
+ EXPECT_EQ(gfx::Rect(10, 20, 23, 9).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 1, 3, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+ // Validate the bounds of 'ABC' on the second line.
+ EXPECT_EQ(gfx::Rect(10, 40, 33, 9).ToString(),
+ static_text_accessible2
+ ->GetInnerTextRangeBoundsRect(
+ 0, 3, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+#ifdef OS_ANDROID
+ // Android disallows getting inner text from accessibility root nodes.
+ EXPECT_EQ(gfx::Rect(0, 0, 0, 0).ToString(),
+ root_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 6, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+ // Android disallows getting inner text from accessibility root nodes.
+ EXPECT_EQ(gfx::Rect(0, 0, 0, 0).ToString(),
+ root_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 2, 4, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+#else
+ // Validate the bounds of 'ABCABC' from both lines.
+ EXPECT_EQ(gfx::Rect(0, 20, 43, 29).ToString(),
+ root_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 6, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+ // Validate the bounds of 'CA' from both lines.
+ EXPECT_EQ(gfx::Rect(10, 20, 23, 29).ToString(),
+ root_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 2, 4, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+#endif
+}
+
+TEST_F(BrowserAccessibilityTest, GetInnerTextRangeBoundsRectBiDi) {
+ // In this example, we assume that the string "123abc" is rendered with "123"
+ // going left-to-right and "abc" going right-to-left. In other words,
+ // on-screen it would look like "123cba".
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.relative_bounds.bounds = gfx::RectF(0, 0, 800, 600);
+
+ ui::AXNodeData static_text;
+ static_text.id = 2;
+ static_text.SetName("123abc");
+ static_text.role = ax::mojom::Role::kStaticText;
+ static_text.relative_bounds.bounds = gfx::RectF(100, 100, 60, 20);
+ root.child_ids.push_back(2);
+
+ ui::AXNodeData inline_text1;
+ inline_text1.id = 3;
+ inline_text1.SetName("123");
+ inline_text1.role = ax::mojom::Role::kInlineTextBox;
+ inline_text1.relative_bounds.bounds = gfx::RectF(100, 100, 30, 20);
+ inline_text1.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ std::vector<int32_t> character_offsets1;
+ character_offsets1.push_back(10); // 0
+ character_offsets1.push_back(20); // 1
+ character_offsets1.push_back(30); // 2
+ inline_text1.AddIntListAttribute(
+ ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets1);
+ static_text.child_ids.push_back(3);
+
+ ui::AXNodeData inline_text2;
+ inline_text2.id = 4;
+ inline_text2.SetName("abc");
+ inline_text2.role = ax::mojom::Role::kInlineTextBox;
+ inline_text2.relative_bounds.bounds = gfx::RectF(130, 100, 30, 20);
+ inline_text2.SetTextDirection(ax::mojom::TextDirection::kRtl);
+ std::vector<int32_t> character_offsets2;
+ character_offsets2.push_back(10);
+ character_offsets2.push_back(20);
+ character_offsets2.push_back(30);
+ inline_text2.AddIntListAttribute(
+ ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets2);
+ static_text.child_ids.push_back(4);
+
+ std::unique_ptr<BrowserAccessibilityManager> browser_accessibility_manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(root, static_text, inline_text1, inline_text2),
+ test_browser_accessibility_delegate_.get(),
+ new BrowserAccessibilityFactory()));
+
+ BrowserAccessibility* root_accessible =
+ browser_accessibility_manager->GetRoot();
+ ASSERT_NE(nullptr, root_accessible);
+ BrowserAccessibility* static_text_accessible =
+ root_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, static_text_accessible);
+
+ EXPECT_EQ(gfx::Rect(100, 100, 60, 20).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 6, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+ EXPECT_EQ(gfx::Rect(100, 100, 10, 20).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 1, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+ EXPECT_EQ(gfx::Rect(100, 100, 30, 20).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 3, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+ EXPECT_EQ(gfx::Rect(150, 100, 10, 20).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 3, 4, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+ EXPECT_EQ(gfx::Rect(130, 100, 30, 20).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 3, 6, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+
+ // This range is only two characters, but because of the direction switch
+ // the bounds are as wide as four characters.
+ EXPECT_EQ(gfx::Rect(120, 100, 40, 20).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 2, 4, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+}
+
+TEST_F(BrowserAccessibilityTest, GetInnerTextRangeBoundsRectScrolledWindow) {
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.AddIntAttribute(ax::mojom::IntAttribute::kScrollX, 25);
+ root.AddIntAttribute(ax::mojom::IntAttribute::kScrollY, 50);
+ root.relative_bounds.bounds = gfx::RectF(0, 0, 800, 600);
+
+ ui::AXNodeData static_text;
+ static_text.id = 2;
+ static_text.SetName("ABC");
+ static_text.role = ax::mojom::Role::kStaticText;
+ static_text.relative_bounds.bounds = gfx::RectF(100, 100, 16, 9);
+ root.child_ids.push_back(2);
+
+ ui::AXNodeData inline_text;
+ inline_text.id = 3;
+ inline_text.SetName("ABC");
+ inline_text.role = ax::mojom::Role::kInlineTextBox;
+ inline_text.relative_bounds.bounds = gfx::RectF(100, 100, 16, 9);
+ inline_text.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ std::vector<int32_t> character_offsets1;
+ character_offsets1.push_back(6); // 0
+ character_offsets1.push_back(11); // 1
+ character_offsets1.push_back(16); // 2
+ inline_text.AddIntListAttribute(
+ ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets1);
+ static_text.child_ids.push_back(3);
+
+ std::unique_ptr<BrowserAccessibilityManager> browser_accessibility_manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(root, static_text, inline_text),
+ test_browser_accessibility_delegate_.get(),
+ new BrowserAccessibilityFactory()));
+
+ BrowserAccessibility* root_accessible =
+ browser_accessibility_manager->GetRoot();
+ ASSERT_NE(nullptr, root_accessible);
+ BrowserAccessibility* static_text_accessible =
+ root_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, static_text_accessible);
+
+ if (browser_accessibility_manager
+ ->UseRootScrollOffsetsWhenComputingBounds()) {
+ EXPECT_EQ(gfx::Rect(75, 50, 16, 9).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 3, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+ } else {
+ EXPECT_EQ(gfx::Rect(100, 100, 16, 9).ToString(),
+ static_text_accessible
+ ->GetInnerTextRangeBoundsRect(
+ 0, 3, ui::AXCoordinateSystem::kRootFrame,
+ ui::AXClippingBehavior::kUnclipped)
+ .ToString());
+ }
+}
+
+TEST_F(BrowserAccessibilityTest, GetAuthorUniqueId) {
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.html_attributes.push_back(std::make_pair("id", "my_html_id"));
+
+ std::unique_ptr<BrowserAccessibilityManager> browser_accessibility_manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(root), test_browser_accessibility_delegate_.get(),
+ new BrowserAccessibilityFactory()));
+ ASSERT_NE(nullptr, browser_accessibility_manager.get());
+
+ BrowserAccessibility* root_accessible =
+ browser_accessibility_manager->GetRoot();
+ ASSERT_NE(nullptr, root_accessible);
+
+ ASSERT_EQ(base::WideToUTF16(L"my_html_id"),
+ root_accessible->GetAuthorUniqueId());
+}
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.cc b/chromium/content/browser/accessibility/browser_accessibility_win.cc
index db85c277c5a..e2c2d9041f0 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.cc
@@ -49,7 +49,11 @@ void BrowserAccessibilityWin::OnLocationChanged() {
}
base::string16 BrowserAccessibilityWin::GetText() const {
- return GetCOM()->AXPlatformNodeWin::GetText();
+ return GetHypertext();
+}
+
+base::string16 BrowserAccessibilityWin::GetHypertext() const {
+ return GetCOM()->AXPlatformNodeWin::GetHypertext();
}
gfx::NativeViewAccessible BrowserAccessibilityWin::GetNativeViewAccessible() {
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.h b/chromium/content/browser/accessibility/browser_accessibility_win.h
index 07a7c4db8e0..955c88de7d3 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.h
@@ -28,6 +28,7 @@ class CONTENT_EXPORT BrowserAccessibilityWin : public BrowserAccessibility {
bool IsNative() const override;
void OnLocationChanged() override;
base::string16 GetText() const override;
+ base::string16 GetHypertext() const override;
gfx::NativeViewAccessible GetNativeViewAccessible() override;
ui::AXPlatformNode* GetFromNodeID(int32_t id) override;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
index e82634e2140..0d9d1ef8fbe 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -179,7 +179,7 @@ TEST_F(BrowserAccessibilityWinTest, TestChildrenChange) {
AXEventNotificationDetails event_bundle;
event_bundle.updates.resize(1);
event_bundle.updates[0].nodes.push_back(text2);
- manager->OnAccessibilityEvents(event_bundle);
+ ASSERT_TRUE(manager->OnAccessibilityEvents(event_bundle));
// Query for the text IAccessible and verify that it now returns "new text"
// as its value.
@@ -243,7 +243,7 @@ TEST_F(BrowserAccessibilityWinTest, TestChildrenChangeNoLeaks) {
AXEventNotificationDetails event_bundle;
event_bundle.updates.resize(1);
event_bundle.updates[0].nodes.push_back(root);
- manager->OnAccessibilityEvents(event_bundle);
+ ASSERT_TRUE(manager->OnAccessibilityEvents(event_bundle));
// Delete the manager and test that all BrowserAccessibility instances are
// deleted.
@@ -677,7 +677,7 @@ TEST_F(BrowserAccessibilityWinTest, TestCreateEmptyDocument) {
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);
+ ASSERT_TRUE(manager->OnAccessibilityEvents(event_bundle));
// Save for later comparison.
BrowserAccessibility* acc1_2 = manager->GetFromID(2);
@@ -704,7 +704,7 @@ TEST_F(BrowserAccessibilityWinTest, TestCreateEmptyDocument) {
event_bundle.updates[0].nodes.push_back(tree2_2);
// Fire another load complete.
- manager->OnAccessibilityEvents(event_bundle);
+ ASSERT_TRUE(manager->OnAccessibilityEvents(event_bundle));
BrowserAccessibility* acc2_2 = manager->GetFromID(3);
@@ -2516,7 +2516,7 @@ TEST_F(BrowserAccessibilityWinTest, DISABLED_TestIAccessible2Relations) {
AXEventNotificationDetails event_bundle;
event_bundle.updates.resize(1);
event_bundle.updates[0].nodes.push_back(child1);
- manager->OnAccessibilityEvents(event_bundle);
+ ASSERT_TRUE(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/cross_platform_accessibility_browsertest.cc b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index a34d8ab9151..34041d0dbb1 100644
--- a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -62,8 +62,8 @@ class CrossPlatformAccessibilityBrowserTest : public ContentBrowserTest {
std::unordered_set<int>* ids) {
ASSERT_TRUE(ids->find(node->id()) == ids->end());
ids->insert(node->id());
- for (int i = 0; i < node->child_count(); i++)
- RecursiveAssertUniqueIds(node->ChildAtIndex(i), ids);
+ for (const auto* child : node->children())
+ RecursiveAssertUniqueIds(child, ids);
}
// ContentBrowserTest
@@ -188,8 +188,8 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
EXPECT_EQ(ax::mojom::Role::kRootWebArea, root->data().role);
// Check properties of the BODY element.
- ASSERT_EQ(1, root->child_count());
- const ui::AXNode* body = root->ChildAtIndex(0);
+ ASSERT_EQ(1u, root->children().size());
+ const ui::AXNode* body = root->children().front();
EXPECT_EQ(ax::mojom::Role::kGenericContainer, body->data().role);
EXPECT_STREQ("body",
GetAttr(body, ax::mojom::StringAttribute::kHtmlTag).c_str());
@@ -197,9 +197,9 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
GetAttr(body, ax::mojom::StringAttribute::kDisplay).c_str());
// Check properties of the two children of the BODY element.
- ASSERT_EQ(2, body->child_count());
+ ASSERT_EQ(2u, body->children().size());
- const ui::AXNode* button = body->ChildAtIndex(0);
+ const ui::AXNode* button = body->children()[0];
EXPECT_EQ(ax::mojom::Role::kButton, button->data().role);
EXPECT_STREQ("input",
GetAttr(button, ax::mojom::StringAttribute::kHtmlTag).c_str());
@@ -213,7 +213,7 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
EXPECT_STREQ("value", button->data().html_attributes[1].first.c_str());
EXPECT_STREQ("push", button->data().html_attributes[1].second.c_str());
- const ui::AXNode* checkbox = body->ChildAtIndex(1);
+ const ui::AXNode* checkbox = body->children()[1];
EXPECT_EQ(ax::mojom::Role::kCheckBox, checkbox->data().role);
EXPECT_STREQ("input",
GetAttr(checkbox, ax::mojom::StringAttribute::kHtmlTag).c_str());
@@ -238,10 +238,10 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const ui::AXTree& tree = GetAXTree();
const ui::AXNode* root = tree.root();
- ASSERT_EQ(1, root->child_count());
- const ui::AXNode* body = root->ChildAtIndex(0);
- ASSERT_EQ(1, body->child_count());
- const ui::AXNode* text = body->ChildAtIndex(0);
+ ASSERT_EQ(1u, root->children().size());
+ const ui::AXNode* body = root->children().front();
+ ASSERT_EQ(1u, body->children().size());
+ const ui::AXNode* text = body->children().front();
EXPECT_EQ(ax::mojom::Role::kTextField, text->data().role);
EXPECT_STREQ("input",
GetAttr(text, ax::mojom::StringAttribute::kHtmlTag).c_str());
@@ -269,10 +269,10 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const ui::AXTree& tree = GetAXTree();
const ui::AXNode* root = tree.root();
- ASSERT_EQ(1, root->child_count());
- const ui::AXNode* body = root->ChildAtIndex(0);
- ASSERT_EQ(1, body->child_count());
- const ui::AXNode* text = body->ChildAtIndex(0);
+ ASSERT_EQ(1u, root->children().size());
+ const ui::AXNode* body = root->children().front();
+ ASSERT_EQ(1u, body->children().size());
+ const ui::AXNode* text = body->children().front();
EXPECT_EQ(ax::mojom::Role::kTextField, text->data().role);
EXPECT_STREQ("input",
GetAttr(text, ax::mojom::StringAttribute::kHtmlTag).c_str());
@@ -323,33 +323,33 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const ui::AXTree& tree = GetAXTree();
const ui::AXNode* root = tree.root();
- ASSERT_EQ(1, root->child_count());
- const ui::AXNode* body = root->ChildAtIndex(0);
- ASSERT_EQ(3, body->child_count());
+ ASSERT_EQ(1u, root->children().size());
+ const ui::AXNode* body = root->children().front();
+ ASSERT_EQ(3u, body->children().size());
- const ui::AXNode* button1 = body->ChildAtIndex(0);
+ const ui::AXNode* button1 = body->children()[0];
EXPECT_EQ(ax::mojom::Role::kButton, button1->data().role);
EXPECT_STREQ("Button 1",
GetAttr(button1, ax::mojom::StringAttribute::kName).c_str());
- const ui::AXNode* iframe = body->ChildAtIndex(1);
+ const ui::AXNode* iframe = body->children()[1];
EXPECT_STREQ("iframe",
GetAttr(iframe, ax::mojom::StringAttribute::kHtmlTag).c_str());
- ASSERT_EQ(1, iframe->child_count());
+ ASSERT_EQ(1u, iframe->children().size());
- const ui::AXNode* sub_document = iframe->ChildAtIndex(0);
+ const ui::AXNode* sub_document = iframe->children().front();
EXPECT_EQ(ax::mojom::Role::kWebArea, sub_document->data().role);
- ASSERT_EQ(1, sub_document->child_count());
+ ASSERT_EQ(1u, sub_document->children().size());
- const ui::AXNode* sub_body = sub_document->ChildAtIndex(0);
- ASSERT_EQ(1, sub_body->child_count());
+ const ui::AXNode* sub_body = sub_document->children().front();
+ ASSERT_EQ(1u, sub_body->children().size());
- const ui::AXNode* button2 = sub_body->ChildAtIndex(0);
+ const ui::AXNode* button2 = sub_body->children().front();
EXPECT_EQ(ax::mojom::Role::kButton, button2->data().role);
EXPECT_STREQ("Button 2",
GetAttr(button2, ax::mojom::StringAttribute::kName).c_str());
- const ui::AXNode* button3 = body->ChildAtIndex(2);
+ const ui::AXNode* button3 = body->children()[2];
EXPECT_EQ(ax::mojom::Role::kButton, button3->data().role);
EXPECT_STREQ("Button 3",
GetAttr(button3, ax::mojom::StringAttribute::kName).c_str());
@@ -396,18 +396,18 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, MAYBE_TableSpan) {
const ui::AXTree& tree = GetAXTree();
const ui::AXNode* root = tree.root();
- const ui::AXNode* table = root->ChildAtIndex(0);
+ const ui::AXNode* table = root->children().front();
EXPECT_EQ(ax::mojom::Role::kTable, table->data().role);
- 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);
+ ASSERT_GE(table->children().size(), 2u);
+ EXPECT_EQ(ax::mojom::Role::kRow, table->children()[0]->data().role);
+ EXPECT_EQ(ax::mojom::Role::kRow, table->children()[1]->data().role);
EXPECT_EQ(3, GetIntAttr(table, ax::mojom::IntAttribute::kTableColumnCount));
EXPECT_EQ(2, GetIntAttr(table, ax::mojom::IntAttribute::kTableRowCount));
- const ui::AXNode* cell1 = table->ChildAtIndex(0)->ChildAtIndex(0);
- const ui::AXNode* cell2 = table->ChildAtIndex(0)->ChildAtIndex(1);
- const ui::AXNode* cell3 = table->ChildAtIndex(1)->ChildAtIndex(0);
- const ui::AXNode* cell4 = table->ChildAtIndex(1)->ChildAtIndex(1);
+ const ui::AXNode* cell1 = table->children()[0]->children()[0];
+ const ui::AXNode* cell2 = table->children()[0]->children()[1];
+ const ui::AXNode* cell3 = table->children()[1]->children()[0];
+ const ui::AXNode* cell4 = table->children()[1]->children()[1];
EXPECT_EQ(0,
GetIntAttr(cell1, ax::mojom::IntAttribute::kTableCellColumnIndex));
@@ -440,8 +440,8 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, WritableElement) {
NavigateToURL(shell(), url);
const ui::AXTree& tree = GetAXTree();
const ui::AXNode* root = tree.root();
- ASSERT_EQ(1, root->child_count());
- const ui::AXNode* textbox = root->ChildAtIndex(0);
+ ASSERT_EQ(1u, root->children().size());
+ const ui::AXNode* textbox = root->children().front();
EXPECT_TRUE(textbox->data().HasAction(ax::mojom::Action::kSetValue));
}
@@ -462,17 +462,17 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const ui::AXTree& tree = GetAXTree();
const ui::AXNode* root = tree.root();
- const ui::AXNode* table = root->ChildAtIndex(0);
+ const ui::AXNode* table = root->children().front();
EXPECT_EQ(ax::mojom::Role::kTable, table->data().role);
- EXPECT_EQ(1, table->child_count());
- const ui::AXNode* row = table->ChildAtIndex(0);
- EXPECT_EQ(5, row->child_count());
+ EXPECT_EQ(1u, table->children().size());
+ const ui::AXNode* row = table->children().front();
+ EXPECT_EQ(5u, row->children().size());
- const ui::AXNode* header1 = row->ChildAtIndex(0);
- const ui::AXNode* header2 = row->ChildAtIndex(1);
- const ui::AXNode* header3 = row->ChildAtIndex(2);
- const ui::AXNode* header4 = row->ChildAtIndex(3);
- const ui::AXNode* header5 = row->ChildAtIndex(4);
+ const ui::AXNode* header1 = row->children()[0];
+ const ui::AXNode* header2 = row->children()[1];
+ const ui::AXNode* header3 = row->children()[2];
+ const ui::AXNode* header4 = row->children()[3];
+ const ui::AXNode* header5 = row->children()[4];
EXPECT_EQ(static_cast<int>(ax::mojom::SortDirection::kAscending),
GetIntAttr(header1, ax::mojom::IntAttribute::kSortDirection));
@@ -629,8 +629,8 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const ui::AXTree& tree = GetAXTree();
const ui::AXNode* root = tree.root();
- const ui::AXNode* input1 = root->ChildAtIndex(0);
- const ui::AXNode* input2 = root->ChildAtIndex(1);
+ const ui::AXNode* input1 = root->children()[0];
+ const ui::AXNode* input2 = root->children()[1];
EXPECT_EQ(static_cast<int>(ax::mojom::NameFrom::kTitle),
GetIntAttr(input1, ax::mojom::IntAttribute::kNameFrom));
@@ -660,9 +660,9 @@ IN_PROC_BROWSER_TEST_F(
const ui::AXTree& tree = GetAXTree();
const ui::AXNode* root = tree.root();
- const ui::AXNode* group = root->ChildAtIndex(0);
- const ui::AXNode* input1 = group->ChildAtIndex(0);
- const ui::AXNode* input2 = group->ChildAtIndex(1);
+ const ui::AXNode* group = root->children().front();
+ const ui::AXNode* input1 = group->children()[0];
+ const ui::AXNode* input2 = group->children()[1];
using ax::mojom::StringAttribute;
diff --git a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index 81d795dc2ce..7232aa362cd 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -163,7 +163,8 @@ std::vector<int> DumpAccessibilityTestBase::DiffLines(
void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives(
const std::string& test_html,
std::vector<std::string>* wait_for,
- std::vector<std::string>* run_until) {
+ std::vector<std::string>* run_until,
+ std::vector<std::string>* default_action_on) {
for (const std::string& line : base::SplitString(
test_html, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
const std::string& allow_empty_str = formatter_->GetAllowEmptyString();
@@ -172,6 +173,7 @@ void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives(
const std::string& deny_node_str = formatter_->GetDenyNodeString();
const std::string& wait_str = "@WAIT-FOR:";
const std::string& until_str = "@RUN-UNTIL-EVENT:";
+ const std::string& default_action_on_str = "@DEFAULT-ACTION-ON:";
if (base::StartsWith(line, allow_empty_str, base::CompareCase::SENSITIVE)) {
property_filters_.push_back(
PropertyFilter(base::UTF8ToUTF16(line.substr(allow_empty_str.size())),
@@ -200,6 +202,9 @@ void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives(
} else if (base::StartsWith(line, until_str,
base::CompareCase::SENSITIVE)) {
run_until->push_back(line.substr(until_str.size()));
+ } else if (base::StartsWith(line, default_action_on_str,
+ base::CompareCase::SENSITIVE)) {
+ default_action_on->push_back(line.substr(default_action_on_str.size()));
}
}
}
@@ -304,11 +309,13 @@ void DumpAccessibilityTestBase::RunTestForPlatform(
// Parse filters and other directives in the test file.
std::vector<std::string> wait_for;
std::vector<std::string> run_until;
+ std::vector<std::string> default_action_on;
property_filters_.clear();
node_filters_.clear();
formatter_->AddDefaultFilters(&property_filters_);
AddDefaultFilters(&property_filters_);
- ParseHtmlForExtraDirectives(html_contents, &wait_for, &run_until);
+ ParseHtmlForExtraDirectives(html_contents, &wait_for, &run_until,
+ &default_action_on);
// Get the test URL.
GURL url(embedded_test_server()->GetURL("/" + std::string(file_dir) + "/" +
@@ -332,6 +339,21 @@ void DumpAccessibilityTestBase::RunTestForPlatform(
accessibility_waiter.WaitForNotification();
}
+ // Perform default action on any elements specified by the test.
+ for (const auto& str : default_action_on) {
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kClicked);
+
+ BrowserAccessibility* action_element = FindNode(str);
+
+ ui::AXActionData action_data;
+ action_data.action = ax::mojom::Action::kDoDefault;
+ action_element->AccessibilityPerformAction(action_data);
+
+ waiter.WaitForNotification();
+ }
+
// Get the url of every frame in the frame tree.
FrameTree* frame_tree = web_contents->GetFrameTree();
std::vector<std::string> all_frame_urls;
@@ -457,4 +479,33 @@ void DumpAccessibilityTestBase::RunTestForPlatform(
}
}
+BrowserAccessibility* DumpAccessibilityTestBase::FindNode(
+ const std::string& name) {
+ BrowserAccessibility* root = GetManager()->GetRoot();
+ CHECK(root);
+ return FindNodeInSubtree(*root, name);
+}
+
+BrowserAccessibilityManager* DumpAccessibilityTestBase::GetManager() {
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ return web_contents->GetRootBrowserAccessibilityManager();
+}
+
+BrowserAccessibility* DumpAccessibilityTestBase::FindNodeInSubtree(
+ BrowserAccessibility& node,
+ const std::string& name) {
+ if (node.GetStringAttribute(ax::mojom::StringAttribute::kName) == name) {
+ return &node;
+ }
+
+ for (unsigned int i = 0; i < node.PlatformChildCount(); ++i) {
+ BrowserAccessibility* result =
+ FindNodeInSubtree(*node.PlatformGetChild(i), name);
+ if (result)
+ return result;
+ }
+ return nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h
index 1241435ff81..92e7da7b7ae 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h
+++ b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h
@@ -97,10 +97,19 @@ class DumpAccessibilityTestBase : public ContentBrowserTest,
// @WAIT-FOR: directives.
void ParseHtmlForExtraDirectives(const std::string& test_html,
std::vector<std::string>* wait_for,
- std::vector<std::string>* run_until);
+ std::vector<std::string>* run_until,
+ std::vector<std::string>* default_action_on);
void RunTestForPlatform(const base::FilePath file_path, const char* file_dir);
+ // Retrieve the accessibility node, starting from the root node, that matches
+ // the accessibility name.
+ BrowserAccessibility* FindNode(const std::string& name);
+
+ // Retrieve the browser accessibility manager object for the current web
+ // contents.
+ BrowserAccessibilityManager* GetManager();
+
// The default property filters plus the property filters loaded from the test
// file.
std::vector<AccessibilityTreeFormatter::PropertyFilter> property_filters_;
@@ -125,6 +134,10 @@ class DumpAccessibilityTestBase : public ContentBrowserTest,
bool enable_accessibility_after_navigating_;
base::test::ScopedFeatureList scoped_feature_list_;
+
+ private:
+ BrowserAccessibility* FindNodeInSubtree(BrowserAccessibility& node,
+ const std::string& name);
};
} // namespace content
diff --git a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index 3827cbfd11a..99070d8dfc0 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -74,6 +74,11 @@ class DumpAccessibilityEventsTest : public DumpAccessibilityTestBase {
property_filters->push_back(
PropertyFilter(base::ASCIIToUTF16("AutomationFocusChanged*document*"),
PropertyFilter::DENY));
+ // Implementing IRawElementProviderAdviseEvents causes Win7 to fire
+ // spurious focus events (regardless of what the implementation does).
+ property_filters->push_back(PropertyFilter(
+ base::ASCIIToUTF16("AutomationFocusChanged on role=region"),
+ PropertyFilter::DENY));
}
std::vector<std::string> Dump(std::vector<std::string>& run_until) override;
@@ -226,6 +231,11 @@ INSTANTIATE_TEST_SUITE_P(
DumpAccessibilityEventsTestPassToString());
IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaAtomicChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-atomic-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
AccessibilityEventsAriaBusyChanged) {
RunEventTest(FILE_PATH_LITERAL("aria-busy-changed.html"));
}
@@ -246,6 +256,71 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaDisabledChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-disabled-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaDropeffectChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-dropeffect-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaGrabbedChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-grabbed-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaHasPopupChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-haspopup-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaInvalidChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-invalid-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaLevelChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-level-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaLiveChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-live-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaMultilineChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-multiline-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaPosinsetChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-posinset-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaReadonlyChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-readonly-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaRelevantChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-relevant-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaSetSizeChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-setsize-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaSortChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-sort-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
AccessibilityEventsAriaTreeCollapse) {
RunEventTest(FILE_PATH_LITERAL("aria-tree-collapse.html"));
}
@@ -318,6 +393,11 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAddChild) {
+ RunEventTest(FILE_PATH_LITERAL("add-child.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
AccessibilityEventsAddChildOfBody) {
RunEventTest(FILE_PATH_LITERAL("add-child-of-body.html"));
}
@@ -405,11 +485,6 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
- AccessibilityEventsInvalidStatusChange) {
- RunEventTest(FILE_PATH_LITERAL("invalid-status-change.html"));
-}
-
-IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
AccessibilityEventsListboxFocus) {
RunEventTest(FILE_PATH_LITERAL("listbox-focus.html"));
}
@@ -495,6 +570,11 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsMultipleAriaPropertiesChanged) {
+ RunEventTest(FILE_PATH_LITERAL("multiple-aria-properties-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
AccessibilityEventsNameChange) {
RunEventTest(FILE_PATH_LITERAL("name-change.html"));
}
@@ -682,4 +762,9 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
RunEventTest(FILE_PATH_LITERAL("aria-flow-to.html"));
}
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsSelectAddRemove) {
+ RunEventTest(FILE_PATH_LITERAL("select-selected-add-remove.html"));
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 400e17c35ec..ebedcf55082 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -1321,8 +1321,9 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("iframe-coordinates.html"));
}
+// https://crbug.com/956990
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
- AccessibilityIframeCoordinatesCrossProcess) {
+ DISABLED_AccessibilityIframeCoordinatesCrossProcess) {
RunHtmlTest(FILE_PATH_LITERAL("iframe-coordinates-cross-process.html"));
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityIframePadding) {
@@ -1407,6 +1408,11 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityInputDate) {
RunHtmlTest(FILE_PATH_LITERAL("input-date.html"));
}
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+ AccessibilityInputDateWithPopupOpen) {
+ RunHtmlTest(FILE_PATH_LITERAL("input-date-with-popup-open.html"));
+}
+
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityInputDateTime) {
RunHtmlTest(FILE_PATH_LITERAL("input-datetime.html"));
}
diff --git a/chromium/content/browser/accessibility/snapshot_ax_tree_browsertest.cc b/chromium/content/browser/accessibility/snapshot_ax_tree_browsertest.cc
index 912294fc661..e9a2df53f97 100644
--- a/chromium/content/browser/accessibility/snapshot_ax_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/snapshot_ax_tree_browsertest.cc
@@ -52,8 +52,8 @@ void DumpRolesAndNamesAsText(const ui::AXNode* node,
node->data().GetStringAttribute(ax::mojom::StringAttribute::kName) +
"'";
*dst += "\n";
- for (int i = 0; i < node->child_count(); ++i)
- DumpRolesAndNamesAsText(node->children()[i], indent + 1, dst);
+ for (const auto* child : node->children())
+ DumpRolesAndNamesAsText(child, indent + 1, dst);
}
} // namespace
@@ -87,9 +87,9 @@ IN_PROC_BROWSER_TEST_F(SnapshotAXTreeBrowserTest,
ui::AXNode* root = tree.root();
ASSERT_NE(nullptr, root);
ASSERT_EQ(ax::mojom::Role::kRootWebArea, root->data().role);
- ui::AXNode* group = root->ChildAtIndex(0);
+ ui::AXNode* group = root->children().front();
ASSERT_EQ(ax::mojom::Role::kGenericContainer, group->data().role);
- ui::AXNode* button = group->ChildAtIndex(0);
+ ui::AXNode* button = group->children().front();
ASSERT_EQ(ax::mojom::Role::kButton, button->data().role);
}
diff --git a/chromium/content/browser/accessibility/test_browser_accessibility_delegate.cc b/chromium/content/browser/accessibility/test_browser_accessibility_delegate.cc
index 1540e0c5675..eabb818088a 100644
--- a/chromium/content/browser/accessibility/test_browser_accessibility_delegate.cc
+++ b/chromium/content/browser/accessibility/test_browser_accessibility_delegate.cc
@@ -46,7 +46,7 @@ gfx::NativeViewAccessible TestBrowserAccessibilityDelegate::
return nullptr;
}
-bool TestBrowserAccessibilityDelegate::AccessibilityIsMainFrame() {
+bool TestBrowserAccessibilityDelegate::AccessibilityIsMainFrame() const {
return is_root_frame_;
}
diff --git a/chromium/content/browser/accessibility/test_browser_accessibility_delegate.h b/chromium/content/browser/accessibility/test_browser_accessibility_delegate.h
index 86fb3e98f87..10dca8ba935 100644
--- a/chromium/content/browser/accessibility/test_browser_accessibility_delegate.h
+++ b/chromium/content/browser/accessibility/test_browser_accessibility_delegate.h
@@ -22,7 +22,7 @@ class TestBrowserAccessibilityDelegate : public BrowserAccessibilityDelegate {
gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override;
gfx::NativeViewAccessible AccessibilityGetNativeViewAccessibleForWindow()
override;
- bool AccessibilityIsMainFrame() override;
+ bool AccessibilityIsMainFrame() const override;
bool got_fatal_error() const;
void reset_got_fatal_error();
diff --git a/chromium/content/browser/accessibility/web_contents_accessibility_android.cc b/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
index 6dede061c62..549931e9224 100644
--- a/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -338,9 +338,9 @@ void WebContentsAccessibilityAndroid::Connector::UpdateRenderProcessConnection(
RenderWidgetHostViewAndroid* old_rwhva,
RenderWidgetHostViewAndroid* new_rwhva) {
if (old_rwhva)
- old_rwhva->set_web_contents_accessibility(nullptr);
+ old_rwhva->SetWebContentsAccessibility(nullptr);
if (new_rwhva)
- new_rwhva->set_web_contents_accessibility(accessibility_.get());
+ new_rwhva->SetWebContentsAccessibility(accessibility_.get());
}
WebContentsAccessibilityAndroid::WebContentsAccessibilityAndroid(
@@ -683,7 +683,7 @@ jboolean WebContentsAccessibilityAndroid::PopulateAccessibilityNodeInfo(
base::android::ConvertUTF8ToJavaString(env, node->GetClassName()));
Java_WebContentsAccessibilityImpl_setAccessibilityNodeInfoText(
env, obj, info,
- base::android::ConvertUTF16ToJavaString(env, node->GetText()),
+ base::android::ConvertUTF16ToJavaString(env, node->GetInnerText()),
node->IsLink(), node->IsEditableText(),
base::android::ConvertUTF16ToJavaString(
env, node->GetInheritedString16Attribute(
@@ -777,7 +777,7 @@ jboolean WebContentsAccessibilityAndroid::PopulateAccessibilityEvent(
switch (event_type) {
case ANDROID_ACCESSIBILITY_EVENT_TEXT_CHANGED: {
base::string16 before_text = node->GetTextChangeBeforeText();
- base::string16 text = node->GetText();
+ base::string16 text = node->GetInnerText();
Java_WebContentsAccessibilityImpl_setAccessibilityEventTextChangedAttrs(
env, obj, event, node->GetTextChangeFromIndex(),
node->GetTextChangeAddedCount(), node->GetTextChangeRemovedCount(),
@@ -786,7 +786,7 @@ jboolean WebContentsAccessibilityAndroid::PopulateAccessibilityEvent(
break;
}
case ANDROID_ACCESSIBILITY_EVENT_TEXT_SELECTION_CHANGED: {
- base::string16 text = node->GetText();
+ base::string16 text = node->GetInnerText();
Java_WebContentsAccessibilityImpl_setAccessibilityEventSelectionAttrs(
env, obj, event, node->GetSelectionStart(), node->GetSelectionEnd(),
node->GetEditableTextLength(),
@@ -1009,7 +1009,7 @@ jboolean WebContentsAccessibilityAndroid::NextAtGranularity(
int end_index = -1;
if (root_manager_->NextAtGranularity(granularity, cursor_index, node,
&start_index, &end_index)) {
- base::string16 text = node->GetText();
+ base::string16 text = node->GetInnerText();
Java_WebContentsAccessibilityImpl_finishGranularityMove(
env, obj, base::android::ConvertUTF16ToJavaString(env, text),
extend_selection, start_index, end_index, true);
@@ -1025,7 +1025,7 @@ jint WebContentsAccessibilityAndroid::GetTextLength(
BrowserAccessibilityAndroid* node = GetAXFromUniqueID(unique_id);
if (!node)
return -1;
- base::string16 text = node->GetText();
+ base::string16 text = node->GetInnerText();
return text.size();
}
@@ -1047,7 +1047,8 @@ jboolean WebContentsAccessibilityAndroid::PreviousAtGranularity(
if (root_manager_->PreviousAtGranularity(granularity, cursor_index, node,
&start_index, &end_index)) {
Java_WebContentsAccessibilityImpl_finishGranularityMove(
- env, obj, base::android::ConvertUTF16ToJavaString(env, node->GetText()),
+ env, obj,
+ base::android::ConvertUTF16ToJavaString(env, node->GetInnerText()),
extend_selection, start_index, end_index, false);
return true;
}
@@ -1101,8 +1102,7 @@ void WebContentsAccessibilityAndroid::OnAutofillPopupDisplayed(
DeleteAutofillPopupProxy();
g_autofill_popup_proxy_node = BrowserAccessibility::Create();
- g_autofill_popup_proxy_node_ax_node =
- new ui::AXNode(nullptr, nullptr, -1, -1);
+ g_autofill_popup_proxy_node_ax_node = new ui::AXNode(nullptr, nullptr, -1, 0);
ui::AXNodeData ax_node_data;
ax_node_data.role = ax::mojom::Role::kMenu;
ax_node_data.SetName("Autofill");
@@ -1201,8 +1201,8 @@ WebContentsAccessibilityAndroid::GetCharacterBoundingBoxes(
gfx::Rect object_bounds = node->GetUnclippedRootFrameBoundsRect();
int coords[4 * len];
for (int i = 0; i < len; i++) {
- gfx::Rect char_bounds = node->GetRootFrameRangeBoundsRect(
- start + i, 1, ui::AXClippingBehavior::kUnclipped);
+ gfx::Rect char_bounds = node->GetUnclippedRootFrameInnerTextRangeBoundsRect(
+ start + i, start + i + 1);
if (char_bounds.IsEmpty())
char_bounds = object_bounds;
coords[4 * i + 0] = char_bounds.x();
diff --git a/chromium/content/browser/after_startup_task_utils.cc b/chromium/content/browser/after_startup_task_utils.cc
index 202410587da..3693f61992a 100644
--- a/chromium/content/browser/after_startup_task_utils.cc
+++ b/chromium/content/browser/after_startup_task_utils.cc
@@ -11,7 +11,7 @@
namespace content {
void SetBrowserStartupIsCompleteForTesting() {
- content::BrowserTaskExecutor::NotifyBrowserStartupCompleted();
+ content::BrowserTaskExecutor::EnableAllQueues();
// Forward the message to ContentBrowserClient if one is registered (there are
// many tests where one isn't but that's fine as that also means they get the
// default ContentBrowserClient::IsBrowserStartupComplete() which is always
diff --git a/chromium/content/browser/android/app_web_message_port.cc b/chromium/content/browser/android/app_web_message_port.cc
index 37112192ca7..a1537873940 100644
--- a/chromium/content/browser/android/app_web_message_port.cc
+++ b/chromium/content/browser/android/app_web_message_port.cc
@@ -22,10 +22,7 @@ std::vector<blink::MessagePortChannel> AppWebMessagePort::UnwrapJavaArray(
const base::android::JavaRef<jobjectArray>& jports) {
std::vector<blink::MessagePortChannel> channels;
if (!jports.is_null()) {
- jsize num_ports = env->GetArrayLength(jports.obj());
- for (jsize i = 0; i < num_ports; ++i) {
- base::android::ScopedJavaLocalRef<jobject> jport(
- env, env->GetObjectArrayElement(jports.obj(), i));
+ for (auto jport : jports.ReadElements<jobject>()) {
jint native_port = Java_AppWebMessagePort_releaseNativeHandle(env, jport);
channels.push_back(blink::MessagePortChannel(
mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(native_port))));
diff --git a/chromium/content/browser/android/content_feature_list.cc b/chromium/content/browser/android/content_feature_list.cc
index 4d1b275060e..d7e21b9e45e 100644
--- a/chromium/content/browser/android/content_feature_list.cc
+++ b/chromium/content/browser/android/content_feature_list.cc
@@ -24,7 +24,7 @@ namespace {
const base::Feature* kFeaturesExposedToJava[] = {
&features::kBackgroundMediaRendererHasModerateBinding,
&kEnhancedSelectionInsertionHandle,
- &features::kServiceWorkerForegroundPriority,
+ &kServiceGroupImportance,
};
const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
@@ -44,6 +44,8 @@ const base::Feature kEnhancedSelectionInsertionHandle{
"EnhancedSelectionInsertionHandle", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kRequestUnbufferedDispatch{
"RequestUnbufferedDispatch", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kServiceGroupImportance{"ServiceGroupImportance",
+ base::FEATURE_DISABLED_BY_DEFAULT};
static jboolean JNI_ContentFeatureList_IsEnabled(
JNIEnv* env,
diff --git a/chromium/content/browser/android/content_feature_list.h b/chromium/content/browser/android/content_feature_list.h
index 05c712f651b..68333f8b4d8 100644
--- a/chromium/content/browser/android/content_feature_list.h
+++ b/chromium/content/browser/android/content_feature_list.h
@@ -13,6 +13,7 @@ namespace android {
// Alphabetical:
extern const base::Feature kEnhancedSelectionInsertionHandle;
extern const base::Feature kRequestUnbufferedDispatch;
+extern const base::Feature kServiceGroupImportance;
} // namespace android
} // namespace content
diff --git a/chromium/content/browser/android/date_time_chooser_android.cc b/chromium/content/browser/android/date_time_chooser_android.cc
index 5d0f0449f5a..d78c9f3f82f 100644
--- a/chromium/content/browser/android/date_time_chooser_android.cc
+++ b/chromium/content/browser/android/date_time_chooser_android.cc
@@ -10,8 +10,8 @@
#include "base/android/jni_string.h"
#include "base/i18n/char_iterator.h"
#include "base/i18n/unicodestring.h"
-#include "content/common/date_time_suggestion.h"
-#include "content/common/view_messages.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "jni/DateTimeChooserAndroid_jni.h"
#include "third_party/icu/source/common/unicode/uchar.h"
@@ -45,62 +45,83 @@ base::string16 SanitizeSuggestionString(const base::string16& string) {
namespace content {
// DateTimeChooserAndroid implementation
-DateTimeChooserAndroid::DateTimeChooserAndroid()
- : host_(NULL) {
+DateTimeChooserAndroid::DateTimeChooserAndroid(WebContentsImpl* web_contents)
+ : content::WebContentsObserver(web_contents),
+ date_time_chooser_binding_(this) {
+ registry_.AddInterface(
+ base::BindRepeating(&DateTimeChooserAndroid::OnDateTimeChooserRequest,
+ base::Unretained(this)));
}
DateTimeChooserAndroid::~DateTimeChooserAndroid() {
}
-void DateTimeChooserAndroid::ReplaceDateTime(JNIEnv* env,
- const JavaRef<jobject>&,
- jdouble value) {
- host_->Send(new ViewMsg_ReplaceDateTime(host_->GetRoutingID(), value));
-}
+void DateTimeChooserAndroid::OnDateTimeChooserRequest(
+ blink::mojom::DateTimeChooserRequest request) {
+ // Disconnect the previous picker first.
+ date_time_chooser_binding_.Close();
-void DateTimeChooserAndroid::CancelDialog(JNIEnv* env,
- const JavaRef<jobject>&) {
- host_->Send(new ViewMsg_CancelDateTimeDialog(host_->GetRoutingID()));
+ date_time_chooser_binding_.Bind(std::move(request));
}
-void DateTimeChooserAndroid::ShowDialog(
- gfx::NativeWindow native_window,
- RenderViewHost* host,
- ui::TextInputType dialog_type,
- double dialog_value,
- double min,
- double max,
- double step,
- const std::vector<DateTimeSuggestion>& suggestions) {
- host_ = host;
-
+void DateTimeChooserAndroid::OpenDateTimeDialog(
+ blink::mojom::DateTimeDialogValuePtr value,
+ OpenDateTimeDialogCallback callback) {
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobjectArray> suggestions_array;
- if (suggestions.size() > 0) {
- suggestions_array =
- Java_DateTimeChooserAndroid_createSuggestionsArray(env,
- suggestions.size());
- for (size_t i = 0; i < suggestions.size(); ++i) {
- const content::DateTimeSuggestion& suggestion = suggestions[i];
+ if (open_date_time_response_callback_) {
+ date_time_chooser_binding_.ReportBadMessage(
+ "DateTimeChooserAndroid: Previous picker's binding isn't closed.");
+ return;
+ }
+ open_date_time_response_callback_ = std::move(callback);
+
+ ScopedJavaLocalRef<jobjectArray> suggestions_array;
+ if (value->suggestions.size() > 0) {
+ suggestions_array = Java_DateTimeChooserAndroid_createSuggestionsArray(
+ env, value->suggestions.size());
+ for (size_t i = 0; i < value->suggestions.size(); ++i) {
+ const blink::mojom::DateTimeSuggestionPtr suggestion =
+ std::move(value->suggestions[i]);
ScopedJavaLocalRef<jstring> localized_value = ConvertUTF16ToJavaString(
- env, SanitizeSuggestionString(suggestion.localized_value));
+ env, SanitizeSuggestionString(suggestion->localized_value));
ScopedJavaLocalRef<jstring> label = ConvertUTF16ToJavaString(
- env, SanitizeSuggestionString(suggestion.label));
+ env, SanitizeSuggestionString(suggestion->label));
Java_DateTimeChooserAndroid_setDateTimeSuggestionAt(
- env, suggestions_array, i, suggestion.value, localized_value, label);
+ env, suggestions_array, i, suggestion->value, localized_value, label);
}
}
+ gfx::NativeWindow native_window = web_contents()->GetTopLevelNativeWindow();
+
if (native_window && !(native_window->GetJavaObject()).is_null()) {
j_date_time_chooser_.Reset(
Java_DateTimeChooserAndroid_createDateTimeChooser(
env, native_window->GetJavaObject(),
- reinterpret_cast<intptr_t>(this), dialog_type, dialog_value, min,
- max, step, suggestions_array));
+ reinterpret_cast<intptr_t>(this), value->dialog_type,
+ value->dialog_value, value->minimum, value->maximum, value->step,
+ suggestions_array));
}
if (j_date_time_chooser_.is_null())
- ReplaceDateTime(env, j_date_time_chooser_, dialog_value);
+ std::move(open_date_time_response_callback_).Run(true, value->dialog_value);
+}
+
+void DateTimeChooserAndroid::ReplaceDateTime(JNIEnv* env,
+ const JavaRef<jobject>&,
+ jdouble value) {
+ std::move(open_date_time_response_callback_).Run(true, value);
+}
+
+void DateTimeChooserAndroid::CancelDialog(JNIEnv* env,
+ const JavaRef<jobject>&) {
+ std::move(open_date_time_response_callback_).Run(false, 0.0);
+}
+
+void DateTimeChooserAndroid::OnInterfaceRequestFromFrame(
+ content::RenderFrameHost* render_frame_host,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle* interface_pipe) {
+ registry_.TryBindInterface(interface_name, interface_pipe);
}
} // namespace content
diff --git a/chromium/content/browser/android/date_time_chooser_android.h b/chromium/content/browser/android/date_time_chooser_android.h
index f5da0e6a473..b219fedbb9b 100644
--- a/chromium/content/browser/android/date_time_chooser_android.h
+++ b/chromium/content/browser/android/date_time_chooser_android.h
@@ -11,33 +11,34 @@
#include "base/android/jni_weak_ref.h"
#include "base/macros.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+#include "third_party/blink/public/mojom/choosers/date_time_chooser.mojom.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/gfx/native_widget_types.h"
namespace content {
-class RenderViewHost;
-struct DateTimeSuggestion;
+class WebContentsImpl;
+class RenderFrameHost;
// Android implementation for DateTimeChooser dialogs.
-class DateTimeChooserAndroid {
+class DateTimeChooserAndroid : public blink::mojom::DateTimeChooser,
+ public WebContentsObserver {
public:
- DateTimeChooserAndroid();
- ~DateTimeChooserAndroid();
+ explicit DateTimeChooserAndroid(WebContentsImpl* web_contents);
+ ~DateTimeChooserAndroid() override;
- // DateTimeChooser implementation:
- // Shows the dialog. |dialog_value| is the date/time value converted to a
+ void OnDateTimeChooserRequest(blink::mojom::DateTimeChooserRequest request);
+
+ // blink::mojom::DateTimeChooser implementation:
+ // Shows the dialog. |value| is the date/time value converted to a
// number as defined in HTML. (See blink::InputType::parseToNumber())
- void ShowDialog(gfx::NativeWindow native_window,
- RenderViewHost* host,
- ui::TextInputType dialog_type,
- double dialog_value,
- double min,
- double max,
- double step,
- const std::vector<DateTimeSuggestion>& suggestions);
-
- // Replaces the current value
+ void OpenDateTimeDialog(blink::mojom::DateTimeDialogValuePtr value,
+ OpenDateTimeDialogCallback callback) override;
+
+ // Replaces the current value.
void ReplaceDateTime(JNIEnv* env,
const base::android::JavaRef<jobject>&,
jdouble value);
@@ -45,11 +46,21 @@ class DateTimeChooserAndroid {
// Closes the dialog without propagating any changes.
void CancelDialog(JNIEnv* env, const base::android::JavaRef<jobject>&);
+ // WebContentsObserver overrides:
+ void OnInterfaceRequestFromFrame(
+ content::RenderFrameHost* render_frame_host,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle* interface_pipe) override;
+
private:
- RenderViewHost* host_;
+ OpenDateTimeDialogCallback open_date_time_response_callback_;
base::android::ScopedJavaGlobalRef<jobject> j_date_time_chooser_;
+ mojo::Binding<blink::mojom::DateTimeChooser> date_time_chooser_binding_;
+
+ service_manager::BinderRegistry registry_;
+
DISALLOW_COPY_AND_ASSIGN(DateTimeChooserAndroid);
};
diff --git a/chromium/content/browser/android/dialog_overlay_impl.cc b/chromium/content/browser/android/dialog_overlay_impl.cc
index 67ec2bb24fa..0dd5d68d4b5 100644
--- a/chromium/content/browser/android/dialog_overlay_impl.cc
+++ b/chromium/content/browser/android/dialog_overlay_impl.cc
@@ -256,8 +256,9 @@ static jint JNI_DialogOverlayImpl_RegisterSurface(
const JavaParamRef<jobject>& surface) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return gpu::GpuSurfaceTracker::Get()->AddSurfaceForNativeWidget(
- gpu::GpuSurfaceTracker::SurfaceRecord(gfx::kNullAcceleratedWidget,
- surface.obj()));
+ gpu::GpuSurfaceTracker::SurfaceRecord(
+ gfx::kNullAcceleratedWidget, surface.obj(),
+ false /* can_be_used_with_surface_control */));
}
static void JNI_DialogOverlayImpl_UnregisterSurface(
@@ -271,8 +272,10 @@ static ScopedJavaLocalRef<jobject>
JNI_DialogOverlayImpl_LookupSurfaceForTesting(
JNIEnv* env,
jint surfaceId) {
+ bool can_be_used_with_surface_control = false;
gl::ScopedJavaSurface surface =
- gpu::GpuSurfaceTracker::Get()->AcquireJavaSurface(surfaceId);
+ gpu::GpuSurfaceTracker::Get()->AcquireJavaSurface(
+ surfaceId, &can_be_used_with_surface_control);
return ScopedJavaLocalRef<jobject>(surface.j_surface());
}
diff --git a/chromium/content/browser/android/gpu_process_callback.cc b/chromium/content/browser/android/gpu_process_callback.cc
index 439e600bd73..06c6dee111d 100644
--- a/chromium/content/browser/android/gpu_process_callback.cc
+++ b/chromium/content/browser/android/gpu_process_callback.cc
@@ -5,6 +5,7 @@
#include "base/android/scoped_java_ref.h"
#include "base/android/unguessable_token_android.h"
#include "content/browser/android/scoped_surface_request_manager.h"
+#include "content/common/android/surface_wrapper.h"
#include "content/public/browser/browser_thread.h"
#include "gpu/ipc/common/gpu_surface_tracker.h"
@@ -36,9 +37,12 @@ base::android::ScopedJavaLocalRef<jobject>
JNI_GpuProcessCallback_GetViewSurface(
JNIEnv* env,
jint surface_id) {
+ bool can_be_used_with_surface_control = false;
gl::ScopedJavaSurface surface_view =
- gpu::GpuSurfaceTracker::GetInstance()->AcquireJavaSurface(surface_id);
- return base::android::ScopedJavaLocalRef<jobject>(surface_view.j_surface());
+ gpu::GpuSurfaceTracker::GetInstance()->AcquireJavaSurface(
+ surface_id, &can_be_used_with_surface_control);
+ return JNI_SurfaceWrapper_create(env, surface_view.j_surface(),
+ can_be_used_with_surface_control);
}
} // namespace content
diff --git a/chromium/content/browser/android/ime_adapter_android.cc b/chromium/content/browser/android/ime_adapter_android.cc
index 29149cfbe68..12ed31df8e3 100644
--- a/chromium/content/browser/android/ime_adapter_android.cc
+++ b/chromium/content/browser/android/ime_adapter_android.cc
@@ -184,9 +184,9 @@ void ImeAdapterAndroid::UpdateState(const TextInputState& state) {
ConvertUTF16ToJavaString(env, state.value);
Java_ImeAdapterImpl_updateState(
env, obj, static_cast<int>(state.type), state.flags, state.mode,
- state.show_ime_if_needed, jstring_text, state.selection_start,
- state.selection_end, state.composition_start, state.composition_end,
- state.reply_to_request);
+ static_cast<int>(state.action), state.show_ime_if_needed, jstring_text,
+ state.selection_start, state.selection_end, state.composition_start,
+ state.composition_end, state.reply_to_request);
}
void ImeAdapterAndroid::UpdateAfterViewSizeChanged() {
diff --git a/chromium/content/browser/android/java/gin_java_bound_object.cc b/chromium/content/browser/android/java/gin_java_bound_object.cc
index b762a9c2641..ce1cc16ce50 100644
--- a/chromium/content/browser/android/java/gin_java_bound_object.cc
+++ b/chromium/content/browser/android/java/gin_java_bound_object.cc
@@ -11,6 +11,7 @@
#include "jni/Object_jni.h"
using base::android::AttachCurrentThread;
+using base::android::JavaObjectArrayReader;
using base::android::ScopedJavaLocalRef;
namespace content {
@@ -134,16 +135,11 @@ void GinJavaBoundObject::EnsureMethodsAreSetUp() {
return;
}
- ScopedJavaLocalRef<jobjectArray> methods(GetClassMethods(env, clazz));
- size_t num_methods = env->GetArrayLength(methods.obj());
+ JavaObjectArrayReader<jobject> methods(GetClassMethods(env, clazz));
// Java objects always have public methods.
- DCHECK(num_methods);
-
- for (size_t i = 0; i < num_methods; ++i) {
- ScopedJavaLocalRef<jobject> java_method(
- env,
- env->GetObjectArrayElement(methods.obj(), i));
+ DCHECK_GT(methods.size(), 0);
+ for (auto java_method : methods) {
if (!safe_annotation_clazz_.is_null()) {
if (!IsAnnotationPresent(env, java_method, safe_annotation_clazz_))
continue;
diff --git a/chromium/content/browser/android/render_widget_host_connector.cc b/chromium/content/browser/android/render_widget_host_connector.cc
index d8373e9d127..259924d9ef1 100644
--- a/chromium/content/browser/android/render_widget_host_connector.cc
+++ b/chromium/content/browser/android/render_widget_host_connector.cc
@@ -6,6 +6,7 @@
#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_android.h"
#include "content/browser/web_contents/web_contents_impl.h"
namespace content {
@@ -13,6 +14,7 @@ namespace content {
// Observes RenderWidgetHostViewAndroid to keep the instance up to date.
class RenderWidgetHostConnector::Observer
: public WebContentsObserver,
+ public WebContentsAndroid::DestructionObserver,
public RenderWidgetHostViewAndroid::DestructionObserver {
public:
Observer(WebContents* web_contents, RenderWidgetHostConnector* connector);
@@ -24,7 +26,10 @@ class RenderWidgetHostConnector::Observer
RenderViewHost* new_host) override;
void DidAttachInterstitialPage() override;
void DidDetachInterstitialPage() override;
- void WebContentsDestroyed() override;
+
+ // WebContentsAndroid::DestructionObserver implementation.
+ void WebContentsAndroidDestroyed(
+ WebContentsAndroid* web_contents_android) override;
// RenderWidgetHostViewAndroid::DestructionObserver implementation.
void RenderWidgetHostViewDestroyed(
@@ -49,7 +54,11 @@ RenderWidgetHostConnector::Observer::Observer(
RenderWidgetHostConnector* connector)
: WebContentsObserver(web_contents),
connector_(connector),
- active_rwhva_(nullptr) {}
+ active_rwhva_(nullptr) {
+ static_cast<WebContentsImpl*>(web_contents)
+ ->GetWebContentsAndroid()
+ ->AddDestructionObserver(this);
+}
RenderWidgetHostConnector::Observer::~Observer() {
DCHECK(!active_rwhva_);
@@ -67,10 +76,12 @@ void RenderWidgetHostConnector::Observer::RenderViewHostChanged(
if (web_contents()->ShowingInterstitialPage())
return;
- auto* new_view = new_host ? static_cast<RenderWidgetHostViewAndroid*>(
+ auto* new_view = new_host ? static_cast<RenderWidgetHostViewBase*>(
new_host->GetWidget()->GetView())
: nullptr;
- UpdateRenderWidgetHostView(new_view);
+ DCHECK(!new_view || !new_view->IsRenderWidgetHostViewChildFrame());
+ auto* new_view_android = static_cast<RenderWidgetHostViewAndroid*>(new_view);
+ UpdateRenderWidgetHostView(new_view_android);
}
void RenderWidgetHostConnector::Observer::DidAttachInterstitialPage() {
@@ -81,7 +92,9 @@ void RenderWidgetHostConnector::Observer::DidDetachInterstitialPage() {
UpdateRenderWidgetHostView(GetRenderWidgetHostViewAndroid());
}
-void RenderWidgetHostConnector::Observer::WebContentsDestroyed() {
+void RenderWidgetHostConnector::Observer::WebContentsAndroidDestroyed(
+ WebContentsAndroid* web_contents_android) {
+ web_contents_android->RemoveDestructionObserver(this);
DCHECK_EQ(active_rwhva_, GetRenderWidgetHostViewAndroid());
UpdateRenderWidgetHostView(nullptr);
delete connector_;
@@ -120,6 +133,8 @@ RenderWidgetHostConnector::Observer::GetRenderWidgetHostViewAndroid() const {
->GetWidget()
->GetView();
}
+ DCHECK(!rwhv || !static_cast<RenderWidgetHostViewBase*>(rwhv)
+ ->IsRenderWidgetHostViewChildFrame());
return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
}
diff --git a/chromium/content/browser/android/render_widget_host_connector.h b/chromium/content/browser/android/render_widget_host_connector.h
index 7c4f94ce1ae..95ff1a14cb8 100644
--- a/chromium/content/browser/android/render_widget_host_connector.h
+++ b/chromium/content/browser/android/render_widget_host_connector.h
@@ -16,7 +16,7 @@ namespace content {
// override |UpdateRenderProcessConnection| to set itself to the RWHVA
// brought up foreground, and null out its reference in the RWHVA going
// away so it won't access the object any more.
-// This class owns itself and gets deleted when WebContents is deleted.
+// This class owns itself and gets deleted when the Java WebContents is deleted.
class RenderWidgetHostConnector {
public:
explicit RenderWidgetHostConnector(WebContents* web_contents);
diff --git a/chromium/content/browser/android/synchronous_compositor_host.cc b/chromium/content/browser/android/synchronous_compositor_host.cc
index c5ec129e653..56b6796c424 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.cc
+++ b/chromium/content/browser/android/synchronous_compositor_host.cc
@@ -233,6 +233,7 @@ void SynchronousCompositorHost::UpdateFrameMetaData(
return;
}
frame_metadata_version_ = version;
+ UpdatePresentedFrameToken(frame_metadata.frame_token);
rwhva_->SynchronousFrameMetadata(std::move(frame_metadata));
}
@@ -413,8 +414,19 @@ void SynchronousCompositorHost::ReturnResources(
}
void SynchronousCompositorHost::DidPresentCompositorFrames(
- viz::PresentationFeedbackMap feedbacks) {
+ viz::PresentationFeedbackMap feedbacks,
+ uint32_t frame_token) {
rwhva_->DidPresentCompositorFrames(feedbacks);
+ UpdatePresentedFrameToken(frame_token);
+}
+
+void SynchronousCompositorHost::UpdatePresentedFrameToken(
+ uint32_t frame_token) {
+ if (!viz::FrameTokenGT(frame_token, last_frame_token_))
+ return;
+ last_frame_token_ = frame_token;
+ rwhva_->FrameTokenChangedForSynchronousCompositor(frame_token,
+ root_scroll_offset_);
}
void SynchronousCompositorHost::SetMemoryPolicy(size_t bytes_limit) {
diff --git a/chromium/content/browser/android/synchronous_compositor_host.h b/chromium/content/browser/android/synchronous_compositor_host.h
index 81648e7b776..920f49da28f 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.h
+++ b/chromium/content/browser/android/synchronous_compositor_host.h
@@ -54,8 +54,8 @@ class SynchronousCompositorHost : public SynchronousCompositor,
void ReturnResources(
uint32_t layer_tree_frame_sink_id,
const std::vector<viz::ReturnedResource>& resources) override;
- void DidPresentCompositorFrames(
- viz::PresentationFeedbackMap feedbacks) override;
+ void DidPresentCompositorFrames(viz::PresentationFeedbackMap feedbacks,
+ uint32_t frame_token) override;
void SetMemoryPolicy(size_t bytes_limit) override;
void DidBecomeActive() override;
void DidChangeRootLayerScrollOffset(
@@ -109,6 +109,7 @@ class SynchronousCompositorHost : public SynchronousCompositor,
// handle blocking calls.
bool IsReadyForSynchronousCall();
void UpdateRootLayerStateOnClient();
+ void UpdatePresentedFrameToken(uint32_t frame_token);
RenderWidgetHostViewAndroid* const rwhva_;
SynchronousCompositorClient* const client_;
@@ -159,6 +160,9 @@ class SynchronousCompositorHost : public SynchronousCompositor,
float min_page_scale_factor_ = 0.f;
float max_page_scale_factor_ = 0.f;
+ // From viz display.
+ uint32_t last_frame_token_ = 0u;
+
scoped_refptr<SynchronousCompositorSyncCallBridge> bridge_;
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorHost);
diff --git a/chromium/content/browser/android/web_contents_observer_proxy.cc b/chromium/content/browser/android/web_contents_observer_proxy.cc
index 185ace0caea..6cfd351f6ad 100644
--- a/chromium/content/browser/android/web_contents_observer_proxy.cc
+++ b/chromium/content/browser/android/web_contents_observer_proxy.cc
@@ -132,6 +132,7 @@ void WebContentsObserverProxy::DidStartNavigation(
Java_WebContentsObserverProxy_didStartNavigation(
AttachCurrentThread(), java_observer_,
static_cast<NavigationHandleImpl*>(navigation_handle)
+ ->navigation_request()
->java_navigation_handle());
}
@@ -140,6 +141,7 @@ void WebContentsObserverProxy::DidRedirectNavigation(
Java_WebContentsObserverProxy_didRedirectNavigation(
AttachCurrentThread(), java_observer_,
static_cast<NavigationHandleImpl*>(navigation_handle)
+ ->navigation_request()
->java_navigation_handle());
}
@@ -151,6 +153,7 @@ void WebContentsObserverProxy::DidFinishNavigation(
Java_WebContentsObserverProxy_didFinishNavigation(
AttachCurrentThread(), java_observer_,
static_cast<NavigationHandleImpl*>(navigation_handle)
+ ->navigation_request()
->java_navigation_handle());
}
diff --git a/chromium/content/browser/appcache/appcache_backend_impl.cc b/chromium/content/browser/appcache/appcache_backend_impl.cc
index c72648fad0c..cad776b7a36 100644
--- a/chromium/content/browser/appcache/appcache_backend_impl.cc
+++ b/chromium/content/browser/appcache/appcache_backend_impl.cc
@@ -27,51 +27,16 @@ AppCacheBackendImpl::AppCacheBackendImpl(AppCacheServiceImpl* service,
}
AppCacheBackendImpl::~AppCacheBackendImpl() {
- hosts_.clear();
service_->UnregisterBackend(this);
}
void AppCacheBackendImpl::RegisterHost(
blink::mojom::AppCacheHostRequest host_request,
blink::mojom::AppCacheFrontendPtr frontend,
- int32_t id,
- int32_t render_frame_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (GetHost(id)) {
- mojo::ReportBadMessage("ACDH_REGISTER");
- return;
- }
-
- // The AppCacheHost could have been precreated in which case we want to
- // register it with the backend here.
- std::unique_ptr<AppCacheHost> host =
- AppCacheNavigationHandleCore::GetPrecreatedHost(id);
- if (host) {
- // Switch the frontend proxy so that the host can make IPC calls from
- // here on.
- host->set_frontend(std::move(frontend), render_frame_id);
- } else {
- if (id < 0) {
- // Negative ids correspond to precreated hosts. We should be able to
- // retrieve one, but currently we have a race between this IPC and
- // browser removing the corresponding frame and precreated AppCacheHost.
- // Instead of crashing the renderer or returning wrong host, we do not
- // bind any host and let renderer do nothing until it is destroyed by
- // the request from browser.
- return;
- }
- host = std::make_unique<AppCacheHost>(id, process_id(), render_frame_id,
- std::move(frontend), service_);
- }
-
- host->BindRequest(std::move(host_request));
- hosts_.emplace(std::piecewise_construct, std::forward_as_tuple(id),
- std::forward_as_tuple(std::move(host)));
-}
-
-void AppCacheBackendImpl::UnregisterHost(int32_t id) {
- if (!hosts_.erase(id))
- mojo::ReportBadMessage("ACDH_UNREGISTER");
+ const base::UnguessableToken& host_id) {
+ service_->RegisterHostInternal(std::move(host_request), std::move(frontend),
+ host_id, MSG_ROUTING_NONE, process_id_,
+ mojo::GetBadMessageCallback());
}
} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_backend_impl.h b/chromium/content/browser/appcache/appcache_backend_impl.h
index a4ff77dd138..7a98e7a2fc3 100644
--- a/chromium/content/browser/appcache/appcache_backend_impl.h
+++ b/chromium/content/browser/appcache/appcache_backend_impl.h
@@ -27,25 +27,13 @@ class CONTENT_EXPORT AppCacheBackendImpl
// blink::mojom::AppCacheBackend
void RegisterHost(blink::mojom::AppCacheHostRequest host_request,
blink::mojom::AppCacheFrontendPtr frontend,
- int32_t host_id,
- int32_t render_frame_id) override;
- void UnregisterHost(int32_t host_id);
-
- // Returns a pointer to a registered host. The backend retains ownership.
- AppCacheHost* GetHost(int host_id) {
- auto it = hosts_.find(host_id);
- return (it != hosts_.end()) ? (it->second.get()) : nullptr;
- }
-
- using HostMap = std::unordered_map<int, std::unique_ptr<AppCacheHost>>;
- const HostMap& hosts() { return hosts_; }
+ const base::UnguessableToken& host_id) override;
private:
// Raw pointer is safe because instances of this class are owned by
// |service_|.
AppCacheServiceImpl* service_;
int process_id_;
- HostMap hosts_;
DISALLOW_COPY_AND_ASSIGN(AppCacheBackendImpl);
};
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.cc b/chromium/content/browser/appcache/appcache_disk_cache.cc
index d38e9ed58d5..27d668ad228 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache.cc
+++ b/chromium/content/browser/appcache/appcache_disk_cache.cc
@@ -209,16 +209,16 @@ AppCacheDiskCache::~AppCacheDiskCache() {
net::Error AppCacheDiskCache::InitWithDiskBackend(
const base::FilePath& disk_cache_directory,
- int disk_cache_size,
bool force,
base::OnceClosure post_cleanup_callback,
net::CompletionOnceCallback callback) {
- return Init(net::APP_CACHE, disk_cache_directory, disk_cache_size, force,
+ return Init(net::APP_CACHE, disk_cache_directory,
+ std::numeric_limits<int64_t>::max(), force,
std::move(post_cleanup_callback), std::move(callback));
}
net::Error AppCacheDiskCache::InitWithMemBackend(
- int mem_cache_size,
+ int64_t mem_cache_size,
net::CompletionOnceCallback callback) {
return Init(net::MEMORY_CACHE, base::FilePath(), mem_cache_size, false,
base::OnceClosure(), std::move(callback));
@@ -339,7 +339,7 @@ AppCacheDiskCache::PendingCall::~PendingCall() = default;
net::Error AppCacheDiskCache::Init(net::CacheType cache_type,
const base::FilePath& cache_directory,
- int cache_size,
+ int64_t cache_size,
bool force,
base::OnceClosure post_cleanup_callback,
net::CompletionOnceCallback callback) {
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.h b/chromium/content/browser/appcache/appcache_disk_cache.h
index 82309a1502f..cb9eca5745a 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache.h
+++ b/chromium/content/browser/appcache/appcache_disk_cache.h
@@ -66,14 +66,13 @@ class CONTENT_EXPORT AppCacheDiskCache {
// Initializes the object to use disk backed storage.
net::Error InitWithDiskBackend(const base::FilePath& disk_cache_directory,
- int disk_cache_size,
bool force,
base::OnceClosure post_cleanup_callback,
net::CompletionOnceCallback callback);
// Initializes the object to use memory only storage.
// This is used for Chrome's incognito browsing.
- net::Error InitWithMemBackend(int disk_cache_size,
+ net::Error InitWithMemBackend(int64_t disk_cache_size,
net::CompletionOnceCallback callback);
void Disable();
@@ -141,7 +140,7 @@ class CONTENT_EXPORT AppCacheDiskCache {
net::Error Init(net::CacheType cache_type,
const base::FilePath& directory,
- int cache_size,
+ int64_t cache_size,
bool force,
base::OnceClosure post_cleanup_callback,
net::CompletionOnceCallback callback);
diff --git a/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc b/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
index 8f382da2538..fea5e706d04 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
@@ -55,7 +55,7 @@ TEST_F(AppCacheDiskCacheTest, DisablePriorToInitCompletion) {
// one of each kind of "entry" function.
std::unique_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache);
EXPECT_FALSE(disk_cache->is_disabled());
- disk_cache->InitWithDiskBackend(directory_.GetPath(), k10MBytes, false,
+ disk_cache->InitWithDiskBackend(directory_.GetPath(), false,
base::OnceClosure(), completion_callback_);
disk_cache->CreateEntry(1, &entry, completion_callback_);
disk_cache->OpenEntry(2, &entry, completion_callback_);
@@ -85,7 +85,7 @@ TEST_F(AppCacheDiskCacheTest, DisableAfterInitted) {
// Create an instance and let it fully init.
std::unique_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache);
EXPECT_FALSE(disk_cache->is_disabled());
- disk_cache->InitWithDiskBackend(directory_.GetPath(), k10MBytes, false,
+ disk_cache->InitWithDiskBackend(directory_.GetPath(), false,
base::OnceClosure(), completion_callback_);
FlushCacheTasks();
EXPECT_EQ(1u, completion_results_.size());
@@ -120,7 +120,7 @@ TEST_F(AppCacheDiskCacheTest, DISABLED_DisableWithEntriesOpen) {
// Create an instance and let it fully init.
std::unique_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache);
EXPECT_FALSE(disk_cache->is_disabled());
- disk_cache->InitWithDiskBackend(directory_.GetPath(), k10MBytes, false,
+ disk_cache->InitWithDiskBackend(directory_.GetPath(), false,
base::OnceClosure(), completion_callback_);
FlushCacheTasks();
EXPECT_EQ(1u, completion_results_.size());
@@ -187,7 +187,7 @@ TEST_F(AppCacheDiskCacheTest, CleanupCallback) {
net::TestCompletionCallback init_done;
std::unique_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache);
EXPECT_FALSE(disk_cache->is_disabled());
- disk_cache->InitWithDiskBackend(directory_.GetPath(), k10MBytes, false,
+ disk_cache->InitWithDiskBackend(directory_.GetPath(), false,
cleanup_done.closure(), init_done.callback());
EXPECT_EQ(net::OK, init_done.WaitForResult());
diff --git a/chromium/content/browser/appcache/appcache_fuzzer.cc b/chromium/content/browser/appcache/appcache_fuzzer.cc
index 6727d2be657..222aff93d1a 100644
--- a/chromium/content/browser/appcache/appcache_fuzzer.cc
+++ b/chromium/content/browser/appcache/appcache_fuzzer.cc
@@ -146,21 +146,25 @@ DEFINE_BINARY_PROTO_FUZZER(const fuzzing::proto::Session& session) {
// Create a context for mojo::ReportBadMessage.
mojo::Message message;
auto dispatch_context =
- std::make_unique<mojo::internal::MessageDispatchContext>(&message);
+ std::make_unique<mojo::internal::MessageDispatchContext>(&message);
blink::mojom::AppCacheBackendPtr host;
SingletonEnv().appcache_service->CreateBackend(/*process_id=*/1,
mojo::MakeRequest(&host));
std::map<int, blink::mojom::AppCacheHostPtr> registered_hosts;
+ std::map<int, base::UnguessableToken> registered_host_ids_;
for (const fuzzing::proto::Command& command : session.commands()) {
switch (command.command_case()) {
case fuzzing::proto::Command::kRegisterHost: {
int32_t host_id = command.register_host().host_id();
+ auto& host_id_token = registered_host_ids_[host_id];
+ if (host_id_token.is_empty())
+ host_id_token = base::UnguessableToken::Create();
blink::mojom::AppCacheFrontendPtr frontend;
mojo::MakeRequest(&frontend);
host->RegisterHost(mojo::MakeRequest(&registered_hosts[host_id]),
- std::move(frontend), host_id, MSG_ROUTING_NONE);
+ std::move(frontend), host_id_token);
break;
}
case fuzzing::proto::Command::kUnregisterHost: {
@@ -192,7 +196,10 @@ DEFINE_BINARY_PROTO_FUZZER(const fuzzing::proto::Session& session) {
break;
int32_t spawning_host_id =
command.set_spawning_host_id().spawning_host_id();
- host_it->second->SetSpawningHostId(spawning_host_id);
+ auto& spawning_host_id_token = registered_host_ids_[spawning_host_id];
+ if (spawning_host_id_token.is_empty())
+ spawning_host_id_token = base::UnguessableToken::Create();
+ host_it->second->SetSpawningHostId(spawning_host_id_token);
break;
}
case fuzzing::proto::Command::kSelectCacheForSharedWorker: {
diff --git a/chromium/content/browser/appcache/appcache_group_unittest.cc b/chromium/content/browser/appcache/appcache_group_unittest.cc
index 69910844429..90130b476dc 100644
--- a/chromium/content/browser/appcache/appcache_group_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_group_unittest.cc
@@ -23,8 +23,7 @@ namespace {
class TestAppCacheFrontend : public blink::mojom::AppCacheFrontend {
public:
TestAppCacheFrontend()
- : last_host_id_(-1),
- last_cache_id_(-1),
+ : last_cache_id_(-1),
last_status_(blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE) {}
void CacheSelected(blink::mojom::AppCacheInfoPtr info) override {
@@ -48,16 +47,18 @@ class TestAppCacheFrontend : public blink::mojom::AppCacheFrontend {
void SetSubresourceFactory(
network::mojom::URLLoaderFactoryPtr url_loader_factory) override {}
- blink::mojom::AppCacheFrontendPtr Bind(int32_t host_id) {
+ blink::mojom::AppCacheFrontendPtr Bind(
+ const base::UnguessableToken& host_id) {
blink::mojom::AppCacheFrontendPtr result;
bindings_.AddBinding(this, mojo::MakeRequest(&result), host_id);
return result;
}
- int32_t last_host_id_;
+ base::UnguessableToken last_host_id_;
int64_t last_cache_id_;
blink::mojom::AppCacheStatus last_status_;
- mojo::BindingSet<blink::mojom::AppCacheFrontend, int32_t> bindings_;
+ mojo::BindingSet<blink::mojom::AppCacheFrontend, base::UnguessableToken>
+ bindings_;
};
} // namespace
@@ -81,7 +82,7 @@ class TestUpdateObserver : public AppCacheGroup::UpdateObserver {
class TestAppCacheHost : public AppCacheHost {
public:
- TestAppCacheHost(int host_id,
+ TestAppCacheHost(const base::UnguessableToken& host_id,
TestAppCacheFrontend* frontend,
AppCacheServiceImpl* service)
: AppCacheHost(host_id,
@@ -179,10 +180,14 @@ TEST_F(AppCacheGroupTest, CleanupUnusedGroup) {
AppCacheGroup* group =
new AppCacheGroup(service.storage(), GURL("http://foo.com"), 111);
- AppCacheHost host1(/*host_id=*/1, /*process_id=*/1, /*render_frame_id=*/1,
- frontend.Bind(/*host_id=*/1), &service);
- AppCacheHost host2(/*host_id=*/2, /*process_id=*/2, /*render_frame_id=*/2,
- frontend.Bind(/*host_id=*/2), &service);
+ auto host1_id = base::UnguessableToken::Create();
+ AppCacheHost host1(host1_id,
+ /*process_id=*/1, /*render_frame_id=*/1,
+ frontend.Bind(host1_id), &service);
+ auto host2_id = base::UnguessableToken::Create();
+ AppCacheHost host2(host2_id,
+ /*process_id=*/2, /*render_frame_id=*/2,
+ frontend.Bind(host2_id), &service);
base::Time now = base::Time::Now();
@@ -277,7 +282,7 @@ TEST_F(AppCacheGroupTest, QueueUpdate) {
EXPECT_TRUE(group->update_job_->IsTerminating());
TestAppCacheFrontend frontend;
- TestAppCacheHost host(1, &frontend, &service);
+ TestAppCacheHost host(base::UnguessableToken::Create(), &frontend, &service);
host.new_master_entry_url_ = GURL("http://foo.com/bar.txt");
group->StartUpdateWithNewMasterEntry(&host, host.new_master_entry_url_);
EXPECT_FALSE(group->queued_updates_.empty());
diff --git a/chromium/content/browser/appcache/appcache_host.cc b/chromium/content/browser/appcache/appcache_host.cc
index d6ed8eb67b2..68d690d945b 100644
--- a/chromium/content/browser/appcache/appcache_host.cc
+++ b/chromium/content/browser/appcache/appcache_host.cc
@@ -59,16 +59,13 @@ blink::mojom::AppCacheInfoPtr CreateCacheInfo(
} // namespace
-AppCacheHost::AppCacheHost(int host_id,
+AppCacheHost::AppCacheHost(const base::UnguessableToken& host_id,
int process_id,
int render_frame_id,
blink::mojom::AppCacheFrontendPtr frontend,
AppCacheServiceImpl* service)
: host_id_(host_id),
process_id_(process_id),
- spawning_host_id_(blink::mojom::kAppCacheNoHostId),
- parent_host_id_(blink::mojom::kAppCacheNoHostId),
- parent_process_id_(0),
pending_main_resource_cache_id_(blink::mojom::kAppCacheNoCacheId),
pending_selected_cache_id_(blink::mojom::kAppCacheNoCacheId),
was_select_cache_called_(false),
@@ -126,7 +123,7 @@ void AppCacheHost::RemoveObserver(Observer* observer) {
}
void AppCacheHost::Unregister() {
- service_->GetBackend(process_id_)->UnregisterHost(host_id_);
+ service_->EraseHost(host_id_);
}
void AppCacheHost::SelectCache(const GURL& document_url,
@@ -328,19 +325,13 @@ void AppCacheHost::DoPendingSwapCache() {
std::move(pending_swap_cache_callback_).Run(success);
}
-void AppCacheHost::SetSpawningHostId(int spawning_host_id) {
+void AppCacheHost::SetSpawningHostId(
+ const base::UnguessableToken& spawning_host_id) {
spawning_host_id_ = spawning_host_id;
}
const AppCacheHost* AppCacheHost::GetSpawningHost() const {
- AppCacheBackendImpl* backend = service_->GetBackend(process_id_);
- return backend ? backend->GetHost(spawning_host_id_) : nullptr;
-}
-
-AppCacheHost* AppCacheHost::GetParentAppCacheHost() const {
- DCHECK(is_for_dedicated_worker());
- AppCacheBackendImpl* backend = service_->GetBackend(parent_process_id_);
- return backend ? backend->GetHost(parent_host_id_) : nullptr;
+ return service_->GetHost(spawning_host_id_);
}
void AppCacheHost::GetResourceList(GetResourceListCallback callback) {
@@ -361,14 +352,6 @@ std::unique_ptr<AppCacheRequestHandler> AppCacheHost::CreateRequestHandler(
std::unique_ptr<AppCacheRequest> request,
ResourceType resource_type,
bool should_reset_appcache) {
- if (is_for_dedicated_worker()) {
- AppCacheHost* parent_host = GetParentAppCacheHost();
- if (parent_host)
- return parent_host->CreateRequestHandler(
- std::move(request), resource_type, should_reset_appcache);
- return nullptr;
- }
-
if (AppCacheRequestHandler::IsMainResourceType(resource_type)) {
// Store the first party origin so that it can be used later in SelectCache
// for checking whether the creation of the appcache is allowed.
diff --git a/chromium/content/browser/appcache/appcache_host.h b/chromium/content/browser/appcache/appcache_host.h
index 8653c572caf..d71c73e85e4 100644
--- a/chromium/content/browser/appcache/appcache_host.h
+++ b/chromium/content/browser/appcache/appcache_host.h
@@ -70,7 +70,7 @@ class CONTENT_EXPORT AppCacheHost : public blink::mojom::AppCacheHost,
virtual ~Observer() {}
};
- AppCacheHost(int host_id,
+ AppCacheHost(const base::UnguessableToken& host_id,
int process_id,
int render_frame_id,
blink::mojom::AppCacheFrontendPtr frontend,
@@ -96,7 +96,8 @@ class CONTENT_EXPORT AppCacheHost : public blink::mojom::AppCacheHost,
void GetStatus(GetStatusCallback callback) override;
void StartUpdate(StartUpdateCallback callback) override;
void SwapCache(SwapCacheCallback callback) override;
- void SetSpawningHostId(int spawning_host_id) override;
+ void SetSpawningHostId(
+ const base::UnguessableToken& spawning_host_id) override;
void GetResourceList(GetResourceListCallback callback) override;
// May return NULL if the spawning host context has been closed, or if a
@@ -158,7 +159,7 @@ class CONTENT_EXPORT AppCacheHost : public blink::mojom::AppCacheHost,
// with which pending master entries.
const GURL& pending_master_entry_url() const { return new_master_entry_url_; }
- int host_id() const { return host_id_; }
+ const base::UnguessableToken& host_id() const { return host_id_; }
int process_id() const {
DCHECK_NE(process_id_, ChildProcessHost::kInvalidUniqueID);
@@ -253,19 +254,10 @@ class CONTENT_EXPORT AppCacheHost : public blink::mojom::AppCacheHost,
// AppCacheGroup::UpdateObserver methods.
void OnUpdateComplete(AppCacheGroup* group) override;
- // Returns true if this host is for a dedicated worker context.
- bool is_for_dedicated_worker() const {
- return parent_host_id_ != blink::mojom::kAppCacheNoHostId;
- }
-
void OnAppCacheAccessed(const GURL& manifest_url, bool blocked);
- // Returns the parent context's host instance. This is only valid
- // to call when this instance is_for_dedicated_worker.
- AppCacheHost* GetParentAppCacheHost() const;
-
// Identifies the corresponding appcache host in the child process.
- int host_id_;
+ const base::UnguessableToken host_id_;
// Identifies the renderer process associated with the AppCacheHost. Used for
// security checks via ChildProcessSecurityPolicyImpl::CanAccessDataForOrigin.
@@ -274,17 +266,9 @@ class CONTENT_EXPORT AppCacheHost : public blink::mojom::AppCacheHost,
// Information about the host that created this one; the manifest
// preferred by our creator influences which cache our main resource
// should be loaded from.
- int spawning_host_id_;
+ base::UnguessableToken spawning_host_id_;
GURL preferred_manifest_url_;
- // Hosts for dedicated workers are special cased to shunt
- // request handling off to the dedicated worker's parent.
- // The scriptable api is not accessible in dedicated workers
- // so the other aspects of this class are not relevant for
- // these special case instances.
- int parent_host_id_;
- int parent_process_id_;
-
// Defined prior to refs to AppCaches and Groups because destruction
// order matters, the disabled_storage_reference_ must outlive those
// objects. See additional comments for the storage_ member.
diff --git a/chromium/content/browser/appcache/appcache_host_unittest.cc b/chromium/content/browser/appcache/appcache_host_unittest.cc
index fc13cb4ac62..f13a3144942 100644
--- a/chromium/content/browser/appcache/appcache_host_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_host_unittest.cc
@@ -34,12 +34,6 @@
namespace content {
-namespace {
-
-constexpr int kHostIdForTest = 123;
-
-} // namespace
-
class AppCacheHostTest : public testing::Test {
public:
AppCacheHostTest()
@@ -164,6 +158,8 @@ class AppCacheHostTest : public testing::Test {
const int kProcessIdForTest;
const int kRenderFrameIdForTest;
+ const base::UnguessableToken kHostIdForTest =
+ base::UnguessableToken::Create();
// Mock classes for the 'host' to work with
MockAppCacheService service_;
diff --git a/chromium/content/browser/appcache/appcache_interceptor.cc b/chromium/content/browser/appcache/appcache_interceptor.cc
index 3e4c514dd6f..7cd936e4beb 100644
--- a/chromium/content/browser/appcache/appcache_interceptor.cc
+++ b/chromium/content/browser/appcache/appcache_interceptor.cc
@@ -37,22 +37,18 @@ AppCacheRequestHandler* AppCacheInterceptor::GetHandler(
request->GetUserData(&kHandlerKey));
}
-void AppCacheInterceptor::SetExtraRequestInfo(net::URLRequest* request,
- AppCacheServiceImpl* service,
- int process_id,
- int host_id,
- ResourceType resource_type,
- bool should_reset_appcache) {
- if (!service || (host_id == blink::mojom::kAppCacheNoHostId))
- return;
-
- AppCacheBackendImpl* backend = service->GetBackend(process_id);
- if (!backend)
+void AppCacheInterceptor::SetExtraRequestInfo(
+ net::URLRequest* request,
+ AppCacheServiceImpl* service,
+ const base::UnguessableToken& host_id,
+ ResourceType resource_type,
+ bool should_reset_appcache) {
+ if (!service || host_id.is_empty())
return;
// TODO(michaeln): An invalid host id is indicative of bad data
// from a child process. How should we handle that here?
- AppCacheHost* host = backend->GetHost(host_id);
+ AppCacheHost* host = service->GetHost(host_id);
if (!host)
return;
diff --git a/chromium/content/browser/appcache/appcache_interceptor.h b/chromium/content/browser/appcache/appcache_interceptor.h
index 6658220ddd4..8eed205bd95 100644
--- a/chromium/content/browser/appcache/appcache_interceptor.h
+++ b/chromium/content/browser/appcache/appcache_interceptor.h
@@ -10,6 +10,7 @@
#include <memory>
#include "base/macros.h"
+#include "base/unguessable_token.h"
#include "content/common/content_export.h"
#include "content/public/common/resource_type.h"
#include "net/url_request/url_request_interceptor.h"
@@ -32,8 +33,7 @@ class CONTENT_EXPORT AppCacheInterceptor : public net::URLRequestInterceptor {
// Must be called to make a request eligible for retrieval from an appcache.
static void SetExtraRequestInfo(net::URLRequest* request,
AppCacheServiceImpl* service,
- int process_id,
- int host_id,
+ const base::UnguessableToken& host_id,
ResourceType resource_type,
bool should_reset_appcache);
diff --git a/chromium/content/browser/appcache/appcache_internals_ui.cc b/chromium/content/browser/appcache/appcache_internals_ui.cc
index b05f3cc58a4..ca6fb2c6863 100644
--- a/chromium/content/browser/appcache/appcache_internals_ui.cc
+++ b/chromium/content/browser/appcache/appcache_internals_ui.cc
@@ -380,7 +380,6 @@ AppCacheInternalsUI::AppCacheInternalsUI(WebUI* web_ui)
source->AddResourcePath("appcache_internals.js", IDR_APPCACHE_INTERNALS_JS);
source->AddResourcePath("appcache_internals.css", IDR_APPCACHE_INTERNALS_CSS);
source->SetDefaultResource(IDR_APPCACHE_INTERNALS_HTML);
- source->UseGzip();
WebUIDataSource::Add(browser_context(), source);
diff --git a/chromium/content/browser/appcache/appcache_navigation_handle.cc b/chromium/content/browser/appcache/appcache_navigation_handle.cc
index d8887db8181..4ffc31cc4a9 100644
--- a/chromium/content/browser/appcache/appcache_navigation_handle.cc
+++ b/chromium/content/browser/appcache/appcache_navigation_handle.cc
@@ -11,18 +11,12 @@
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
-namespace {
-// 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;
-}
-
namespace content {
AppCacheNavigationHandle::AppCacheNavigationHandle(
ChromeAppCacheService* appcache_service,
int process_id)
- : appcache_host_id_(g_next_appcache_host_id--),
+ : appcache_host_id_(base::UnguessableToken::Create()),
core_(std::make_unique<AppCacheNavigationHandleCore>(appcache_service,
appcache_host_id_,
process_id)) {
diff --git a/chromium/content/browser/appcache/appcache_navigation_handle.h b/chromium/content/browser/appcache/appcache_navigation_handle.h
index 61b5be8babb..5c5a5511a01 100644
--- a/chromium/content/browser/appcache/appcache_navigation_handle.h
+++ b/chromium/content/browser/appcache/appcache_navigation_handle.h
@@ -7,6 +7,7 @@
#include <memory>
#include "base/macros.h"
+#include "base/unguessable_token.h"
namespace content {
@@ -57,7 +58,9 @@ class AppCacheNavigationHandle {
int process_id);
~AppCacheNavigationHandle();
- int appcache_host_id() const { return appcache_host_id_; }
+ const base::UnguessableToken& appcache_host_id() const {
+ return appcache_host_id_;
+ }
AppCacheNavigationHandleCore* core() const { return core_.get(); }
// Called by NavigationHandleImpl::ReadyToCommitNavigation, because this is
@@ -71,7 +74,7 @@ class AppCacheNavigationHandle {
void SetProcessId(int process_id);
private:
- const int appcache_host_id_;
+ const base::UnguessableToken appcache_host_id_;
std::unique_ptr<AppCacheNavigationHandleCore> core_;
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 1e3fb27549c..f9adffb785c 100644
--- a/chromium/content/browser/appcache/appcache_navigation_handle_core.cc
+++ b/chromium/content/browser/appcache/appcache_navigation_handle_core.cc
@@ -25,7 +25,7 @@ namespace {
// Map of AppCache host id to the AppCacheNavigationHandleCore instance.
// Accessed on the IO thread only.
using AppCacheHandleMap =
- std::map <int, content::AppCacheNavigationHandleCore*>;
+ std::map<base::UnguessableToken, content::AppCacheNavigationHandleCore*>;
base::LazyInstance<AppCacheHandleMap>::DestructorAtExit g_appcache_handle_map =
LAZY_INSTANCE_INITIALIZER;
@@ -35,7 +35,7 @@ namespace content {
AppCacheNavigationHandleCore::AppCacheNavigationHandleCore(
ChromeAppCacheService* appcache_service,
- int appcache_host_id,
+ const base::UnguessableToken& appcache_host_id,
int process_id)
: appcache_service_(appcache_service),
appcache_host_id_(appcache_host_id),
@@ -43,6 +43,7 @@ AppCacheNavigationHandleCore::AppCacheNavigationHandleCore(
// The AppCacheNavigationHandleCore is created on the UI thread but
// should only be accessed from the IO thread afterwards.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!appcache_host_id_.is_empty());
}
AppCacheNavigationHandleCore::~AppCacheNavigationHandleCore() {
@@ -65,7 +66,7 @@ void AppCacheNavigationHandleCore::Initialize() {
// static
std::unique_ptr<AppCacheHost> AppCacheNavigationHandleCore::GetPrecreatedHost(
- int host_id) {
+ const base::UnguessableToken& host_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto index = g_appcache_handle_map.Get().find(host_id);
if (index != g_appcache_handle_map.Get().end()) {
diff --git a/chromium/content/browser/appcache/appcache_navigation_handle_core.h b/chromium/content/browser/appcache/appcache_navigation_handle_core.h
index 565b794f2a7..c6bb8d891b0 100644
--- a/chromium/content/browser/appcache/appcache_navigation_handle_core.h
+++ b/chromium/content/browser/appcache/appcache_navigation_handle_core.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/unguessable_token.h"
#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
@@ -32,7 +33,7 @@ class ChromeAppCacheService;
class AppCacheNavigationHandleCore {
public:
AppCacheNavigationHandleCore(ChromeAppCacheService* appcache_service,
- int appcache_host_id,
+ const base::UnguessableToken& appcache_host_id,
int process_id);
~AppCacheNavigationHandleCore();
@@ -44,7 +45,8 @@ class AppCacheNavigationHandleCore {
// Returns the precreated AppCacheHost pointer. Ownership of the host is
// released here.
- static std::unique_ptr<AppCacheHost> GetPrecreatedHost(int host_id);
+ static std::unique_ptr<AppCacheHost> GetPrecreatedHost(
+ const base::UnguessableToken& host_id);
AppCacheServiceImpl* GetAppCacheService();
@@ -57,7 +59,7 @@ class AppCacheNavigationHandleCore {
private:
std::unique_ptr<AppCacheHost> precreated_host_;
scoped_refptr<ChromeAppCacheService> appcache_service_;
- int appcache_host_id_;
+ const base::UnguessableToken appcache_host_id_;
int process_id_;
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 da9134122fb..023b98ca483 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler.cc
@@ -19,7 +19,7 @@
#include "content/browser/appcache/appcache_url_loader_job.h"
#include "content/browser/appcache/appcache_url_loader_request.h"
#include "content/browser/appcache/appcache_url_request_job.h"
-#include "content/common/navigation_subresource_loader_params.h"
+#include "content/browser/navigation_subresource_loader_params.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
#include "services/network/public/cpp/features.h"
diff --git a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
index 2e284bc464f..1f1432bae08 100644
--- a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
@@ -196,6 +196,8 @@ class AppCacheRequestHandlerTest
AppCacheRequestHandler::SetRunningInTests(true);
if (request_handler_type_ == URLLOADER)
feature_list_.InitAndEnableFeature(network::features::kNetworkService);
+ else
+ feature_list_.InitAndDisableFeature(network::features::kNetworkService);
}
~AppCacheRequestHandlerTest() {
@@ -222,15 +224,14 @@ class AppCacheRequestHandlerTest
mock_service_->set_request_context(empty_context_.get());
mock_policy_.reset(new MockAppCachePolicy);
mock_service_->set_appcache_policy(mock_policy_.get());
- backend_impl_ = std::make_unique<AppCacheBackendImpl>(mock_service_.get(),
- kMockProcessId);
- const int kHostId = 1;
+ const auto kHostId = base::UnguessableToken::Create();
const int kRenderFrameId = 2;
- blink::mojom::AppCacheFrontendPtr frontend;
+ blink::mojom::AppCacheFrontendPtrInfo frontend;
mojo::MakeRequest(&frontend);
- backend_impl_->RegisterHost(mojo::MakeRequest(&host_ptr_),
- std::move(frontend), kHostId, kRenderFrameId);
- host_ = backend_impl_->GetHost(kHostId);
+ mock_service_->RegisterHostForFrame(
+ mojo::MakeRequest(&host_ptr_), std::move(frontend), kHostId,
+ kRenderFrameId, kMockProcessId, GetBadMessageCallback());
+ host_ = mock_service_->GetHost(kHostId);
job_factory_.reset(new MockURLRequestJobFactory());
empty_context_->set_job_factory(job_factory_.get());
}
@@ -244,7 +245,6 @@ class AppCacheRequestHandlerTest
handler_.reset();
request_ = nullptr;
url_request_.reset();
- backend_impl_.reset();
mock_service_.reset();
mock_policy_.reset();
job_factory_.reset();
@@ -413,8 +413,8 @@ class AppCacheRequestHandlerTest
net::HttpResponseInfo info;
std::string headers =
base::StringPrintf("HTTP/1.1 %i Muffin\r\n\r\n", response_code);
- info.headers = new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length()));
+ info.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(headers));
if (request_handler_type_ == URLREQUEST) {
job_factory_->SetJob(std::make_unique<MockURLRequestJob>(
@@ -723,7 +723,7 @@ class AppCacheRequestHandlerTest
ResourceType::kSubResource));
EXPECT_TRUE(handler_.get());
- backend_impl_->UnregisterHost(1);
+ mock_service_->EraseHost(host_->host_id());
host_ = nullptr;
EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
@@ -748,7 +748,7 @@ class AppCacheRequestHandlerTest
EXPECT_TRUE(job());
EXPECT_TRUE(job()->IsWaiting());
- backend_impl_->UnregisterHost(1);
+ mock_service_->EraseHost(host_->host_id());
host_ = nullptr;
if (request_handler_type_ == URLREQUEST) {
@@ -776,7 +776,6 @@ class AppCacheRequestHandlerTest
SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
EXPECT_TRUE(job());
- backend_impl_.reset();
mock_service_.reset();
mock_policy_.reset();
host_ = nullptr;
@@ -893,6 +892,13 @@ class AppCacheRequestHandlerTest
return cache;
}
+ mojo::ReportBadMessageCallback GetBadMessageCallback() {
+ return base::BindOnce(&AppCacheRequestHandlerTest::OnBadMessage,
+ base::Unretained(this));
+ }
+
+ void OnBadMessage(const std::string& reason) { NOTREACHED(); }
+
MockAppCacheStorage* mock_storage() {
return reinterpret_cast<MockAppCacheStorage*>(mock_service_->storage());
}
@@ -929,7 +935,6 @@ class AppCacheRequestHandlerTest
std::unique_ptr<base::WaitableEvent> test_finished_event_;
base::stack<base::OnceClosure> task_stack_;
std::unique_ptr<MockAppCacheService> mock_service_;
- std::unique_ptr<AppCacheBackendImpl> backend_impl_;
std::unique_ptr<MockAppCachePolicy> mock_policy_;
AppCacheHost* host_;
blink::mojom::AppCacheHostPtr host_ptr_;
diff --git a/chromium/content/browser/appcache/appcache_service_impl.cc b/chromium/content/browser/appcache/appcache_service_impl.cc
index 515f6411411..575ff93e38d 100644
--- a/chromium/content/browser/appcache/appcache_service_impl.cc
+++ b/chromium/content/browser/appcache/appcache_service_impl.cc
@@ -21,6 +21,8 @@
#include "content/browser/appcache/appcache_backend_impl.h"
#include "content/browser/appcache/appcache_entry.h"
#include "content/browser/appcache/appcache_histograms.h"
+#include "content/browser/appcache/appcache_host.h"
+#include "content/browser/appcache/appcache_navigation_handle_core.h"
#include "content/browser/appcache/appcache_policy.h"
#include "content/browser/appcache/appcache_quota_client.h"
#include "content/browser/appcache/appcache_response.h"
@@ -405,6 +407,7 @@ AppCacheServiceImpl::AppCacheServiceImpl(
AppCacheServiceImpl::~AppCacheServiceImpl() {
DCHECK(backends_.empty());
+ hosts_.clear();
for (auto& observer : observers_)
observer.OnServiceDestructionImminent(this);
for (auto& helper : pending_helpers_)
@@ -515,4 +518,59 @@ void AppCacheServiceImpl::UnregisterBackend(
backends_.erase(backend_impl->process_id());
}
+AppCacheHost* AppCacheServiceImpl::GetHost(
+ const base::UnguessableToken& host_id) {
+ auto it = hosts_.find(host_id);
+ return (it != hosts_.end()) ? (it->second.get()) : nullptr;
+}
+
+bool AppCacheServiceImpl::EraseHost(const base::UnguessableToken& host_id) {
+ return (hosts_.erase(host_id) != 0);
+}
+
+void AppCacheServiceImpl::RegisterHostForFrame(
+ blink::mojom::AppCacheHostRequest host_request,
+ blink::mojom::AppCacheFrontendPtrInfo frontend,
+ const base::UnguessableToken& host_id,
+ int32_t render_frame_id,
+ int process_id,
+ mojo::ReportBadMessageCallback bad_message_callback) {
+ blink::mojom::AppCacheFrontendPtr appcache_frontend_ptr(std::move(frontend));
+ RegisterHostInternal(
+ std::move(host_request), std::move(appcache_frontend_ptr), host_id,
+ render_frame_id, process_id, std::move(bad_message_callback));
+}
+
+void AppCacheServiceImpl::RegisterHostInternal(
+ blink::mojom::AppCacheHostRequest host_request,
+ blink::mojom::AppCacheFrontendPtr frontend,
+ const base::UnguessableToken& host_id,
+ int32_t render_frame_id,
+ int process_id,
+ mojo::ReportBadMessageCallback bad_message_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (GetHost(host_id)) {
+ std::move(bad_message_callback).Run("ACSI_REGISTER");
+ return;
+ }
+
+ // The AppCacheHost could have been precreated in which case we want to
+ // register it with the backend here.
+ std::unique_ptr<AppCacheHost> host =
+ AppCacheNavigationHandleCore::GetPrecreatedHost(host_id);
+ if (host) {
+ // Switch the frontend proxy so that the host can make IPC calls from
+ // here on.
+ host->set_frontend(std::move(frontend), render_frame_id);
+ } else {
+ host = std::make_unique<AppCacheHost>(host_id, process_id, render_frame_id,
+ std::move(frontend), this);
+ }
+
+ host->BindRequest(std::move(host_request));
+
+ hosts_.emplace(std::piecewise_construct, std::forward_as_tuple(host_id),
+ std::forward_as_tuple(std::move(host)));
+}
+
} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_service_impl.h b/chromium/content/browser/appcache/appcache_service_impl.h
index 4b3e4ec4982..5a6ffd5b767 100644
--- a/chromium/content/browser/appcache/appcache_service_impl.h
+++ b/chromium/content/browser/appcache/appcache_service_impl.h
@@ -24,6 +24,7 @@
#include "net/base/completion_once_callback.h"
#include "net/base/net_errors.h"
#include "storage/browser/quota/quota_manager_proxy.h"
+#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
namespace base {
class FilePath;
@@ -40,6 +41,7 @@ class SpecialStoragePolicy;
namespace content {
FORWARD_DECLARE_TEST(AppCacheServiceImplTest, ScheduleReinitialize);
class AppCacheBackendImpl;
+class AppCacheHost;
class AppCacheQuotaClient;
class AppCachePolicy;
class AppCacheServiceImplTest;
@@ -179,6 +181,17 @@ class CONTENT_EXPORT AppCacheServiceImpl : public AppCacheService {
return url_loader_factory_getter_.get();
}
+ // Returns a pointer to a registered host. It retains ownership.
+ AppCacheHost* GetHost(const base::UnguessableToken& host_id);
+ bool EraseHost(const base::UnguessableToken& host_id);
+ void RegisterHostForFrame(
+ blink::mojom::AppCacheHostRequest host_request,
+ blink::mojom::AppCacheFrontendPtrInfo frontend,
+ const base::UnguessableToken& host_id,
+ int32_t render_frame_id,
+ int process_id,
+ mojo::ReportBadMessageCallback bad_message_callback);
+
protected:
friend class content::AppCacheServiceImplTest;
friend class content::AppCacheStorageImplTest;
@@ -218,6 +231,21 @@ class CONTENT_EXPORT AppCacheServiceImpl : public AppCacheService {
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_;
private:
+ // TODO: Once we remove 'blink::mojom::AppCacheBackend', remove this together.
+ friend class content::AppCacheBackendImpl;
+
+ void RegisterHostInternal(
+ blink::mojom::AppCacheHostRequest host_request,
+ blink::mojom::AppCacheFrontendPtr frontend,
+ const base::UnguessableToken& host_id,
+ int32_t render_frame_id,
+ int process_id,
+ mojo::ReportBadMessageCallback bad_message_callback);
+ // The (process id, host id) pair that identifies one AppCacheHost.
+ using AppCacheHostProcessMap =
+ std::map<base::UnguessableToken, std::unique_ptr<AppCacheHost>>;
+ AppCacheHostProcessMap hosts_;
+
base::WeakPtrFactory<AppCacheServiceImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(AppCacheServiceImpl);
diff --git a/chromium/content/browser/appcache/appcache_storage_impl.cc b/chromium/content/browser/appcache/appcache_storage_impl.cc
index 4193784fd39..91f1d1614f5 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl.cc
+++ b/chromium/content/browser/appcache/appcache_storage_impl.cc
@@ -49,7 +49,6 @@ constexpr const int kMB = 1024 * 1024;
// Hard coded default when not using quota management.
constexpr const int kDefaultQuota = 5 * kMB;
-constexpr const int kMaxAppCacheDiskCacheSize = 250 * kMB;
constexpr const int kMaxAppCacheMemDiskCacheSize = 10 * kMB;
constexpr base::FilePath::CharType kDiskCacheDirectoryName[] =
@@ -83,14 +82,11 @@ bool DeleteGroupAndRelatedRecords(
} // namespace
-// Destroys |database|. If there is appcache data to be deleted
-// (|force_keep_session_state| is false), deletes session-only appcache data.
+// static
void AppCacheStorageImpl::ClearSessionOnlyOrigins(
- AppCacheDatabase* database,
+ std::unique_ptr<AppCacheDatabase> database,
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
bool force_keep_session_state) {
- std::unique_ptr<AppCacheDatabase> database_to_delete(database);
-
// If saving session state, only delete the database.
if (force_keep_session_state)
return;
@@ -129,8 +125,8 @@ void AppCacheStorageImpl::ClearSessionOnlyOrigins(
return;
}
std::vector<int64_t> deletable_response_ids;
- bool success = DeleteGroupAndRelatedRecords(database, group.group_id,
- &deletable_response_ids);
+ bool success = DeleteGroupAndRelatedRecords(
+ database.get(), group.group_id, &deletable_response_ids);
success = success && transaction.Commit();
DCHECK(success);
} // for each group
@@ -144,7 +140,7 @@ class AppCacheStorageImpl::DatabaseTask
public:
explicit DatabaseTask(AppCacheStorageImpl* storage)
: storage_(storage),
- database_(storage->database_),
+ database_(storage->database_.get()),
io_thread_(base::SequencedTaskRunnerHandle::Get()) {
DCHECK(io_thread_.get());
}
@@ -178,7 +174,7 @@ class AppCacheStorageImpl::DatabaseTask
virtual ~DatabaseTask() {}
AppCacheStorageImpl* storage_;
- AppCacheDatabase* database_;
+ AppCacheDatabase* const database_;
DelegateReferenceVector delegates_;
private:
@@ -186,7 +182,7 @@ class AppCacheStorageImpl::DatabaseTask
void CallRunCompleted(base::TimeTicks schedule_time);
void OnFatalError();
- scoped_refptr<base::SequencedTaskRunner> io_thread_;
+ const scoped_refptr<base::SequencedTaskRunner> io_thread_;
};
void AppCacheStorageImpl::DatabaseTask::Schedule() {
@@ -577,9 +573,10 @@ void AppCacheStorageImpl::GroupLoadTask::Run() {
database_->FindCacheForGroup(group_record_.group_id, &cache_record_) &&
FindRelatedCacheRecords(cache_record_.cache_id);
- if (success_)
+ if (success_) {
database_->LazyUpdateLastAccessTime(group_record_.group_id,
base::Time::Now());
+ }
}
void AppCacheStorageImpl::GroupLoadTask::RunCompleted() {
@@ -702,7 +699,7 @@ void AppCacheStorageImpl::StoreGroupAndCacheTask::OnQuotaCallback(
void AppCacheStorageImpl::StoreGroupAndCacheTask::Run() {
DCHECK(!success_);
- sql::Database* connection = database_->db_connection();
+ sql::Database* const connection = database_->db_connection();
if (!connection)
return;
@@ -898,7 +895,7 @@ class NetworkNamespaceHelper {
// Key is cache id
using WhiteListMap = std::map<int64_t, std::vector<AppCacheNamespace>>;
WhiteListMap namespaces_map_;
- AppCacheDatabase* database_;
+ AppCacheDatabase* const database_;
};
} // namespace
@@ -1411,13 +1408,12 @@ AppCacheStorageImpl::~AppCacheStorageImpl() {
if (database_ &&
!db_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&ClearSessionOnlyOrigins, database_,
- base::WrapRefCounted(
- service_->special_storage_policy()),
- service()->force_keep_session_state()))) {
- delete database_;
+ FROM_HERE,
+ base::BindOnce(
+ &ClearSessionOnlyOrigins, std::move(database_),
+ base::WrapRefCounted(service_->special_storage_policy()),
+ service()->force_keep_session_state()))) {
}
- database_ = nullptr; // So no further database tasks can be scheduled.
}
void AppCacheStorageImpl::Initialize(
@@ -1429,7 +1425,7 @@ void AppCacheStorageImpl::Initialize(
base::FilePath db_file_path;
if (!is_incognito_)
db_file_path = cache_directory_.Append(kAppCacheDatabaseName);
- database_ = new AppCacheDatabase(db_file_path);
+ database_ = std::make_unique<AppCacheDatabase>(db_file_path);
db_task_runner_ = db_task_runner;
@@ -1896,8 +1892,7 @@ AppCacheDiskCache* AppCacheStorageImpl::disk_cache() {
expecting_cleanup_complete_on_disable_ = true;
rv = disk_cache_->InitWithDiskBackend(
- cache_directory_.Append(kDiskCacheDirectoryName),
- kMaxAppCacheDiskCacheSize, false,
+ cache_directory_.Append(kDiskCacheDirectoryName), false,
base::BindOnce(&AppCacheStorageImpl::OnDiskCacheCleanupComplete,
weak_factory_.GetWeakPtr()),
base::BindOnce(&AppCacheStorageImpl::OnDiskCacheInitialized,
diff --git a/chromium/content/browser/appcache/appcache_storage_impl.h b/chromium/content/browser/appcache/appcache_storage_impl.h
index 528c26237a8..de16f252c3a 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl.h
+++ b/chromium/content/browser/appcache/appcache_storage_impl.h
@@ -130,8 +130,10 @@ class AppCacheStorageImpl : public AppCacheStorage {
void LazilyCommitLastAccessTimes();
void OnLazyCommitTimer();
+ // If there is appcache data to be deleted (|force_keep_session_state| is
+ // false), deletes session-only appcache data.
static void ClearSessionOnlyOrigins(
- AppCacheDatabase* database,
+ std::unique_ptr<AppCacheDatabase> database,
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
bool force_keep_session_state);
@@ -180,7 +182,7 @@ class AppCacheStorageImpl : public AppCacheStorage {
int64_t last_deletable_response_rowid_;
// Created on the IO thread, but only used on the DB thread.
- AppCacheDatabase* database_;
+ std::unique_ptr<AppCacheDatabase> database_;
// Set if we discover a fatal error like a corrupt SQL database or
// disk cache and cannot continue.
diff --git a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
index c58f47ef6e9..29635a748ac 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
@@ -65,6 +65,7 @@ using blink::mojom::StorageType;
namespace {
+constexpr int kMockProcessId = 1;
constexpr int kMockQuota = 5000;
// The Reinitialize test needs some http accessible resources to run,
@@ -1694,10 +1695,7 @@ class AppCacheStorageImplTest : public testing::Test {
}
void Continue_Reinitialize(ReinitTestCase test_case) {
- const int kMockProcessId = 1;
const int kMockRenderFrameId = MSG_ROUTING_NONE;
- backend_ =
- std::make_unique<AppCacheBackendImpl>(service_.get(), kMockProcessId);
if (test_case == CORRUPT_SQL_ON_INSTALL) {
// Break the db file
@@ -1710,9 +1708,11 @@ class AppCacheStorageImplTest : public testing::Test {
test_case == CORRUPT_SQL_ON_INSTALL) {
// Try to create a new appcache, the resulting update job will
// eventually fail when it gets to disk cache initialization.
- backend_->RegisterHost(blink::mojom::AppCacheHostRequest(),
- BindFrontend(), 1, kMockRenderFrameId);
- AppCacheHost* host1 = backend_->GetHost(1);
+ host1_id_ = base::UnguessableToken::Create();
+ service_->RegisterHostForFrame(
+ blink::mojom::AppCacheHostRequest(), BindFrontend(), host1_id_,
+ kMockRenderFrameId, kMockProcessId, GetBadMessageCallback());
+ AppCacheHost* host1 = service_->GetHost(host1_id_);
const GURL kEmptyPageUrl(GetMockUrl("empty.html"));
host1->SetFirstPartyUrlForTesting(kEmptyPageUrl);
host1->SelectCache(kEmptyPageUrl, blink::mojom::kAppCacheNoCacheId,
@@ -1722,9 +1722,11 @@ class AppCacheStorageImplTest : public testing::Test {
// Try to access the existing cache manifest.
// The URLRequestJob will eventually fail when it gets to disk
// cache initialization.
- backend_->RegisterHost(blink::mojom::AppCacheHostRequest(),
- BindFrontend(), 2, kMockRenderFrameId);
- AppCacheHost* host2 = backend_->GetHost(2);
+ host2_id_ = base::UnguessableToken::Create();
+ service_->RegisterHostForFrame(
+ blink::mojom::AppCacheHostRequest(), BindFrontend(), host2_id_,
+ kMockRenderFrameId, kMockProcessId, GetBadMessageCallback());
+ AppCacheHost* host2 = service_->GetHost(host2_id_);
network::ResourceRequest request;
request.url = GetMockUrl("manifest");
handler_ =
@@ -1757,20 +1759,21 @@ class AppCacheStorageImplTest : public testing::Test {
if (test_case == CORRUPT_CACHE_ON_INSTALL ||
test_case == CORRUPT_SQL_ON_INSTALL) {
EXPECT_TRUE(frontend_.error_event_was_raised_);
- AppCacheHost* host1 = backend_->GetHost(1);
+ AppCacheHost* host1 = service_->GetHost(host1_id_);
EXPECT_FALSE(host1->associated_cache());
EXPECT_FALSE(host1->group_being_updated_.get());
EXPECT_TRUE(host1->disabled_storage_reference_.get());
} else {
ASSERT_EQ(CORRUPT_CACHE_ON_LOAD_EXISTING, test_case);
- AppCacheHost* host2 = backend_->GetHost(2);
+ AppCacheHost* host2 = service_->GetHost(host2_id_);
EXPECT_TRUE(host2->disabled_storage_reference_.get());
}
// Cleanup and claim victory.
+ service_->EraseHost(host1_id_);
+ service_->EraseHost(host2_id_);
service_->RemoveObserver(observer_.get());
handler_.reset();
- backend_.reset();
observer_.reset();
TestFinished();
}
@@ -1783,16 +1786,23 @@ class AppCacheStorageImplTest : public testing::Test {
return static_cast<AppCacheStorageImpl*>(service()->storage());
}
- AppCacheDatabase* database() { return storage()->database_; }
+ AppCacheDatabase* database() { return storage()->database_.get(); }
MockStorageDelegate* delegate() { return delegate_.get(); }
- blink::mojom::AppCacheFrontendPtr BindFrontend() {
- blink::mojom::AppCacheFrontendPtr result;
+ blink::mojom::AppCacheFrontendPtrInfo BindFrontend() {
+ blink::mojom::AppCacheFrontendPtrInfo result;
frontend_bindings_.AddBinding(&frontend_, mojo::MakeRequest(&result));
return result;
}
+ mojo::ReportBadMessageCallback GetBadMessageCallback() {
+ return base::BindOnce(&AppCacheStorageImplTest::OnBadMessage,
+ base::Unretained(this));
+ }
+
+ void OnBadMessage(const std::string& reason) { NOTREACHED(); }
+
void MakeCacheAndGroup(const GURL& manifest_url,
int64_t group_id,
int64_t cache_id,
@@ -1845,6 +1855,9 @@ class AppCacheStorageImplTest : public testing::Test {
scoped_refptr<AppCache> cache_;
scoped_refptr<AppCache> cache2_;
+ base::UnguessableToken host1_id_;
+ base::UnguessableToken host2_id_;
+
// Specifically for the Reinitalize test.
base::test::ScopedFeatureList feature_list_;
base::ScopedTempDir temp_directory_;
@@ -2039,4 +2052,4 @@ TEST_F(AppCacheStorageImplTest, Reinitialize3) {
// That's all folks!
-} // namespace content \ No newline at end of file
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_subresource_url_factory.cc b/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
index 0476075eeef..7b065611ab4 100644
--- a/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
+++ b/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
@@ -253,8 +253,8 @@ class SubresourceLoader : public network::mojom::URLLoader,
std::move(ack_callback));
}
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {
- remote_client_->OnReceiveCachedMetadata(data);
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override {
+ remote_client_->OnReceiveCachedMetadata(std::move(data));
}
void OnTransferSizeUpdated(int32_t transfer_size_diff) override {
@@ -366,6 +366,7 @@ void AppCacheSubresourceURLFactory::CreateLoaderAndStart(
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
// TODO(943887): Replace HasSecurityState() call with something that can
// preserve security state after process shutdown. The security state check
// is a temporary solution to avoid crashes when this method is run after the
@@ -396,6 +397,14 @@ void AppCacheSubresourceURLFactory::CreateLoaderAndStart(
}
}
+ // Subresource requests from renderer processes should not be allowed to use
+ // network::mojom::FetchRequestMode::kNavigate.
+ if (request.fetch_request_mode ==
+ network::mojom::FetchRequestMode::kNavigate) {
+ mojo::ReportBadMessage("APPCACHE_SUBRESOURCE_URL_FACTORY_NAVIGATE");
+ return;
+ }
+
new SubresourceLoader(std::move(url_loader_request), routing_id, request_id,
options, request, std::move(client), traffic_annotation,
appcache_host_, network_loader_factory_);
diff --git a/chromium/content/browser/appcache/appcache_unittest.cc b/chromium/content/browser/appcache/appcache_unittest.cc
index f793d49e4a1..96b26b795e3 100644
--- a/chromium/content/browser/appcache/appcache_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_unittest.cc
@@ -32,11 +32,13 @@ TEST_F(AppCacheTest, CleanupUnusedCache) {
blink::mojom::AppCacheFrontendPtr frontend1;
mojo::MakeRequest(&frontend1);
- AppCacheHost host1(/*host_id=*/1, /*process_id=*/1, /*render_frame_id=*/1,
+ AppCacheHost host1(/*host_id=*/base::UnguessableToken::Create(),
+ /*process_id=*/1, /*render_frame_id=*/1,
std::move(frontend1), &service);
blink::mojom::AppCacheFrontendPtr frontend2;
mojo::MakeRequest(&frontend2);
- AppCacheHost host2(/*host_id=*/2, /*process_id=*/2, /*render_frame_id=*/2,
+ AppCacheHost host2(/*host_id=*/base::UnguessableToken::Create(),
+ /*process_id=*/2, /*render_frame_id=*/2,
std::move(frontend2), &service);
host1.AssociateCompleteCache(cache.get());
diff --git a/chromium/content/browser/appcache/appcache_update_job.cc b/chromium/content/browser/appcache/appcache_update_job.cc
index 229b2affbae..5bb008925a1 100644
--- a/chromium/content/browser/appcache/appcache_update_job.cc
+++ b/chromium/content/browser/appcache/appcache_update_job.cc
@@ -334,7 +334,7 @@ void AppCacheUpdateJob::StartUpdate(AppCacheHost* host,
is_new_pending_master_entry);
}
- BrowserThread::PostAfterStartupTask(
+ BrowserThread::PostBestEffortTask(
FROM_HERE, base::ThreadTaskRunnerHandle::Get(),
base::BindOnce(&AppCacheUpdateJob::FetchManifest,
weak_factory_.GetWeakPtr(), true));
diff --git a/chromium/content/browser/appcache/appcache_update_job_unittest.cc b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
index b1b85de5f96..ed993697fd8 100644
--- a/chromium/content/browser/appcache/appcache_update_job_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
@@ -618,8 +618,8 @@ class MockURLLoaderFactory : public network::mojom::URLLoaderFactory {
}
net::HttpResponseInfo info;
- info.headers = new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length()));
+ info.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(headers));
network::ResourceResponseHead response;
response.headers = info.headers;
@@ -753,8 +753,9 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend mock_frontend;
- AppCacheHost host(/*host_id=*/1, /*process_id=*/1, /*render_frame_id=*/1,
- nullptr, service_.get());
+ AppCacheHost host(/*host_id=*/base::UnguessableToken::Create(),
+ /*process_id=*/1, /*render_frame_id=*/1, nullptr,
+ service_.get());
host.set_frontend_for_testing(&mock_frontend);
update->StartUpdate(&host, GURL());
@@ -794,23 +795,27 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
MockFrontend mock_frontend3;
MockFrontend mock_frontend4;
- AppCacheHost host1(/*host_id=*/1, /*process_id=*/1, /*render_frame_id=*/1,
- nullptr, service_.get());
+ AppCacheHost host1(/*host_id=*/base::UnguessableToken::Create(),
+ /*process_id=*/1, /*render_frame_id=*/1, nullptr,
+ service_.get());
host1.set_frontend_for_testing(&mock_frontend1);
host1.AssociateCompleteCache(cache1);
- AppCacheHost host2(/*host_id=*/2, /*process_id=*/2, /*render_frame_id=*/2,
- nullptr, service_.get());
+ AppCacheHost host2(/*host_id=*/base::UnguessableToken::Create(),
+ /*process_id=*/2, /*render_frame_id=*/2, nullptr,
+ service_.get());
host2.set_frontend_for_testing(&mock_frontend2);
host2.AssociateCompleteCache(cache2);
- AppCacheHost host3(/*host_id=*/3, /*process_id=*/3, /*render_frame_id=*/3,
- nullptr, service_.get());
+ AppCacheHost host3(/*host_id=*/base::UnguessableToken::Create(),
+ /*process_id=*/3, /*render_frame_id=*/3, nullptr,
+ service_.get());
host3.set_frontend_for_testing(&mock_frontend3);
host3.AssociateCompleteCache(cache1);
- AppCacheHost host4(/*host_id=*/4, /*process_id=*/4, /*render_frame_id=*/4,
- nullptr, service_.get());
+ AppCacheHost host4(/*host_id=*/base::UnguessableToken::Create(),
+ /*process_id=*/4, /*render_frame_id=*/4, nullptr,
+ service_.get());
host4.set_frontend_for_testing(&mock_frontend4);
AppCacheUpdateJob* update =
@@ -860,7 +865,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -887,8 +892,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(1, 111);
MockFrontend* frontend1 = MakeMockFrontend();
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host1 = MakeHost(frontend1);
+ AppCacheHost* host2 = MakeHost(frontend2);
host1->AssociateCompleteCache(cache);
host2->AssociateCompleteCache(cache);
@@ -927,7 +932,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -954,7 +959,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 33);
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->AssociateCompleteCache(cache);
frontend->SetVerifyProgressEvents(true);
@@ -994,8 +999,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(1, 111);
MockFrontend* frontend1 = MakeMockFrontend();
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host1 = MakeHost(frontend1);
+ AppCacheHost* host2 = MakeHost(frontend2);
host1->AssociateCompleteCache(cache);
host2->AssociateCompleteCache(cache);
@@ -1030,7 +1035,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -1055,7 +1060,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -1082,8 +1087,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(1, 111);
MockFrontend* frontend1 = MakeMockFrontend();
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host1 = MakeHost(frontend1);
+ AppCacheHost* host2 = MakeHost(frontend2);
host1->AssociateCompleteCache(cache);
host2->AssociateCompleteCache(cache);
@@ -1130,8 +1135,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(1, response_writer_->response_id());
MockFrontend* frontend1 = MakeMockFrontend();
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host1 = MakeHost(frontend1);
+ AppCacheHost* host2 = MakeHost(frontend2);
host1->AssociateCompleteCache(cache);
host2->AssociateCompleteCache(cache);
@@ -1179,7 +1184,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
MockHttpServer::GetMockUrl("files/missing-mime-manifest");
AppCache* cache = MakeCacheForGroup(1, wrong_manifest_url, 111);
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->AssociateCompleteCache(cache);
update->StartUpdate(nullptr, GURL());
@@ -1222,7 +1227,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -1250,7 +1255,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -1283,8 +1288,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
response_writer_->response_id());
MockFrontend* frontend1 = MakeMockFrontend();
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host1 = MakeHost(frontend1);
+ AppCacheHost* host2 = MakeHost(frontend2);
host1->AssociateCompleteCache(cache);
host2->AssociateCompleteCache(cache);
frontend1->SetVerifyProgressEvents(true);
@@ -1350,7 +1355,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->AssociateCompleteCache(cache);
// Give the newest cache an entry that is in storage.
@@ -1420,7 +1425,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->AssociateCompleteCache(cache);
// Give the newest cache an entry that is in storage.
@@ -1488,7 +1493,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->AssociateCompleteCache(cache);
// Give the newest cache an entry that is in storage.
@@ -1556,7 +1561,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->AssociateCompleteCache(cache);
// Give the newest cache an entry that is in storage.
@@ -1630,8 +1635,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
MockFrontend* frontend1 = MakeMockFrontend();
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host1 = MakeHost(frontend1);
+ AppCacheHost* host2 = MakeHost(frontend2);
host1->AssociateCompleteCache(cache);
host2->AssociateCompleteCache(cache);
@@ -1690,7 +1695,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -1722,8 +1727,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
MockFrontend* frontend2 = MakeMockFrontend();
frontend1->SetIgnoreProgressEvents(true);
frontend2->SetIgnoreProgressEvents(true);
- AppCacheHost* host1 = MakeHost(1, frontend1);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host1 = MakeHost(frontend1);
+ AppCacheHost* host2 = MakeHost(frontend2);
host1->AssociateCompleteCache(cache);
host2->AssociateCompleteCache(cache);
@@ -1769,8 +1774,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 25);
MockFrontend* frontend1 = MakeMockFrontend();
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host1 = MakeHost(frontend1);
+ AppCacheHost* host2 = MakeHost(frontend2);
host1->AssociateCompleteCache(cache);
host2->AssociateCompleteCache(cache);
@@ -1876,8 +1881,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 33);
MockFrontend* frontend1 = MakeMockFrontend();
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host1 = MakeHost(frontend1);
+ AppCacheHost* host2 = MakeHost(frontend2);
host1->AssociateCompleteCache(cache);
host2->AssociateCompleteCache(cache);
@@ -1926,7 +1931,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 22);
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->AssociateCompleteCache(cache);
frontend->SetVerifyProgressEvents(true);
@@ -1967,7 +1972,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -1996,7 +2001,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -2026,7 +2031,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -2055,7 +2060,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -2084,7 +2089,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -2113,7 +2118,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -2144,8 +2149,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 11);
MockFrontend* frontend1 = MakeMockFrontend();
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host1 = MakeHost(frontend1);
+ AppCacheHost* host2 = MakeHost(frontend2);
host1->AssociateCompleteCache(cache);
host2->AssociateCompleteCache(cache);
@@ -2209,7 +2214,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
service_->storage()->NewCacheId(), kManifestResponseId));
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->SetFirstPartyUrlForTesting(kManifestUrl);
host->SelectCache(MockHttpServer::GetMockUrl("files/empty1"),
blink::mojom::kAppCacheNoCacheId, kManifestUrl);
@@ -2246,8 +2251,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(1, 111);
MockFrontend* frontend1 = MakeMockFrontend();
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host1 = MakeHost(frontend1);
+ AppCacheHost* host2 = MakeHost(frontend2);
host1->AssociateCompleteCache(cache);
host2->AssociateCompleteCache(cache);
@@ -2281,7 +2286,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->new_master_entry_url_ = GURL("http://failme/blah");
update->StartUpdate(host, host->new_master_entry_url_);
@@ -2309,7 +2314,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/blah");
update->StartUpdate(host, host->new_master_entry_url_);
@@ -2337,7 +2342,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/blah");
update->StartUpdate(host, host->new_master_entry_url_);
@@ -2367,7 +2372,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
MockFrontend* frontend = MakeMockFrontend();
frontend->SetIgnoreProgressEvents(true);
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/explicit1");
update->StartUpdate(host, host->new_master_entry_url_);
@@ -2399,14 +2404,14 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
MockFrontend* frontend1 = MakeMockFrontend();
frontend1->SetIgnoreProgressEvents(true);
- AppCacheHost* host1 = MakeHost(1, frontend1);
+ AppCacheHost* host1 = MakeHost(frontend1);
host1->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/nosuchfile");
update->StartUpdate(host1, host1->new_master_entry_url_);
MockFrontend* frontend2 = MakeMockFrontend();
frontend2->SetIgnoreProgressEvents(true);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host2 = MakeHost(frontend2);
host2->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/servererror");
update->StartUpdate(host2, host2->new_master_entry_url_);
@@ -2445,19 +2450,19 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
MockFrontend* frontend1 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
+ AppCacheHost* host1 = MakeHost(frontend1);
host1->AssociateCompleteCache(cache);
MockFrontend* frontend2 = MakeMockFrontend();
frontend2->SetIgnoreProgressEvents(true);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host2 = MakeHost(frontend2);
host2->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/nosuchfile");
update->StartUpdate(host2, host2->new_master_entry_url_);
MockFrontend* frontend3 = MakeMockFrontend();
frontend3->SetIgnoreProgressEvents(true);
- AppCacheHost* host3 = MakeHost(3, frontend3);
+ AppCacheHost* host3 = MakeHost(frontend3);
host3->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/servererror");
update->StartUpdate(host3, host3->new_master_entry_url_);
@@ -2509,13 +2514,13 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
MockFrontend* frontend1 = MakeMockFrontend();
frontend1->SetIgnoreProgressEvents(true);
- AppCacheHost* host1 = MakeHost(1, frontend1);
+ AppCacheHost* host1 = MakeHost(frontend1);
host1->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/nosuchfile");
update->StartUpdate(host1, host1->new_master_entry_url_);
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host2 = MakeHost(frontend2);
host2->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit2");
update->StartUpdate(host2, host2->new_master_entry_url_);
@@ -2564,18 +2569,18 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
MockFrontend* frontend1 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
+ AppCacheHost* host1 = MakeHost(frontend1);
host1->AssociateCompleteCache(cache);
MockFrontend* frontend2 = MakeMockFrontend();
frontend2->SetIgnoreProgressEvents(true);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host2 = MakeHost(frontend2);
host2->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/nosuchfile");
update->StartUpdate(host2, host2->new_master_entry_url_);
MockFrontend* frontend3 = MakeMockFrontend();
- AppCacheHost* host3 = MakeHost(3, frontend3);
+ AppCacheHost* host3 = MakeHost(frontend3);
host3->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit2");
update->StartUpdate(host3, host3->new_master_entry_url_);
@@ -2636,7 +2641,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(1, 111);
MockFrontend* frontend1 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
+ AppCacheHost* host1 = MakeHost(frontend1);
host1->AssociateCompleteCache(cache);
// Give cache an existing entry that can also be fetched.
@@ -2648,13 +2653,13 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
cache->set_update_time(base::Time());
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host2 = MakeHost(frontend2);
host2->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit1");
update->StartUpdate(host2, host2->new_master_entry_url_);
MockFrontend* frontend3 = MakeMockFrontend();
- AppCacheHost* host3 = MakeHost(3, frontend3);
+ AppCacheHost* host3 = MakeHost(frontend3);
host3->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit2");
update->StartUpdate(host3, host3->new_master_entry_url_);
@@ -2694,7 +2699,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend1 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
+ AppCacheHost* host1 = MakeHost(frontend1);
host1->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit2");
update->StartUpdate(host1, host1->new_master_entry_url_);
@@ -2702,22 +2707,22 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
// Set up additional updates to be started while update is in progress.
MockFrontend* frontend2 = MakeMockFrontend();
frontend2->SetIgnoreProgressEvents(true);
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host2 = MakeHost(frontend2);
host2->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/nosuchfile");
MockFrontend* frontend3 = MakeMockFrontend();
- AppCacheHost* host3 = MakeHost(3, frontend3);
+ AppCacheHost* host3 = MakeHost(frontend3);
host3->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit1");
MockFrontend* frontend4 = MakeMockFrontend();
- AppCacheHost* host4 = MakeHost(4, frontend4);
+ AppCacheHost* host4 = MakeHost(frontend4);
host4->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit2");
MockFrontend* frontend5 = MakeMockFrontend();
- AppCacheHost* host5 = MakeHost(5, frontend5); // no master entry url
+ AppCacheHost* host5 = MakeHost(frontend5); // no master entry url
frontend1->TriggerAdditionalUpdates(
blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT, update);
@@ -2803,7 +2808,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(1, 111);
MockFrontend* frontend1 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
+ AppCacheHost* host1 = MakeHost(frontend1);
host1->AssociateCompleteCache(cache);
// Give cache an existing entry.
@@ -2813,27 +2818,27 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
// Start update with a pending master entry that will fail to give us an
// event to trigger other updates.
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host2 = MakeHost(frontend2);
host2->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/nosuchfile");
update->StartUpdate(host2, host2->new_master_entry_url_);
// Set up additional updates to be started while update is in progress.
MockFrontend* frontend3 = MakeMockFrontend();
- AppCacheHost* host3 = MakeHost(3, frontend3);
+ AppCacheHost* host3 = MakeHost(frontend3);
host3->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit1");
MockFrontend* frontend4 = MakeMockFrontend();
- AppCacheHost* host4 = MakeHost(4, frontend4); // no master entry url
+ AppCacheHost* host4 = MakeHost(frontend4); // no master entry url
MockFrontend* frontend5 = MakeMockFrontend();
- AppCacheHost* host5 = MakeHost(5, frontend5);
+ AppCacheHost* host5 = MakeHost(frontend5);
host5->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit2"); // existing entry
MockFrontend* frontend6 = MakeMockFrontend();
- AppCacheHost* host6 = MakeHost(6, frontend6);
+ AppCacheHost* host6 = MakeHost(frontend6);
host6->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit1");
@@ -2895,27 +2900,27 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
MockFrontend* frontend1 = MakeMockFrontend();
- AppCacheHost* host1 = MakeHost(1, frontend1);
+ AppCacheHost* host1 = MakeHost(frontend1);
host1->AssociateCompleteCache(cache);
update->StartUpdate(nullptr, GURL());
// Set up additional updates to be started while update is in progress.
MockFrontend* frontend2 = MakeMockFrontend();
- AppCacheHost* host2 = MakeHost(2, frontend2);
+ AppCacheHost* host2 = MakeHost(frontend2);
host2->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit1");
MockFrontend* frontend3 = MakeMockFrontend();
- AppCacheHost* host3 = MakeHost(3, frontend3);
+ AppCacheHost* host3 = MakeHost(frontend3);
host3->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit2");
MockFrontend* frontend4 = MakeMockFrontend();
- AppCacheHost* host4 = MakeHost(4, frontend4); // no master entry url
+ AppCacheHost* host4 = MakeHost(frontend4); // no master entry url
MockFrontend* frontend5 = MakeMockFrontend();
- AppCacheHost* host5 = MakeHost(5, frontend5);
+ AppCacheHost* host5 = MakeHost(frontend5);
host5->new_master_entry_url_ =
MockHttpServer::GetMockUrl("files/explicit2");
@@ -3009,7 +3014,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
// Start an update. Should be queued.
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/explicit2");
update->StartUpdate(host, host->new_master_entry_url_);
EXPECT_TRUE(update->pending_master_entries_.empty());
@@ -3064,8 +3069,9 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
// synchronously.
HttpHeadersRequestTestJob::Initialize(std::string(), std::string());
MockFrontend mock_frontend;
- AppCacheHost host(/*host_id=*/1, /*process_id=*/1, /*render_frame_id=*/1,
- nullptr, service_.get());
+ AppCacheHost host(/*host_id=*/base::UnguessableToken::Create(),
+ /*process_id=*/1, /*render_frame_id=*/1, nullptr,
+ service_.get());
host.set_frontend_for_testing(&mock_frontend);
update->StartUpdate(&host, GURL());
@@ -3181,7 +3187,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
response_writer_->response_id());
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->AssociateCompleteCache(cache);
// Set up checks for when update job finishes.
@@ -3247,7 +3253,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
response_writer_->response_id());
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
host->AssociateCompleteCache(cache);
// Set up checks for when update job finishes.
@@ -3388,7 +3394,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -3416,7 +3422,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
MockFrontend* frontend = MakeMockFrontend();
- AppCacheHost* host = MakeHost(1, frontend);
+ AppCacheHost* host = MakeHost(frontend);
update->StartUpdate(host, GURL());
// Set up checks for when update job finishes.
@@ -3500,13 +3506,12 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
return cache;
}
- AppCacheHost* MakeHost(int host_id,
- blink::mojom::AppCacheFrontend* frontend) {
+ AppCacheHost* MakeHost(blink::mojom::AppCacheFrontend* frontend) {
constexpr int kProcessIdForTests = 123;
constexpr int kRenderFrameIdForTests = 456;
- hosts_.push_back(std::make_unique<AppCacheHost>(host_id, kProcessIdForTests,
- kRenderFrameIdForTests,
- nullptr, service_.get()));
+ hosts_.push_back(std::make_unique<AppCacheHost>(
+ base::UnguessableToken::Create(), kProcessIdForTests,
+ kRenderFrameIdForTests, nullptr, service_.get()));
hosts_.back()->set_frontend_for_testing(frontend);
return hosts_.back().get();
}
@@ -3873,8 +3878,8 @@ TEST_F(AppCacheUpdateJobTest, AlreadyChecking) {
EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status());
MockFrontend mock_frontend;
- AppCacheHost host(/*host_id=*/1, /*process_id=*/1, /*render_frame_id=*/1,
- nullptr, &service);
+ AppCacheHost host(/*host_id=*/base::UnguessableToken::Create(),
+ /*process_id=*/1, /*render_frame_id=*/1, nullptr, &service);
host.set_frontend_for_testing(&mock_frontend);
update.StartUpdate(&host, GURL());
@@ -3900,8 +3905,8 @@ TEST_F(AppCacheUpdateJobTest, AlreadyDownloading) {
EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status());
MockFrontend mock_frontend;
- AppCacheHost host(/*host_id=*/1, /*process_id=*/1, /*render_frame_id=*/1,
- nullptr, &service);
+ AppCacheHost host(/*host_id=*/base::UnguessableToken::Create(),
+ /*process_id=*/1, /*render_frame_id=*/1, nullptr, &service);
host.set_frontend_for_testing(&mock_frontend);
update.StartUpdate(&host, GURL());
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 eebe377910b..f232fbce251 100644
--- a/chromium/content/browser/appcache/appcache_update_url_loader_request.cc
+++ b/chromium/content/browser/appcache/appcache_update_url_loader_request.cc
@@ -168,8 +168,7 @@ void AppCacheUpdateJob::UpdateURLLoaderRequest::OnUploadProgress(
}
void AppCacheUpdateJob::UpdateURLLoaderRequest::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
-}
+ mojo_base::BigBuffer data) {}
void AppCacheUpdateJob::UpdateURLLoaderRequest::OnTransferSizeUpdated(
int32_t transfer_size_diff) {
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 04e5f307de7..0acbf4785ad 100644
--- a/chromium/content/browser/appcache/appcache_update_url_loader_request.h
+++ b/chromium/content/browser/appcache/appcache_update_url_loader_request.h
@@ -99,7 +99,7 @@ class AppCacheUpdateJob::UpdateURLLoaderRequest
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
diff --git a/chromium/content/browser/background_fetch/background_fetch_context.cc b/chromium/content/browser/background_fetch/background_fetch_context.cc
index 1b1663547dc..c33451a03d2 100644
--- a/chromium/content/browser/background_fetch/background_fetch_context.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_context.cc
@@ -36,7 +36,7 @@ BackgroundFetchContext::BackgroundFetchContext(
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
const scoped_refptr<CacheStorageContextImpl>& cache_storage_context,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
- scoped_refptr<DevToolsBackgroundServicesContext> devtools_context)
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context)
: browser_context_(browser_context),
service_worker_context_(service_worker_context),
devtools_context_(std::move(devtools_context)),
diff --git a/chromium/content/browser/background_fetch/background_fetch_context.h b/chromium/content/browser/background_fetch/background_fetch_context.h
index 36bab3433a6..969e01e20c1 100644
--- a/chromium/content/browser/background_fetch/background_fetch_context.h
+++ b/chromium/content/browser/background_fetch/background_fetch_context.h
@@ -17,7 +17,7 @@
#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/devtools/devtools_background_services_context.h"
+#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom.h"
@@ -52,7 +52,7 @@ class CONTENT_EXPORT BackgroundFetchContext
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
const scoped_refptr<CacheStorageContextImpl>& cache_storage_context,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
- scoped_refptr<DevToolsBackgroundServicesContext> devtools_context);
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context);
void InitializeOnIOThread();
@@ -196,7 +196,7 @@ class CONTENT_EXPORT BackgroundFetchContext
std::unique_ptr<BackgroundFetchDataManager> data_manager_;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
- scoped_refptr<DevToolsBackgroundServicesContext> devtools_context_;
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context_;
std::unique_ptr<BackgroundFetchRegistrationNotifier> registration_notifier_;
BackgroundFetchDelegateProxy delegate_proxy_;
std::unique_ptr<BackgroundFetchScheduler> scheduler_;
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 9228b53ff6b..50b2232c8d8 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -24,6 +24,8 @@
#include "content/browser/background_fetch/storage/mark_request_complete_task.h"
#include "content/browser/background_fetch/storage/match_requests_task.h"
#include "content/browser/background_fetch/storage/start_next_pending_request_task.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/cache_storage/cache_storage.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"
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 3e64463d797..0af1c80c833 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
@@ -27,6 +27,7 @@
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/background_fetch/storage/image_helpers.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/cache_storage/cache_storage.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
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 c08f3a5455a..12022bd8072 100644
--- a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
@@ -14,7 +14,7 @@
#include "base/strings/stringprintf.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/background_fetch/background_fetch_registration_service_impl.h"
-#include "content/browser/devtools/devtools_background_services_context.h"
+#include "content/browser/devtools/devtools_background_services_context_impl.h"
#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_version.h"
@@ -26,7 +26,7 @@ namespace content {
namespace {
// Returns the histogram suffix for the given |event| type.
-std::string EventTypeToString(ServiceWorkerMetrics::EventType event) {
+std::string HistogramSuffixForEventType(ServiceWorkerMetrics::EventType event) {
switch (event) {
case ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_ABORT:
return "AbortEvent";
@@ -42,12 +42,29 @@ std::string EventTypeToString(ServiceWorkerMetrics::EventType event) {
}
}
+// Returns a human-readable string for the given |event| type.
+std::string EventTypeToString(ServiceWorkerMetrics::EventType event) {
+ switch (event) {
+ case ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_ABORT:
+ return "BackgroundFetchAbortEvent";
+ case ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_CLICK:
+ return "BackgroundFetchClickEvent";
+ case ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_FAIL:
+ return "BackgroundFetchFailEvent";
+ case ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_SUCCESS:
+ return "BackgroundFetchSuccessEvent";
+ default:
+ NOTREACHED();
+ return std::string();
+ }
+}
+
// Records the result of a dispatched Background Fetch event.
void RecordDispatchResult(
ServiceWorkerMetrics::EventType event,
BackgroundFetchEventDispatcher::DispatchResult result) {
- std::string histogram_name =
- "BackgroundFetch.EventDispatchResult." + EventTypeToString(event);
+ std::string histogram_name = "BackgroundFetch.EventDispatchResult." +
+ HistogramSuffixForEventType(event);
// Used because the |histogram_name| is not a constant.
base::UmaHistogramEnumeration(
@@ -59,7 +76,7 @@ void RecordDispatchResult(
void RecordFailureResult(ServiceWorkerMetrics::EventType event,
const char* metric_name,
blink::ServiceWorkerStatusCode service_worker_status) {
- std::string event_type = EventTypeToString(event);
+ std::string event_type = HistogramSuffixForEventType(event);
std::string histogram_name =
base::StringPrintf("BackgroundFetch.EventDispatchFailure.%s.%s",
metric_name, event_type.c_str());
@@ -73,7 +90,7 @@ void RecordFailureResult(ServiceWorkerMetrics::EventType event,
BackgroundFetchEventDispatcher::BackgroundFetchEventDispatcher(
BackgroundFetchContext* background_fetch_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- DevToolsBackgroundServicesContext* devtools_context)
+ DevToolsBackgroundServicesContextImpl* devtools_context)
: background_fetch_context_(background_fetch_context),
service_worker_context_(std::move(service_worker_context)),
devtools_context_(devtools_context) {
@@ -338,21 +355,23 @@ void BackgroundFetchEventDispatcher::LogBackgroundFetchCompletionForDevTools(
blink::mojom::BackgroundFetchFailureReason failure_reason) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!devtools_context_->IsRecording(devtools::proto::BACKGROUND_FETCH))
+ if (!devtools_context_->IsRecording(
+ DevToolsBackgroundService::kBackgroundFetch)) {
return;
+ }
std::map<std::string, std::string> metadata = {
- {"event type", EventTypeToString(event_type)}};
+ {"Event Type", EventTypeToString(event_type)}};
if (failure_reason != blink::mojom::BackgroundFetchFailureReason::NONE) {
std::stringstream stream;
stream << failure_reason;
- metadata["failure reason"] = stream.str();
+ metadata["Failure Reason"] = stream.str();
}
- devtools_context_->LogBackgroundServiceEvent(
+ devtools_context_->LogBackgroundServiceEventOnIO(
registration_id.service_worker_registration_id(),
- registration_id.origin(), devtools::proto::BACKGROUND_FETCH,
- /* event_name= */ "background fetch completed",
+ registration_id.origin(), DevToolsBackgroundService::kBackgroundFetch,
+ /* event_name= */ "Background Fetch completed",
/* instance_id= */ registration_id.developer_id(), metadata);
}
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 4cc6bd061a8..9a4aa92e4f2 100644
--- a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h
+++ b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h
@@ -18,7 +18,7 @@ namespace content {
class BackgroundFetchContext;
class BackgroundFetchRegistrationId;
-class DevToolsBackgroundServicesContext;
+class DevToolsBackgroundServicesContextImpl;
class ServiceWorkerContextWrapper;
class ServiceWorkerRegistration;
class ServiceWorkerVersion;
@@ -40,7 +40,7 @@ class CONTENT_EXPORT BackgroundFetchEventDispatcher {
BackgroundFetchEventDispatcher(
BackgroundFetchContext* background_fetch_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- DevToolsBackgroundServicesContext* devtools_context);
+ DevToolsBackgroundServicesContextImpl* devtools_context);
~BackgroundFetchEventDispatcher();
// Dispatches one of the update, fail, or success events depending on the
@@ -138,7 +138,7 @@ class CONTENT_EXPORT BackgroundFetchEventDispatcher {
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id);
- // Informs the DevToolsBackgroundServicesContext of the completion event.
+ // Informs the DevToolsBackgroundServicesContextImpl of the completion event.
void LogBackgroundFetchCompletionForDevTools(
const BackgroundFetchRegistrationId& registration_id,
ServiceWorkerMetrics::EventType event_type,
@@ -149,7 +149,7 @@ class CONTENT_EXPORT BackgroundFetchEventDispatcher {
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
// Owned by BackgroundFetchContext.
- DevToolsBackgroundServicesContext* devtools_context_;
+ DevToolsBackgroundServicesContextImpl* devtools_context_;
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchEventDispatcher);
};
diff --git a/chromium/content/browser/background_fetch/background_fetch_scheduler.cc b/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
index 8334eaa91bf..539f1458ffc 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
@@ -15,7 +15,7 @@
#include "content/browser/background_fetch/background_fetch_job_controller.h"
#include "content/browser/background_fetch/background_fetch_registration_notifier.h"
#include "content/browser/background_fetch/background_fetch_registration_service_impl.h"
-#include "content/browser/devtools/devtools_background_services_context.h"
+#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/common/content_features.h"
@@ -63,7 +63,7 @@ BackgroundFetchScheduler::BackgroundFetchScheduler(
BackgroundFetchDataManager* data_manager,
BackgroundFetchRegistrationNotifier* registration_notifier,
BackgroundFetchDelegateProxy* delegate_proxy,
- DevToolsBackgroundServicesContext* devtools_context,
+ DevToolsBackgroundServicesContextImpl* devtools_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
: data_manager_(data_manager),
registration_notifier_(registration_notifier),
@@ -351,8 +351,8 @@ void BackgroundFetchScheduler::OnRegistrationCreated(
LogBackgroundFetchEventForDevTools(
Event::kFetchRegistered, registration_id,
/* request_info= */ nullptr,
- {{"total requests", base::NumberToString(num_requests)},
- {"start paused", start_paused ? "yes" : "no"}});
+ {{"Total Requests", base::NumberToString(num_requests)},
+ {"Start Paused", start_paused ? "Yes" : "No"}});
registration_notifier_->NoteTotalRequests(registration_id.unique_id(),
num_requests);
@@ -387,8 +387,8 @@ void BackgroundFetchScheduler::OnRegistrationLoadedAtStartup(
LogBackgroundFetchEventForDevTools(
Event::kFetchResumedOnStartup, registration_id,
/* request_info= */ nullptr,
- {{"completed requests", base::NumberToString(num_completed_requests)},
- {"active requests",
+ {{"Completed Requests", base::NumberToString(num_completed_requests)},
+ {"Active Requests",
base::NumberToString(active_fetch_requests.size())}});
auto controller = CreateInitializedController(
@@ -513,8 +513,10 @@ void BackgroundFetchScheduler::LogBackgroundFetchEventForDevTools(
const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchRequestInfo* request_info,
std::map<std::string, std::string> metadata) {
- if (!devtools_context_->IsRecording(devtools::proto::BACKGROUND_FETCH))
+ if (!devtools_context_->IsRecording(
+ DevToolsBackgroundService::kBackgroundFetch)) {
return;
+ }
std::string event_name;
@@ -522,24 +524,24 @@ void BackgroundFetchScheduler::LogBackgroundFetchEventForDevTools(
// any additional data to |metadata|.
switch (event) {
case Event::kFetchRegistered:
- event_name = "background fetch registered";
+ event_name = "Background Fetch registered";
break;
case Event::kFetchResumedOnStartup:
- event_name = "background fetch resuming after browser restart";
+ event_name = "Background Fetch resuming after browser restart";
break;
case Event::kFetchScheduled:
- event_name = "background fetch started";
+ event_name = "Background Fetch started";
break;
case Event::kRequestStarted:
- event_name = "request processing started";
+ event_name = "Request processing started";
DCHECK(request_info);
break;
case Event::kRequestCompleted:
- event_name = "request processing completed";
+ event_name = "Request processing completed";
DCHECK(request_info);
- metadata["response status"] =
+ metadata["Response Status"] =
base::NumberToString(request_info->GetResponseCode());
- metadata["response size (bytes)"] =
+ metadata["Response Size (bytes)"] =
base::NumberToString(request_info->GetResponseSize());
break;
}
@@ -548,17 +550,17 @@ void BackgroundFetchScheduler::LogBackgroundFetchEventForDevTools(
// Include common request metadata.
if (request_info) {
- metadata["url"] = request_info->fetch_request()->url.spec();
- metadata["request index"] =
+ metadata["URL"] = request_info->fetch_request()->url.spec();
+ metadata["Request Index"] =
base::NumberToString(request_info->request_index());
if (request_info->request_body_size())
- metadata["upload size (bytes)"] =
+ metadata["Upload Size (bytes)"] =
base::NumberToString(request_info->request_body_size());
}
- devtools_context_->LogBackgroundServiceEvent(
+ devtools_context_->LogBackgroundServiceEventOnIO(
registration_id.service_worker_registration_id(),
- registration_id.origin(), devtools::proto::BACKGROUND_FETCH,
+ registration_id.origin(), DevToolsBackgroundService::kBackgroundFetch,
std::move(event_name),
/* instance_id= */ registration_id.developer_id(), metadata);
}
diff --git a/chromium/content/browser/background_fetch/background_fetch_scheduler.h b/chromium/content/browser/background_fetch/background_fetch_scheduler.h
index d953a0e2275..0159718c45f 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler.h
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler.h
@@ -29,7 +29,7 @@ class BackgroundFetchJobController;
class BackgroundFetchRegistrationId;
class BackgroundFetchRegistrationNotifier;
class BackgroundFetchRequestInfo;
-class DevToolsBackgroundServicesContext;
+class DevToolsBackgroundServicesContextImpl;
// Maintains a list of Controllers and chooses which ones should launch new
// downloads.
@@ -42,7 +42,7 @@ class CONTENT_EXPORT BackgroundFetchScheduler
BackgroundFetchDataManager* data_manager,
BackgroundFetchRegistrationNotifier* registration_notifier,
BackgroundFetchDelegateProxy* delegate_proxy,
- DevToolsBackgroundServicesContext* devtools_context,
+ DevToolsBackgroundServicesContextImpl* devtools_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
~BackgroundFetchScheduler() override;
@@ -140,10 +140,11 @@ class CONTENT_EXPORT BackgroundFetchScheduler
void DispatchClickEvent(const std::string& unique_id);
- // Information needed to send over to the DevToolsBackgroundServicesContext.
- // |event| is an enum describing the stage of the fetch. |request_info| is
- // nullptr if not available at the moment. Any additional data to log can be
- // passed through the |metadata| map.
+ // Information needed to send over to the
+ // DevToolsBackgroundServicesContextImpl. |event| is an enum describing the
+ // stage of the fetch. |request_info| is nullptr if not available at the
+ // moment. Any additional data to log can be passed through the |metadata|
+ // map.
void LogBackgroundFetchEventForDevTools(
Event event,
const BackgroundFetchRegistrationId& registration_id,
@@ -154,7 +155,7 @@ class CONTENT_EXPORT BackgroundFetchScheduler
BackgroundFetchDataManager* data_manager_;
BackgroundFetchRegistrationNotifier* registration_notifier_;
BackgroundFetchDelegateProxy* delegate_proxy_;
- DevToolsBackgroundServicesContext* devtools_context_;
+ DevToolsBackgroundServicesContextImpl* devtools_context_;
BackgroundFetchEventDispatcher event_dispatcher_;
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 5da09190752..f457c9fbd82 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
@@ -93,7 +93,7 @@ class BackgroundFetchServiceTest
: public BackgroundFetchTestBase,
public BackgroundFetchDataManagerObserver,
public ServiceWorkerContextCoreObserver,
- public DevToolsBackgroundServicesContext::EventObserver {
+ public DevToolsBackgroundServicesContextImpl::EventObserver {
public:
BackgroundFetchServiceTest() = default;
~BackgroundFetchServiceTest() override = default;
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 93a55419518..8940d4c1231 100644
--- a/chromium/content/browser/background_fetch/background_fetch_test_base.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_test_base.cc
@@ -191,7 +191,7 @@ BackgroundFetchTestBase::CreateBackgroundFetchRegistrationData(
/* download_total= */ 0, /* downloaded= */ 0, result, failure_reason);
}
-scoped_refptr<DevToolsBackgroundServicesContext>
+scoped_refptr<DevToolsBackgroundServicesContextImpl>
BackgroundFetchTestBase::devtools_context() const {
DCHECK(storage_partition_);
return static_cast<StoragePartitionImpl*>(storage_partition_)
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 bc1402d0f32..a1aa4c04e46 100644
--- a/chromium/content/browser/background_fetch/background_fetch_test_base.h
+++ b/chromium/content/browser/background_fetch/background_fetch_test_base.h
@@ -14,7 +14,7 @@
#include "base/memory/ref_counted.h"
#include "content/browser/background_fetch/background_fetch_test_browser_context.h"
#include "content/browser/background_fetch/background_fetch_test_service_worker.h"
-#include "content/browser/devtools/devtools_background_services_context.h"
+#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -83,7 +83,7 @@ class BackgroundFetchTestBase : public ::testing::Test {
const url::Origin& origin() const { return origin_; }
// Returns the DevTools context for logging events.
- scoped_refptr<DevToolsBackgroundServicesContext> devtools_context() const;
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context() const;
protected:
TestBrowserThreadBundle thread_bundle_; // Must be first member.
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
index ec304775ab7..c513187fc56 100644
--- a/chromium/content/browser/background_fetch/background_fetch_test_data_manager.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_test_data_manager.cc
@@ -7,6 +7,7 @@
#include "base/run_loop.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
+#include "content/browser/cache_storage/legacy/legacy_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"
@@ -69,9 +70,10 @@ void BackgroundFetchTestDataManager::InitializeOnIOThread() {
quota_manager_proxy_ =
base::MakeRefCounted<MockBGFQuotaManagerProxy>(mock_quota_manager_.get());
- cache_manager_ = CacheStorageManager::Create(
+ cache_manager_ = LegacyCacheStorageManager::Create(
storage_partition_->GetPath(), base::ThreadTaskRunnerHandle::Get(),
- quota_manager_proxy_);
+ base::ThreadTaskRunnerHandle::Get(), quota_manager_proxy_,
+ base::MakeRefCounted<CacheStorageContextImpl::ObserverList>());
DCHECK(cache_manager_);
cache_manager_->SetBlobParametersForCache(
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 0a2bbd87ecf..cfbd087ce90 100644
--- a/chromium/content/browser/background_fetch/storage/create_metadata_task.cc
+++ b/chromium/content/browser/background_fetch/storage/create_metadata_task.cc
@@ -18,6 +18,7 @@
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/background_fetch/storage/image_helpers.h"
#include "content/browser/background_fetch/storage/mark_registration_for_deletion_task.h"
+#include "content/browser/cache_storage/cache_storage.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/background_fetch/background_fetch_types.h"
#include "content/common/service_worker/service_worker_utils.h"
diff --git a/chromium/content/browser/background_fetch/storage/database_task.cc b/chromium/content/browser/background_fetch/storage/database_task.cc
index 8cdaa9c6e53..69213efc999 100644
--- a/chromium/content/browser/background_fetch/storage/database_task.cc
+++ b/chromium/content/browser/background_fetch/storage/database_task.cc
@@ -13,6 +13,7 @@
#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/cache_storage/cache_storage.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/browser_thread.h"
#include "storage/browser/quota/quota_manager_proxy.h"
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 0934673567b..8700b4ac9c7 100644
--- a/chromium/content/browser/background_fetch/storage/delete_registration_task.cc
+++ b/chromium/content/browser/background_fetch/storage/delete_registration_task.cc
@@ -11,6 +11,7 @@
#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.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "third_party/blink/public/common/cache_storage/cache_storage_utils.h"
diff --git a/chromium/content/browser/background_fetch/storage/get_request_blob_task.cc b/chromium/content/browser/background_fetch/storage/get_request_blob_task.cc
index 5cb25dd7a1d..18dafadf381 100644
--- a/chromium/content/browser/background_fetch/storage/get_request_blob_task.cc
+++ b/chromium/content/browser/background_fetch/storage/get_request_blob_task.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "content/browser/background_fetch/background_fetch_request_match_params.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/cache_storage/cache_storage.h"
#include "content/common/background_fetch/background_fetch_types.h"
#include "third_party/blink/public/common/cache_storage/cache_storage_utils.h"
diff --git a/chromium/content/browser/background_fetch/storage/get_request_blob_task.h b/chromium/content/browser/background_fetch/storage/get_request_blob_task.h
index 2a295af305b..a11625e2682 100644
--- a/chromium/content/browser/background_fetch/storage/get_request_blob_task.h
+++ b/chromium/content/browser/background_fetch/storage/get_request_blob_task.h
@@ -9,6 +9,7 @@
#include "base/memory/scoped_refptr.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/browser/background_fetch/storage/database_task.h"
+#include "content/browser/cache_storage/cache_storage_cache.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
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 f871442fa3e..055e637bea4 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
@@ -12,6 +12,7 @@
#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.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/background_fetch/background_fetch_types.h"
diff --git a/chromium/content/browser/background_fetch/storage/match_requests_task.cc b/chromium/content/browser/background_fetch/storage/match_requests_task.cc
index 23bb7d6a774..4d4617ca6f6 100644
--- a/chromium/content/browser/background_fetch/storage/match_requests_task.cc
+++ b/chromium/content/browser/background_fetch/storage/match_requests_task.cc
@@ -10,6 +10,7 @@
#include "base/bind.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.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/service_worker/service_worker_utils.h"
diff --git a/chromium/content/browser/background_fetch/storage/match_requests_task.h b/chromium/content/browser/background_fetch/storage/match_requests_task.h
index 66cf554daa0..6166103563b 100644
--- a/chromium/content/browser/background_fetch/storage/match_requests_task.h
+++ b/chromium/content/browser/background_fetch/storage/match_requests_task.h
@@ -12,7 +12,7 @@
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/background_fetch_request_match_params.h"
#include "content/browser/background_fetch/storage/database_task.h"
-#include "content/browser/cache_storage/cache_storage_cache_handle.h"
+#include "content/browser/cache_storage/cache_storage_cache.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
diff --git a/chromium/content/browser/background_sync/background_sync.proto b/chromium/content/browser/background_sync/background_sync.proto
index b1ba29680be..943c9dced02 100644
--- a/chromium/content/browser/background_sync/background_sync.proto
+++ b/chromium/content/browser/background_sync/background_sync.proto
@@ -28,6 +28,7 @@ message BackgroundSyncRegistrationProto {
required int32 num_attempts = 7;
required int64 delay_until = 8;
optional PeriodicSyncOptions periodic_sync_options = 9;
+ optional int32 max_attempts = 10;
}
message BackgroundSyncRegistrationsProto {
diff --git a/chromium/content/browser/background_sync/background_sync_browsertest.cc b/chromium/content/browser/background_sync/background_sync_browsertest.cc
index abc17ed9650..cb7cf276bc6 100644
--- a/chromium/content/browser/background_sync/background_sync_browsertest.cc
+++ b/chromium/content/browser/background_sync/background_sync_browsertest.cc
@@ -100,7 +100,7 @@ void RegistrationPendingDidGetSWRegistration(
ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
int64_t service_worker_id = registration->id();
BackgroundSyncManager* sync_manager = sync_context->background_sync_manager();
- sync_manager->GetRegistrations(
+ sync_manager->GetOneShotSyncRegistrations(
service_worker_id,
base::BindOnce(&RegistrationPendingDidGetSyncRegistration, tag,
std::move(callback)));
@@ -514,7 +514,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, GetTags) {
EXPECT_TRUE(GetTags(registered_tags));
}
-// Verify that GetRegistrations works in a service worker
+// Verify that GetOneShotSyncRegistrations works in a service worker
IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
GetRegistrationsFromServiceWorker) {
EXPECT_TRUE(RegisterServiceWorker());
@@ -535,7 +535,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
EXPECT_TRUE(GetTagsFromServiceWorker(registered_tags));
}
-// Verify that GetRegistration works in a service worker
+// Verify that GetOneShotSyncRegistration works in a service worker
IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, HasTagFromServiceWorker) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
diff --git a/chromium/content/browser/background_sync/background_sync_context_impl.cc b/chromium/content/browser/background_sync/background_sync_context_impl.cc
index cd21013c431..27228285cb9 100644
--- a/chromium/content/browser/background_sync/background_sync_context_impl.cc
+++ b/chromium/content/browser/background_sync/background_sync_context_impl.cc
@@ -13,7 +13,7 @@
#include "content/browser/background_sync/background_sync_launcher.h"
#include "content/browser/background_sync/background_sync_manager.h"
#include "content/browser/background_sync/background_sync_service_impl.h"
-#include "content/browser/devtools/devtools_background_services_context.h"
+#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -58,7 +58,8 @@ void BackgroundSyncContext::GetSoonestWakeupDeltaAcrossPartitions(
void BackgroundSyncContextImpl::Init(
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
- const scoped_refptr<DevToolsBackgroundServicesContext>& devtools_context) {
+ const scoped_refptr<DevToolsBackgroundServicesContextImpl>&
+ devtools_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::PostTaskWithTraits(
@@ -177,7 +178,7 @@ void BackgroundSyncContextImpl::DidFireBackgroundSyncEventsOnIOThread(
void BackgroundSyncContextImpl::CreateBackgroundSyncManager(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- scoped_refptr<DevToolsBackgroundServicesContext> devtools_context) {
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!background_sync_manager_);
diff --git a/chromium/content/browser/background_sync/background_sync_context_impl.h b/chromium/content/browser/background_sync/background_sync_context_impl.h
index 4b5c1f242e3..47fb4764737 100644
--- a/chromium/content/browser/background_sync/background_sync_context_impl.h
+++ b/chromium/content/browser/background_sync/background_sync_context_impl.h
@@ -21,7 +21,7 @@ namespace content {
class BackgroundSyncManager;
class BackgroundSyncServiceImpl;
-class DevToolsBackgroundServicesContext;
+class DevToolsBackgroundServicesContextImpl;
class ServiceWorkerContextWrapper;
// One instance of this exists per StoragePartition, and services multiple child
@@ -39,7 +39,8 @@ class CONTENT_EXPORT BackgroundSyncContextImpl
// StoragePartition is being setup and torn down.
void Init(
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
- const scoped_refptr<DevToolsBackgroundServicesContext>& devtools_context);
+ const scoped_refptr<DevToolsBackgroundServicesContextImpl>&
+ devtools_context);
// Shutdown must be called before deleting this. Call on the UI thread.
void Shutdown();
@@ -77,7 +78,7 @@ class CONTENT_EXPORT BackgroundSyncContextImpl
void DidFireBackgroundSyncEventsOnIOThread(base::OnceClosure done_closure);
virtual void CreateBackgroundSyncManager(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- scoped_refptr<DevToolsBackgroundServicesContext> devtools_context);
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context);
void CreateServiceOnIOThread(
mojo::InterfaceRequest<blink::mojom::BackgroundSyncService> request);
diff --git a/chromium/content/browser/background_sync/background_sync_manager.cc b/chromium/content/browser/background_sync/background_sync_manager.cc
index d0d81349e2f..a60da5e18c4 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager.cc
@@ -40,6 +40,9 @@
#endif
using blink::mojom::BackgroundSyncType;
+using blink::mojom::PermissionStatus;
+using SyncAndNotificationPermissions =
+ std::pair<PermissionStatus, PermissionStatus>;
namespace content {
@@ -89,15 +92,16 @@ BackgroundSyncController* GetBackgroundSyncControllerOnUIThread(
return browser_context->GetBackgroundSyncController();
}
-blink::mojom::PermissionStatus GetBackgroundSyncPermissionOnUIThread(
+SyncAndNotificationPermissions GetBackgroundSyncPermissionOnUIThread(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- const url::Origin& origin) {
+ const url::Origin& origin,
+ BackgroundSyncType sync_type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserContext* browser_context =
GetBrowserContextOnUIThread(std::move(service_worker_context));
if (!browser_context)
- return blink::mojom::PermissionStatus::DENIED;
+ return {PermissionStatus::DENIED, PermissionStatus::DENIED};
PermissionController* permission_controller =
BrowserContext::GetPermissionController(browser_context);
@@ -105,8 +109,14 @@ blink::mojom::PermissionStatus GetBackgroundSyncPermissionOnUIThread(
// The requesting origin always matches the embedding origin.
GURL origin_url = origin.GetURL();
- return permission_controller->GetPermissionStatus(
- PermissionType::BACKGROUND_SYNC, origin_url, origin_url);
+ auto sync_permission = permission_controller->GetPermissionStatus(
+ sync_type == BackgroundSyncType::ONE_SHOT
+ ? PermissionType::BACKGROUND_SYNC
+ : PermissionType::PERIODIC_BACKGROUND_SYNC,
+ origin_url, origin_url);
+ auto notification_permission = permission_controller->GetPermissionStatus(
+ PermissionType::NOTIFICATIONS, origin_url, origin_url);
+ return {sync_permission, notification_permission};
}
void NotifyBackgroundSyncRegisteredOnUIThread(
@@ -218,8 +228,8 @@ void DidStartWorkerForSyncEvent(
BackgroundSyncType GetBackgroundSyncType(
const blink::mojom::SyncRegistrationOptions& options) {
- return options.min_interval >= 0 ? BackgroundSyncType::PERIODIC
- : BackgroundSyncType::ONE_SHOT;
+ return options.min_interval == -1 ? BackgroundSyncType::ONE_SHOT
+ : BackgroundSyncType::PERIODIC;
}
std::string GetEventStatusString(blink::ServiceWorkerStatusCode status_code) {
@@ -271,7 +281,7 @@ BackgroundSyncManager::BackgroundSyncRegistrations::
// static
std::unique_ptr<BackgroundSyncManager> BackgroundSyncManager::Create(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- scoped_refptr<DevToolsBackgroundServicesContext> devtools_context) {
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BackgroundSyncManager* sync_manager = new BackgroundSyncManager(
@@ -305,11 +315,45 @@ void BackgroundSyncManager::Register(
return;
}
+ if (GetBackgroundSyncType(options) == BackgroundSyncType::ONE_SHOT) {
+ op_scheduler_.ScheduleOperation(
+ CacheStorageSchedulerOp::kBackgroundSync,
+ base::BindOnce(
+ &BackgroundSyncManager::RegisterCheckIfHasMainFrame,
+ weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
+ std::move(options),
+ op_scheduler_.WrapCallbackToRunNext(std::move(callback))));
+ } else {
+ // Periodic Background Sync events already have a pre-defined cadence which
+ // the user agent decides. Don't block registration if there's no top level
+ // frame at the time of registration.
+ op_scheduler_.ScheduleOperation(
+ CacheStorageSchedulerOp::kBackgroundSync,
+ base::BindOnce(
+ &BackgroundSyncManager::RegisterImpl,
+ weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
+ std::move(options),
+ op_scheduler_.WrapCallbackToRunNext(std::move(callback))));
+ }
+}
+
+void BackgroundSyncManager::UnregisterPeriodicSync(
+ int64_t sw_registration_id,
+ const std::string& tag,
+ BackgroundSyncManager::StatusCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (disabled_) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback),
+ BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
+ return;
+ }
+
op_scheduler_.ScheduleOperation(
CacheStorageSchedulerOp::kBackgroundSync,
- base::BindOnce(&BackgroundSyncManager::RegisterCheckIfHasMainFrame,
- weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
- std::move(options),
+ base::BindOnce(&BackgroundSyncManager::UnregisterPeriodicSyncImpl,
+ weak_ptr_factory_.GetWeakPtr(), sw_registration_id, tag,
op_scheduler_.WrapCallbackToRunNext(std::move(callback))));
}
@@ -326,7 +370,22 @@ void BackgroundSyncManager::DidResolveRegistration(
std::move(registration_info)));
}
+void BackgroundSyncManager::GetOneShotSyncRegistrations(
+ int64_t sw_registration_id,
+ StatusAndRegistrationsCallback callback) {
+ GetRegistrations(BackgroundSyncType::ONE_SHOT, sw_registration_id,
+ std::move(callback));
+}
+
+void BackgroundSyncManager::GetPeriodicSyncRegistrations(
+ int64_t sw_registration_id,
+ StatusAndRegistrationsCallback callback) {
+ GetRegistrations(BackgroundSyncType::PERIODIC, sw_registration_id,
+ std::move(callback));
+}
+
void BackgroundSyncManager::GetRegistrations(
+ BackgroundSyncType sync_type,
int64_t sw_registration_id,
StatusAndRegistrationsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -343,7 +402,8 @@ void BackgroundSyncManager::GetRegistrations(
op_scheduler_.ScheduleOperation(
CacheStorageSchedulerOp::kBackgroundSync,
base::BindOnce(&BackgroundSyncManager::GetRegistrationsImpl,
- weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
+ weak_ptr_factory_.GetWeakPtr(), sync_type,
+ sw_registration_id,
op_scheduler_.WrapCallbackToRunNext(std::move(callback))));
}
@@ -415,8 +475,9 @@ void BackgroundSyncManager::EmulateServiceWorkerOffline(
BackgroundSyncManager::BackgroundSyncManager(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- scoped_refptr<DevToolsBackgroundServicesContext> devtools_context)
- : op_scheduler_(CacheStorageSchedulerClient::kBackgroundSync),
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context)
+ : op_scheduler_(CacheStorageSchedulerClient::kBackgroundSync,
+ base::ThreadTaskRunnerHandle::Get()),
service_worker_context_(std::move(service_worker_context)),
devtools_context_(std::move(devtools_context)),
parameters_(std::make_unique<BackgroundSyncParameters>()),
@@ -535,6 +596,10 @@ void BackgroundSyncManager::InitDidGetDataFromBackend(
registration->set_delay_until(
base::Time::FromInternalValue(registration_proto.delay_until()));
registration->set_resolved();
+ if (registration_proto.has_max_attempts())
+ registration->set_max_attempts(registration_proto.max_attempts());
+ else
+ registration->set_max_attempts(parameters_->max_sync_attempts);
}
}
}
@@ -605,11 +670,12 @@ void BackgroundSyncManager::RegisterImpl(
return;
}
+ BackgroundSyncType sync_type = GetBackgroundSyncType(options);
base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&GetBackgroundSyncPermissionOnUIThread,
- service_worker_context_,
- url::Origin::Create(sw_registration->scope().GetOrigin())),
+ base::BindOnce(
+ &GetBackgroundSyncPermissionOnUIThread, service_worker_context_,
+ url::Origin::Create(sw_registration->scope().GetOrigin()), sync_type),
base::BindOnce(&BackgroundSyncManager::RegisterDidAskForPermission,
weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
std::move(options), std::move(callback)));
@@ -619,15 +685,15 @@ void BackgroundSyncManager::RegisterDidAskForPermission(
int64_t sw_registration_id,
blink::mojom::SyncRegistrationOptions options,
StatusAndRegistrationCallback callback,
- blink::mojom::PermissionStatus permission_status) {
+ SyncAndNotificationPermissions permission_statuses) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (permission_status == blink::mojom::PermissionStatus::DENIED) {
+ if (permission_statuses.first == PermissionStatus::DENIED) {
RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_PERMISSION_DENIED,
std::move(callback));
return;
}
- DCHECK(permission_status == blink::mojom::PermissionStatus::GRANTED);
+ DCHECK_EQ(permission_statuses.first, PermissionStatus::GRANTED);
ServiceWorkerRegistration* sw_registration =
service_worker_context_->GetLiveRegistration(sw_registration_id);
@@ -684,6 +750,10 @@ void BackgroundSyncManager::RegisterDidAskForPermission(
BackgroundSyncRegistration new_registration;
*new_registration.options() = std::move(options);
+ new_registration.set_max_attempts(
+ permission_statuses.second == PermissionStatus::GRANTED
+ ? parameters_->max_sync_attempts_with_notification_permission
+ : parameters_->max_sync_attempts);
if (new_registration.sync_type() == BackgroundSyncType::PERIODIC) {
base::PostTaskWithTraitsAndReplyWithResult(
@@ -735,6 +805,48 @@ void BackgroundSyncManager::RegisterDidGetDelay(
new_registration, std::move(callback)));
}
+void BackgroundSyncManager::UnregisterPeriodicSyncImpl(
+ int64_t sw_registration_id,
+ const std::string& tag,
+ BackgroundSyncManager::StatusCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ auto registration_info = blink::mojom::BackgroundSyncRegistrationInfo(
+ sw_registration_id, tag, BackgroundSyncType::PERIODIC);
+
+ if (!LookupActiveRegistration(registration_info)) {
+ // It's okay to not find a matching tag.
+ UnregisterPeriodicSyncDidStore(std::move(callback),
+ blink::ServiceWorkerStatusCode::kOk);
+ return;
+ }
+
+ RemoveActiveRegistration(std::move(registration_info));
+ StoreRegistrations(
+ sw_registration_id,
+ base::BindOnce(&BackgroundSyncManager::UnregisterPeriodicSyncDidStore,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void BackgroundSyncManager::UnregisterPeriodicSyncDidStore(
+ BackgroundSyncManager::StatusCallback callback,
+ blink::ServiceWorkerStatusCode status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
+ BackgroundSyncMetrics::CountUnregisterPeriodicSync(
+ BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
+ DisableAndClearManager(base::BindOnce(
+ std::move(callback), BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
+ return;
+ }
+
+ BackgroundSyncMetrics::CountUnregisterPeriodicSync(BACKGROUND_SYNC_STATUS_OK);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback), BACKGROUND_SYNC_STATUS_OK));
+}
+
void BackgroundSyncManager::DisableAndClearManager(base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -832,6 +944,7 @@ void BackgroundSyncManager::StoreRegistrations(
registration.options()->min_interval);
}
registration_proto->set_num_attempts(registration.num_attempts());
+ registration_proto->set_max_attempts(registration.max_attempts());
registration_proto->set_delay_until(
registration.delay_until().ToInternalValue());
}
@@ -943,9 +1056,9 @@ void BackgroundSyncManager::AddActiveRegistration(
sync_registration;
if (ShouldLogToDevTools(sync_type)) {
- devtools_context_->LogBackgroundServiceEvent(
- sw_registration_id, origin, devtools::proto::BACKGROUND_SYNC,
- /* event_name= */ "registered sync",
+ devtools_context_->LogBackgroundServiceEventOnIO(
+ sw_registration_id, origin, DevToolsBackgroundService::kBackgroundSync,
+ /* event_name= */ "Registered sync",
/* instance_id= */ sync_registration.options()->tag,
/* event_metadata= */ {});
}
@@ -1005,17 +1118,52 @@ void BackgroundSyncManager::DispatchSyncEvent(
base::BindOnce(&OnSyncEventFinished, active_version, request_id,
std::move(repeating_callback)));
- if (devtools_context_->IsRecording(devtools::proto::BACKGROUND_SYNC)) {
- devtools_context_->LogBackgroundServiceEvent(
+ if (devtools_context_->IsRecording(
+ DevToolsBackgroundService::kBackgroundSync)) {
+ devtools_context_->LogBackgroundServiceEventOnIO(
active_version->registration_id(), active_version->script_origin(),
- devtools::proto::BACKGROUND_SYNC,
- /* event_name= */ "dispatched sync event",
+ DevToolsBackgroundService::kBackgroundSync,
+ /* event_name= */ "Dispatched sync event",
/* instance_id= */ tag,
/* event_metadata= */
- {{"last chance", last_chance ? "yes" : "no"}});
+ {{"Last Chance", last_chance ? "Yes" : "No"}});
}
}
+void BackgroundSyncManager::DispatchPeriodicSyncEvent(
+ const std::string& tag,
+ scoped_refptr<ServiceWorkerVersion> active_version,
+ ServiceWorkerVersion::StatusCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(active_version);
+
+ if (active_version->running_status() != EmbeddedWorkerStatus::RUNNING) {
+ active_version->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::PERIODIC_SYNC,
+ base::BindOnce(
+ &DidStartWorkerForSyncEvent,
+ base::BindOnce(&BackgroundSyncManager::DispatchPeriodicSyncEvent,
+ weak_ptr_factory_.GetWeakPtr(), tag, active_version),
+ std::move(callback)));
+ return;
+ }
+
+ auto repeating_callback =
+ base::AdaptCallbackForRepeating(std::move(callback));
+
+ int request_id = active_version->StartRequestWithCustomTimeout(
+ ServiceWorkerMetrics::EventType::PERIODIC_SYNC, repeating_callback,
+ parameters_->max_sync_event_duration,
+ ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);
+
+ active_version->endpoint()->DispatchPeriodicSyncEvent(
+ tag, parameters_->max_sync_event_duration,
+ base::BindOnce(&OnSyncEventFinished, active_version, request_id,
+ std::move(repeating_callback)));
+
+ // TODO(crbug.com/961238): Record Periodic Sync events for DevTools.
+}
+
void BackgroundSyncManager::ScheduleDelayedTask(base::OnceClosure callback,
base::TimeDelta delay) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
@@ -1029,6 +1177,7 @@ void BackgroundSyncManager::HasMainFrameProviderHost(const url::Origin& origin,
}
void BackgroundSyncManager::GetRegistrationsImpl(
+ BackgroundSyncType sync_type,
int64_t sw_registration_id,
StatusAndRegistrationsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -1050,6 +1199,8 @@ void BackgroundSyncManager::GetRegistrationsImpl(
for (const auto& key_and_registration : registrations.registration_map) {
const BackgroundSyncRegistration& registration =
key_and_registration.second;
+ if (registration.sync_type() != sync_type)
+ continue;
out_registrations.push_back(
std::make_unique<BackgroundSyncRegistration>(registration));
}
@@ -1265,21 +1416,6 @@ void BackgroundSyncManager::FireReadyEventsDidFindRegistration(
service_worker_registration->id());
DCHECK(registration);
- // Don't dispatch a sync event if the sync is periodic.
- // TODO(crbug.com/925297): Remove this code when we've added the logic to
- // dispatch periodic sync events.
- if (registration &&
- registration_info->sync_type == BackgroundSyncType::PERIODIC) {
- RemoveActiveRegistration(*registration_info);
- StoreRegistrations(registration_info->service_worker_registration_id,
- base::DoNothing());
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, std::move(event_fired_callback));
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, std::move(event_completed_callback));
- return;
- }
-
// The connectivity was lost before dispatching the sync event, so there is
// no point in going through with it.
if (!AreOptionConditionsMet()) {
@@ -1294,19 +1430,32 @@ void BackgroundSyncManager::FireReadyEventsDidFindRegistration(
num_firing_registrations_ += 1;
const bool last_chance =
- registration->num_attempts() == parameters_->max_sync_attempts - 1;
+ registration->num_attempts() == registration->max_attempts() - 1;
HasMainFrameProviderHost(
url::Origin::Create(service_worker_registration->scope().GetOrigin()),
base::BindOnce(&BackgroundSyncMetrics::RecordEventStarted));
- DispatchSyncEvent(
- registration->options()->tag,
- service_worker_registration->active_version(), last_chance,
- base::BindOnce(
- &BackgroundSyncManager::EventComplete, weak_ptr_factory_.GetWeakPtr(),
- service_worker_registration, std::move(registration_info),
- std::move(keepalive), std::move(event_completed_callback)));
+ auto sync_type = registration_info->sync_type;
+ if (sync_type == BackgroundSyncType::ONE_SHOT) {
+ DispatchSyncEvent(
+ registration->options()->tag,
+ service_worker_registration->active_version(), last_chance,
+ base::BindOnce(&BackgroundSyncManager::EventComplete,
+ weak_ptr_factory_.GetWeakPtr(),
+ service_worker_registration,
+ std::move(registration_info), std::move(keepalive),
+ std::move(event_completed_callback)));
+ } else {
+ DispatchPeriodicSyncEvent(
+ registration->options()->tag,
+ service_worker_registration->active_version(),
+ base::BindOnce(&BackgroundSyncManager::EventComplete,
+ weak_ptr_factory_.GetWeakPtr(),
+ service_worker_registration,
+ std::move(registration_info), std::move(keepalive),
+ std::move(event_completed_callback)));
+ }
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, std::move(event_fired_callback));
@@ -1383,7 +1532,7 @@ void BackgroundSyncManager::EventCompleteImpl(
// It's important to update |num_attempts| before we update |delay_until|.
registration->set_num_attempts(registration->num_attempts() + 1);
if ((registration->sync_type() == BackgroundSyncType::PERIODIC &&
- registration->num_attempts() == parameters_->max_sync_attempts) ||
+ registration->num_attempts() == registration->max_attempts()) ||
(registration->sync_state() ==
blink::mojom::BackgroundSyncState::REREGISTERED_WHILE_FIRING)) {
registration->set_num_attempts(0);
@@ -1393,7 +1542,7 @@ void BackgroundSyncManager::EventCompleteImpl(
bool succeeded = status_code == blink::ServiceWorkerStatusCode::kOk;
if (registration->sync_type() == BackgroundSyncType::PERIODIC ||
(!succeeded &&
- registration->num_attempts() < parameters_->max_sync_attempts)) {
+ registration->num_attempts() < registration->max_attempts())) {
base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(
@@ -1427,8 +1576,7 @@ void BackgroundSyncManager::EventCompleteDidGetDelay(
}
bool succeeded = status_code == blink::ServiceWorkerStatusCode::kOk;
- bool can_retry =
- registration->num_attempts() < parameters_->max_sync_attempts;
+ bool can_retry = registration->num_attempts() < registration->max_attempts();
bool registration_completed = true;
if (registration->sync_state() ==
@@ -1437,10 +1585,10 @@ void BackgroundSyncManager::EventCompleteDidGetDelay(
registration->set_num_attempts(0);
registration_completed = false;
if (ShouldLogToDevTools(registration->sync_type())) {
- devtools_context_->LogBackgroundServiceEvent(
+ devtools_context_->LogBackgroundServiceEventOnIO(
registration_info->service_worker_registration_id, origin,
- devtools::proto::BACKGROUND_SYNC,
- /* event_name= */ "sync event reregistered",
+ DevToolsBackgroundService::kBackgroundSync,
+ /* event_name= */ "Sync event reregistered",
/* instance_id= */ registration_info->tag,
/* event_metadata= */ {});
}
@@ -1454,13 +1602,13 @@ void BackgroundSyncManager::EventCompleteDidGetDelay(
std::string delay_ms = delay.is_max()
? "infinite"
: base::NumberToString(delay.InMilliseconds());
- devtools_context_->LogBackgroundServiceEvent(
+ devtools_context_->LogBackgroundServiceEventOnIO(
registration_info->service_worker_registration_id, origin,
- devtools::proto::BACKGROUND_SYNC,
- /* event_name= */ "sync event failed",
+ DevToolsBackgroundService::kBackgroundSync,
+ /* event_name= */ "Sync event failed",
/* instance_id= */ registration_info->tag,
- {{"next attempt delay (ms)", delay_ms},
- {"failure reason", GetEventStatusString(status_code)}});
+ {{"Next Attempt Delay (ms)", delay_ms},
+ {"Failure Reason", GetEventStatusString(status_code)}});
}
}
@@ -1469,12 +1617,12 @@ void BackgroundSyncManager::EventCompleteDidGetDelay(
succeeded, registration->num_attempts());
if (ShouldLogToDevTools(registration->sync_type())) {
- devtools_context_->LogBackgroundServiceEvent(
+ devtools_context_->LogBackgroundServiceEventOnIO(
registration_info->service_worker_registration_id, origin,
- devtools::proto::BACKGROUND_SYNC,
- /* event_name= */ "sync complete",
+ DevToolsBackgroundService::kBackgroundSync,
+ /* event_name= */ "Sync completed",
/* instance_id= */ registration_info->tag,
- {{"status", GetEventStatusString(status_code)}});
+ {{"Status", GetEventStatusString(status_code)}});
}
if (registration_info->sync_type ==
@@ -1484,7 +1632,7 @@ void BackgroundSyncManager::EventCompleteDidGetDelay(
base::BindOnce(&NotifyBackgroundSyncCompletedOnUIThread,
service_worker_context_, origin, status_code,
registration->num_attempts(),
- parameters_->max_sync_attempts));
+ registration->max_attempts()));
}
RemoveActiveRegistration(*registration_info);
@@ -1584,7 +1732,8 @@ blink::ServiceWorkerStatusCode BackgroundSyncManager::CanEmulateSyncEvent(
bool BackgroundSyncManager::ShouldLogToDevTools(BackgroundSyncType sync_type) {
return sync_type == BackgroundSyncType::ONE_SHOT &&
- devtools_context_->IsRecording(devtools::proto::BACKGROUND_SYNC);
+ devtools_context_->IsRecording(
+ DevToolsBackgroundService::kBackgroundSync);
}
} // 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 352506202d0..376f41d7193 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.h
+++ b/chromium/content/browser/background_sync/background_sync_manager.h
@@ -24,7 +24,7 @@
#include "content/browser/background_sync/background_sync_registration.h"
#include "content/browser/background_sync/background_sync_status.h"
#include "content/browser/cache_storage/cache_storage_scheduler.h"
-#include "content/browser/devtools/devtools_background_services_context.h"
+#include "content/browser/devtools/devtools_background_services_context_impl.h"
#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"
@@ -58,6 +58,7 @@ class CONTENT_EXPORT BackgroundSyncManager
: public ServiceWorkerContextCoreObserver {
public:
using BoolCallback = base::OnceCallback<void(bool)>;
+ using StatusCallback = base::OnceCallback<void(BackgroundSyncStatus)>;
using StatusAndRegistrationCallback =
base::OnceCallback<void(BackgroundSyncStatus,
std::unique_ptr<BackgroundSyncRegistration>)>;
@@ -69,7 +70,7 @@ class CONTENT_EXPORT BackgroundSyncManager
static std::unique_ptr<BackgroundSyncManager> Create(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- scoped_refptr<DevToolsBackgroundServicesContext> devtools_context);
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context);
~BackgroundSyncManager() override;
// Stores the given background sync registration and adds it to the scheduling
@@ -83,16 +84,29 @@ class CONTENT_EXPORT BackgroundSyncManager
blink::mojom::SyncRegistrationOptions options,
StatusAndRegistrationCallback callback);
+ // Removes the Periodic Background Sync registration identified by |tag| for
+ // the service worker identified by |sw_registration_id|. Calls |callback|
+ // with BACKGROUND_SYNC_STATUS_OK on success.
+ void UnregisterPeriodicSync(int64_t sw_registration_id,
+ const std::string& tag,
+ StatusCallback callback);
+
// Called after the client has resolved its registration promise. At this
// point it's safe to fire any pending registrations.
void DidResolveRegistration(
blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info);
- // Finds the background sync registrations associated with
+ // Finds the one-shot Background Sync registrations associated with
// |sw_registration_id|. Calls |callback| with BACKGROUND_SYNC_STATUS_OK on
// success.
- void GetRegistrations(int64_t sw_registration_id,
- StatusAndRegistrationsCallback callback);
+ void GetOneShotSyncRegistrations(int64_t sw_registration_id,
+ StatusAndRegistrationsCallback callback);
+
+ // Finds the periodic Background Sync registrations associated with
+ // |sw_registration_id|. Calls |callback| with BACKGROUND_SYNC_STATUS_OK on
+ // success.
+ void GetPeriodicSyncRegistrations(int64_t sw_registration_id,
+ StatusAndRegistrationsCallback callback);
// ServiceWorkerContextCoreObserver overrides.
void OnRegistrationDeleted(int64_t sw_registration_id,
@@ -138,7 +152,7 @@ class CONTENT_EXPORT BackgroundSyncManager
protected:
BackgroundSyncManager(
scoped_refptr<ServiceWorkerContextWrapper> context,
- scoped_refptr<DevToolsBackgroundServicesContext> devtools_context);
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context);
// Init must be called before any public member function. Only call it once.
void Init();
@@ -158,6 +172,10 @@ class CONTENT_EXPORT BackgroundSyncManager
scoped_refptr<ServiceWorkerVersion> active_version,
bool last_chance,
ServiceWorkerVersion::StatusCallback callback);
+ virtual void DispatchPeriodicSyncEvent(
+ const std::string& tag,
+ scoped_refptr<ServiceWorkerVersion> active_version,
+ ServiceWorkerVersion::StatusCallback callback);
virtual void ScheduleDelayedTask(base::OnceClosure callback,
base::TimeDelta delay);
virtual void HasMainFrameProviderHost(const url::Origin& origin,
@@ -222,6 +240,10 @@ class CONTENT_EXPORT BackgroundSyncManager
const std::vector<std::pair<int64_t, std::string>>& user_data,
blink::ServiceWorkerStatusCode status);
+ void GetRegistrations(blink::mojom::BackgroundSyncType sync_type,
+ int64_t sw_registration_id,
+ StatusAndRegistrationsCallback callback);
+
// Register callbacks
void RegisterCheckIfHasMainFrame(
int64_t sw_registration_id,
@@ -239,7 +261,8 @@ class CONTENT_EXPORT BackgroundSyncManager
int64_t sw_registration_id,
blink::mojom::SyncRegistrationOptions options,
StatusAndRegistrationCallback callback,
- blink::mojom::PermissionStatus permission_status);
+ std::pair<blink::mojom::PermissionStatus, blink::mojom::PermissionStatus>
+ permission_statuses);
void RegisterDidGetDelay(int64_t sw_registration_id,
BackgroundSyncRegistration new_registration,
StatusAndRegistrationCallback callback,
@@ -248,6 +271,11 @@ class CONTENT_EXPORT BackgroundSyncManager
const BackgroundSyncRegistration& new_registration,
StatusAndRegistrationCallback callback,
blink::ServiceWorkerStatusCode status);
+ void UnregisterPeriodicSyncImpl(int64_t sw_registration_id,
+ const std::string& tag,
+ StatusCallback callback);
+ void UnregisterPeriodicSyncDidStore(StatusCallback callback,
+ blink::ServiceWorkerStatusCode status);
// DidResolveRegistration callbacks
void DidResolveRegistrationImpl(
@@ -256,7 +284,8 @@ class CONTENT_EXPORT BackgroundSyncManager
std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive);
// GetRegistrations callbacks
- void GetRegistrationsImpl(int64_t sw_registration_id,
+ void GetRegistrationsImpl(blink::mojom::BackgroundSyncType sync_type,
+ int64_t sw_registration_id,
StatusAndRegistrationsCallback callback);
bool AreOptionConditionsMet();
@@ -338,7 +367,7 @@ class CONTENT_EXPORT BackgroundSyncManager
CacheStorageScheduler op_scheduler_;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
- scoped_refptr<DevToolsBackgroundServicesContext> devtools_context_;
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context_;
std::unique_ptr<BackgroundSyncParameters> parameters_;
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 6b7a73feec2..a91f43fd9f2 100644
--- a/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -18,13 +18,14 @@
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_entropy_provider.h"
#include "base/test/simple_test_clock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/background_sync/background_sync_network_observer.h"
#include "content/browser/background_sync/background_sync_status.h"
-#include "content/browser/devtools/devtools_background_services_context.h"
+#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -86,15 +87,16 @@ void UnregisterServiceWorkerCallback(bool* called,
blink::mojom::BackgroundSyncType GetBackgroundSyncType(
const blink::mojom::SyncRegistrationOptions& options) {
- return options.min_interval >= 0 ? blink::mojom::BackgroundSyncType::PERIODIC
- : blink::mojom::BackgroundSyncType::ONE_SHOT;
+ return options.min_interval == -1
+ ? blink::mojom::BackgroundSyncType::ONE_SHOT
+ : blink::mojom::BackgroundSyncType::PERIODIC;
}
} // namespace
class BackgroundSyncManagerTest
: public testing::Test,
- public DevToolsBackgroundServicesContext::EventObserver {
+ public DevToolsBackgroundServicesContextImpl::EventObserver {
public:
BackgroundSyncManagerTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
@@ -116,6 +118,12 @@ class BackgroundSyncManagerTest
ON_CALL(*mock_permission_manager,
GetPermissionStatus(PermissionType::BACKGROUND_SYNC, _, _))
.WillByDefault(Return(blink::mojom::PermissionStatus::GRANTED));
+ ON_CALL(*mock_permission_manager,
+ GetPermissionStatus(PermissionType::PERIODIC_BACKGROUND_SYNC, _, _))
+ .WillByDefault(Return(blink::mojom::PermissionStatus::GRANTED));
+ ON_CALL(*mock_permission_manager,
+ GetPermissionStatus(PermissionType::NOTIFICATIONS, _, _))
+ .WillByDefault(Return(blink::mojom::PermissionStatus::DENIED));
helper_->browser_context()->SetPermissionControllerDelegate(
std::move(mock_permission_manager));
@@ -193,22 +201,40 @@ class BackgroundSyncManagerTest
}
}
- void StatusAndRegistrationCallback(
+ void StatusAndOneShotSyncRegistrationCallback(
bool* was_called,
BackgroundSyncStatus status,
std::unique_ptr<BackgroundSyncRegistration> registration) {
*was_called = true;
- callback_status_ = status;
- callback_registration_ = std::move(registration);
+ one_shot_sync_callback_status_ = status;
+ callback_one_shot_sync_registration_ = std::move(registration);
}
- void StatusAndRegistrationsCallback(
+ void StatusAndPeriodicSyncRegistrationCallback(
+ bool* was_called,
+ BackgroundSyncStatus status,
+ std::unique_ptr<BackgroundSyncRegistration> registration) {
+ *was_called = true;
+ periodic_sync_callback_status_ = status;
+ callback_periodic_sync_registration_ = std::move(registration);
+ }
+
+ void StatusAndOneShotSyncRegistrationsCallback(
bool* was_called,
BackgroundSyncStatus status,
std::vector<std::unique_ptr<BackgroundSyncRegistration>> registrations) {
*was_called = true;
- callback_status_ = status;
- callback_registrations_ = std::move(registrations);
+ one_shot_sync_callback_status_ = status;
+ callback_one_shot_sync_registrations_ = std::move(registrations);
+ }
+
+ void StatusAndPeriodicSyncRegistrationsCallback(
+ bool* was_called,
+ BackgroundSyncStatus status,
+ std::vector<std::unique_ptr<BackgroundSyncRegistration>> registrations) {
+ *was_called = true;
+ periodic_sync_callback_status_ = status;
+ callback_periodic_sync_registrations_ = std::move(registrations);
}
void StatusCallback(bool* was_called, BackgroundSyncStatus status) {
@@ -276,27 +302,65 @@ class BackgroundSyncManagerTest
std::move(sync_options));
}
+ bool Unregister(blink::mojom::SyncRegistrationOptions sync_options) {
+ return UnregisterWithServiceWorkerId(sw_registration_id_1_,
+ std::move(sync_options));
+ }
+
bool RegisterWithServiceWorkerId(
int64_t sw_registration_id,
blink::mojom::SyncRegistrationOptions options) {
bool was_called = false;
- background_sync_manager_->Register(
- sw_registration_id, std::move(options),
- base::BindOnce(
- &BackgroundSyncManagerTest::StatusAndRegistrationCallback,
- base::Unretained(this), &was_called));
+ BackgroundSyncStatus* callback_status;
+ if (GetBackgroundSyncType(options) ==
+ blink::mojom::BackgroundSyncType::ONE_SHOT) {
+ background_sync_manager_->Register(
+ sw_registration_id, std::move(options),
+ base::BindOnce(&BackgroundSyncManagerTest::
+ StatusAndOneShotSyncRegistrationCallback,
+ base::Unretained(this), &was_called));
+ callback_status = &one_shot_sync_callback_status_;
+ } else {
+ background_sync_manager_->Register(
+ sw_registration_id, std::move(options),
+ base::BindOnce(&BackgroundSyncManagerTest::
+ StatusAndPeriodicSyncRegistrationCallback,
+ base::Unretained(this), &was_called));
+ callback_status = &periodic_sync_callback_status_;
+ }
+
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
// Mock the client receiving the response and calling
// DidResolveRegistration.
- if (callback_status_ == BACKGROUND_SYNC_STATUS_OK) {
+ if (*callback_status == BACKGROUND_SYNC_STATUS_OK) {
background_sync_manager_->DidResolveRegistration(
blink::mojom::BackgroundSyncRegistrationInfo::New(
sw_registration_id, options.tag, GetBackgroundSyncType(options)));
base::RunLoop().RunUntilIdle();
}
+ return *callback_status == BACKGROUND_SYNC_STATUS_OK;
+ }
+
+ bool UnregisterWithServiceWorkerId(
+ int64_t sw_registration_id,
+ blink::mojom::SyncRegistrationOptions options) {
+ if (GetBackgroundSyncType(options) ==
+ blink::mojom::BackgroundSyncType::ONE_SHOT) {
+ // Not supported for one-shot sync.
+ return false;
+ }
+
+ bool was_called = false;
+ background_sync_manager_->UnregisterPeriodicSync(
+ sw_registration_id, options.tag,
+ base::BindOnce(&BackgroundSyncManagerTest::StatusCallback,
+ base::Unretained(this), &was_called));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(was_called);
+
return callback_status_ == BACKGROUND_SYNC_STATUS_OK;
}
@@ -307,30 +371,40 @@ class BackgroundSyncManagerTest
bool GetRegistration(
blink::mojom::SyncRegistrationOptions registration_options) {
- return GetRegistrationWithServiceWorkerId(sw_registration_id_1_,
- std::move(registration_options));
+ if (GetBackgroundSyncType(registration_options) ==
+ blink::mojom::BackgroundSyncType::ONE_SHOT) {
+ return GetOneShotSyncRegistrationWithServiceWorkerId(
+ sw_registration_id_1_, std::move(registration_options));
+ }
+ return GetPeriodicSyncRegistrationWithServiceWorkerId(
+ sw_registration_id_1_, std::move(registration_options));
}
- bool GetRegistrationWithServiceWorkerId(
+ bool GetOneShotSyncRegistrationWithServiceWorkerId(
int64_t sw_registration_id,
blink::mojom::SyncRegistrationOptions registration_options) {
bool was_called = false;
- background_sync_manager_->GetRegistrations(
+
+ background_sync_manager_->GetOneShotSyncRegistrations(
sw_registration_id,
- base::BindOnce(
- &BackgroundSyncManagerTest::StatusAndRegistrationsCallback,
- base::Unretained(this), &was_called));
+ base::BindOnce(&BackgroundSyncManagerTest::
+ StatusAndOneShotSyncRegistrationsCallback,
+ base::Unretained(this), &was_called));
+
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- if (callback_status_ == BACKGROUND_SYNC_STATUS_OK) {
- for (auto iter = callback_registrations_.begin();
- iter < callback_registrations_.end(); ++iter) {
- if ((*iter)->options()->Equals(registration_options)) {
+ if (one_shot_sync_callback_status_ == BACKGROUND_SYNC_STATUS_OK) {
+ for (auto& one_shot_sync_registration :
+ callback_one_shot_sync_registrations_) {
+ if (one_shot_sync_registration->options()->Equals(
+ registration_options)) {
// Transfer the matching registration out of the vector into
- // callback_registration_ for testing.
- callback_registration_ = std::move(*iter);
- callback_registrations_.erase(iter);
+ // |callback_one_shot_sync_registration_| for testing.
+ callback_one_shot_sync_registration_ =
+ std::move(one_shot_sync_registration);
+ base::Erase(callback_one_shot_sync_registrations_,
+ one_shot_sync_registration);
return true;
}
}
@@ -338,21 +412,62 @@ class BackgroundSyncManagerTest
return false;
}
- bool GetRegistrations() {
- return GetRegistrationsWithServiceWorkerId(sw_registration_id_1_);
+ bool GetPeriodicSyncRegistrationWithServiceWorkerId(
+ int64_t sw_registration_id,
+ blink::mojom::SyncRegistrationOptions registration_options) {
+ bool was_called = false;
+
+ background_sync_manager_->GetPeriodicSyncRegistrations(
+ sw_registration_id,
+ base::BindOnce(&BackgroundSyncManagerTest::
+ StatusAndPeriodicSyncRegistrationsCallback,
+ base::Unretained(this), &was_called));
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(was_called);
+
+ if (periodic_sync_callback_status_ == BACKGROUND_SYNC_STATUS_OK) {
+ for (auto& periodic_sync_registration :
+ callback_periodic_sync_registrations_) {
+ if (periodic_sync_registration->options()->Equals(
+ registration_options)) {
+ // Transfer the matching registration out of the vector into
+ // |callback_periodic_sync_registration_| for testing.
+ callback_periodic_sync_registration_ =
+ std::move(periodic_sync_registration);
+ base::Erase(callback_periodic_sync_registrations_,
+ periodic_sync_registration);
+ return true;
+ }
+ }
+ }
+ return false;
}
- bool GetRegistrationsWithServiceWorkerId(int64_t sw_registration_id) {
+ bool GetOneShotSyncRegistrations() {
bool was_called = false;
- background_sync_manager_->GetRegistrations(
- sw_registration_id,
- base::BindOnce(
- &BackgroundSyncManagerTest::StatusAndRegistrationsCallback,
- base::Unretained(this), &was_called));
+ background_sync_manager_->GetOneShotSyncRegistrations(
+ sw_registration_id_1_,
+ base::BindOnce(&BackgroundSyncManagerTest::
+ StatusAndOneShotSyncRegistrationsCallback,
+ base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return callback_status_ == BACKGROUND_SYNC_STATUS_OK;
+ return one_shot_sync_callback_status_ == BACKGROUND_SYNC_STATUS_OK;
+ }
+
+ bool GetPeriodicSyncRegistrations() {
+ bool was_called = false;
+ background_sync_manager_->GetPeriodicSyncRegistrations(
+ sw_registration_id_1_,
+ base::BindOnce(&BackgroundSyncManagerTest::
+ StatusAndPeriodicSyncRegistrationsCallback,
+ base::Unretained(this), &was_called));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(was_called);
+
+ return periodic_sync_callback_status_ == BACKGROUND_SYNC_STATUS_OK;
}
MockBackgroundSyncController* GetController() {
@@ -385,6 +500,13 @@ class BackgroundSyncManagerTest
SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
}
+ void SetupForPeriodicSyncEvent(
+ const TestBackgroundSyncManager::DispatchSyncCallback& callback) {
+ test_background_sync_manager_->set_dispatch_periodic_sync_callback(
+ callback);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
+ }
+
void DispatchSyncStatusCallback(
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerVersion> active_version,
@@ -393,12 +515,26 @@ class BackgroundSyncManagerTest
std::move(callback).Run(status);
}
+ void DispatchPeriodicSyncStatusCallback(
+ blink::ServiceWorkerStatusCode status,
+ scoped_refptr<ServiceWorkerVersion> active_version,
+ ServiceWorkerVersion::StatusCallback callback) {
+ periodic_sync_events_called_++;
+ std::move(callback).Run(status);
+ }
+
void InitSyncEventTest() {
SetupForSyncEvent(base::BindRepeating(
&BackgroundSyncManagerTest::DispatchSyncStatusCallback,
base::Unretained(this), blink::ServiceWorkerStatusCode::kOk));
}
+ void InitPeriodicSyncEventTest() {
+ SetupForPeriodicSyncEvent(base::BindRepeating(
+ &BackgroundSyncManagerTest::DispatchPeriodicSyncStatusCallback,
+ base::Unretained(this), blink::ServiceWorkerStatusCode::kOk));
+ }
+
void InitFailedSyncEventTest() {
SetupForSyncEvent(base::BindRepeating(
&BackgroundSyncManagerTest::DispatchSyncStatusCallback,
@@ -421,12 +557,12 @@ class BackgroundSyncManagerTest
void RegisterAndVerifySyncEventDelayed(
blink::mojom::SyncRegistrationOptions sync_options) {
- int sync_events_called = sync_events_called_;
+ int count_sync_events = sync_events_called_;
EXPECT_FALSE(sync_fired_callback_);
EXPECT_TRUE(Register(sync_options));
- EXPECT_EQ(sync_events_called + 1, sync_events_called_);
+ EXPECT_EQ(count_sync_events + 1, sync_events_called_);
EXPECT_TRUE(GetRegistration(std::move(sync_options)));
EXPECT_TRUE(sync_fired_callback_);
}
@@ -442,11 +578,19 @@ class BackgroundSyncManagerTest
BackgroundSyncParameters* parameters =
GetController()->background_sync_parameters();
parameters->max_sync_attempts = max_sync_attempts;
+ parameters->max_sync_attempts_with_notification_permission =
+ max_sync_attempts + 1;
// Restart the BackgroundSyncManager so that it updates its parameters.
SetupBackgroundSyncManager();
}
+ void FireReadyEvents() { background_sync_manager_->OnNetworkChanged(); }
+
+ bool AreOptionConditionsMet() {
+ return background_sync_manager_->AreOptionConditionsMet();
+ }
+
TestBrowserThreadBundle browser_thread_bundle_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
std::unique_ptr<BackgroundSyncManager> background_sync_manager_;
@@ -463,13 +607,23 @@ class BackgroundSyncManagerTest
blink::mojom::SyncRegistrationOptions sync_options_2_;
// Callback values.
+ BackgroundSyncStatus one_shot_sync_callback_status_ =
+ BACKGROUND_SYNC_STATUS_OK;
+ BackgroundSyncStatus periodic_sync_callback_status_ =
+ BACKGROUND_SYNC_STATUS_OK;
BackgroundSyncStatus callback_status_ = BACKGROUND_SYNC_STATUS_OK;
- std::unique_ptr<BackgroundSyncRegistration> callback_registration_;
+ std::unique_ptr<BackgroundSyncRegistration>
+ callback_one_shot_sync_registration_;
+ std::unique_ptr<BackgroundSyncRegistration>
+ callback_periodic_sync_registration_;
std::vector<std::unique_ptr<BackgroundSyncRegistration>>
- callback_registrations_;
+ callback_one_shot_sync_registrations_;
+ std::vector<std::unique_ptr<BackgroundSyncRegistration>>
+ callback_periodic_sync_registrations_;
blink::ServiceWorkerStatusCode callback_sw_status_code_ =
blink::ServiceWorkerStatusCode::kOk;
int sync_events_called_ = 0;
+ int periodic_sync_events_called_ = 0;
ServiceWorkerVersion::StatusCallback sync_fired_callback_;
};
@@ -482,13 +636,63 @@ TEST_F(BackgroundSyncManagerTest, FailToRegisterWithInvalidOptions) {
EXPECT_FALSE(Register(sync_options_1_));
}
+TEST_F(BackgroundSyncManagerTest, Unregister) {
+ // Not supported for One-shot syncs.
+ EXPECT_TRUE(Register(sync_options_1_));
+ EXPECT_FALSE(Unregister(sync_options_1_));
+
+ sync_options_1_.min_interval = 36000;
+ EXPECT_TRUE(Register(sync_options_1_));
+
+ // Don't fail for non-existent Periodic Sync registrations.
+ sync_options_2_.min_interval = 36000;
+ EXPECT_TRUE(Unregister(sync_options_2_));
+
+ // Unregistering one periodic sync doesn't affect another.
+ EXPECT_TRUE(Register(sync_options_2_));
+ EXPECT_TRUE(Unregister(sync_options_1_));
+ EXPECT_FALSE(GetRegistration(sync_options_1_));
+ EXPECT_TRUE(GetRegistration(sync_options_2_));
+
+ // Disable manager. Unregister should fail.
+ test_background_sync_manager_->set_corrupt_backend(true);
+ EXPECT_FALSE(Unregister(sync_options_2_));
+ SetupBackgroundSyncManager();
+ EXPECT_TRUE(Unregister(sync_options_2_));
+}
+
+TEST_F(BackgroundSyncManagerTest, UnregistrationStopsPeriodicTasks) {
+ InitPeriodicSyncEventTest();
+ int thirteen_hours_ms = 13 * 60 * 60 * 1000;
+ sync_options_2_.min_interval = thirteen_hours_ms;
+
+ EXPECT_TRUE(Register(sync_options_2_));
+ EXPECT_EQ(0, periodic_sync_events_called_);
+
+ // Advance clock.
+ test_clock_.Advance(base::TimeDelta::FromMilliseconds(thirteen_hours_ms));
+ FireReadyEvents();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1, periodic_sync_events_called_);
+
+ EXPECT_TRUE(Unregister(sync_options_2_));
+
+ // Advance clock. Expect no increase in periodicSync events fired.
+ test_clock_.Advance(base::TimeDelta::FromMilliseconds(thirteen_hours_ms));
+ FireReadyEvents();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, periodic_sync_events_called_);
+}
+
TEST_F(BackgroundSyncManagerTest, RegisterAndWaitToFireUntilResolved) {
InitSyncEventTest();
bool was_called = false;
background_sync_manager_->Register(
sw_registration_id_1_, sync_options_1_,
- base::BindOnce(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
- base::Unretained(this), &was_called));
+ base::BindOnce(
+ &BackgroundSyncManagerTest::StatusAndOneShotSyncRegistrationCallback,
+ base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
@@ -509,8 +713,9 @@ TEST_F(BackgroundSyncManagerTest, ResolveInvalidRegistration) {
bool was_called = false;
background_sync_manager_->Register(
sw_registration_id_1_, sync_options_1_,
- base::BindOnce(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
- base::Unretained(this), &was_called));
+ base::BindOnce(
+ &BackgroundSyncManagerTest::StatusAndOneShotSyncRegistrationCallback,
+ base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
@@ -529,8 +734,12 @@ TEST_F(BackgroundSyncManagerTest, ResolveInvalidRegistration) {
TEST_F(BackgroundSyncManagerTest, RegistrationIntact) {
EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_STREQ(sync_options_1_.tag.c_str(),
- callback_registration_->options()->tag.c_str());
+ EXPECT_EQ(sync_options_1_.tag,
+ callback_one_shot_sync_registration_->options()->tag);
+ sync_options_2_.min_interval = 3600;
+ EXPECT_TRUE(Register(sync_options_2_));
+ EXPECT_EQ(sync_options_2_.tag,
+ callback_periodic_sync_registration_->options()->tag);
}
TEST_F(BackgroundSyncManagerTest, RegisterWithoutLiveSWRegistration) {
@@ -550,13 +759,15 @@ TEST_F(BackgroundSyncManagerTest, RegisterWithoutLiveSWRegistration) {
sw_registration_1_ = nullptr;
EXPECT_FALSE(Register(sync_options_1_));
- EXPECT_EQ(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER, callback_status_);
+ EXPECT_EQ(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
+ one_shot_sync_callback_status_);
}
TEST_F(BackgroundSyncManagerTest, RegisterWithoutActiveSWRegistration) {
sw_registration_1_->UnsetVersion(sw_registration_1_->active_version());
EXPECT_FALSE(Register(sync_options_1_));
- EXPECT_EQ(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER, callback_status_);
+ EXPECT_EQ(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
+ one_shot_sync_callback_status_);
}
TEST_F(BackgroundSyncManagerTest, RegisterBadBackend) {
@@ -573,10 +784,22 @@ TEST_F(BackgroundSyncManagerTest, RegisterPermissionDenied) {
GetPermissionControllerDelegate();
EXPECT_CALL(*mock_permission_manager,
+ GetPermissionStatus(PermissionType::NOTIFICATIONS,
+ expected_origin, expected_origin))
+ .Times(2);
+
+ EXPECT_CALL(*mock_permission_manager,
GetPermissionStatus(PermissionType::BACKGROUND_SYNC,
expected_origin, expected_origin))
.WillOnce(testing::Return(blink::mojom::PermissionStatus::DENIED));
EXPECT_FALSE(Register(sync_options_1_));
+
+ sync_options_2_.min_interval = 36000;
+ EXPECT_CALL(*mock_permission_manager,
+ GetPermissionStatus(PermissionType::PERIODIC_BACKGROUND_SYNC,
+ expected_origin, expected_origin))
+ .WillOnce(testing::Return(blink::mojom::PermissionStatus::DENIED));
+ EXPECT_FALSE(Register(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, RegisterPermissionGranted) {
@@ -585,10 +808,22 @@ TEST_F(BackgroundSyncManagerTest, RegisterPermissionGranted) {
GetPermissionControllerDelegate();
EXPECT_CALL(*mock_permission_manager,
+ GetPermissionStatus(PermissionType::NOTIFICATIONS,
+ expected_origin, expected_origin))
+ .Times(2);
+
+ EXPECT_CALL(*mock_permission_manager,
GetPermissionStatus(PermissionType::BACKGROUND_SYNC,
expected_origin, expected_origin))
.WillOnce(testing::Return(blink::mojom::PermissionStatus::GRANTED));
EXPECT_TRUE(Register(sync_options_1_));
+
+ sync_options_2_.min_interval = 36000;
+ EXPECT_CALL(*mock_permission_manager,
+ GetPermissionStatus(PermissionType::PERIODIC_BACKGROUND_SYNC,
+ expected_origin, expected_origin))
+ .WillOnce(testing::Return(blink::mojom::PermissionStatus::GRANTED));
+ EXPECT_TRUE(Register(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, TwoRegistrations) {
@@ -619,38 +854,55 @@ TEST_F(BackgroundSyncManagerTest, GetRegistrationBadBackend) {
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationsZero) {
- EXPECT_TRUE(GetRegistrations());
- EXPECT_EQ(0u, callback_registrations_.size());
+ EXPECT_TRUE(GetOneShotSyncRegistrations());
+ EXPECT_EQ(0u, callback_one_shot_sync_registrations_.size());
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationsOne) {
EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(GetRegistrations());
+ EXPECT_TRUE(GetOneShotSyncRegistrations());
+
+ ASSERT_EQ(1u, callback_one_shot_sync_registrations_.size());
+ sync_options_1_.Equals(*callback_one_shot_sync_registrations_[0]->options());
+
+ sync_options_1_.min_interval = 3600;
+ EXPECT_TRUE(Register(sync_options_1_));
+ EXPECT_TRUE(GetPeriodicSyncRegistrations());
- EXPECT_EQ(1u, callback_registrations_.size());
- sync_options_1_.Equals(*callback_registrations_[0]->options());
+ ASSERT_EQ(1u, callback_periodic_sync_registrations_.size());
+ sync_options_1_.Equals(*callback_periodic_sync_registrations_[0]->options());
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationsTwo) {
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(Register(sync_options_2_));
- EXPECT_TRUE(GetRegistrations());
+ EXPECT_TRUE(GetOneShotSyncRegistrations());
+
+ ASSERT_EQ(2u, callback_one_shot_sync_registrations_.size());
+ sync_options_1_.Equals(*callback_one_shot_sync_registrations_[0]->options());
+ sync_options_2_.Equals(*callback_one_shot_sync_registrations_[1]->options());
+
+ sync_options_1_.min_interval = 3600;
+ sync_options_2_.min_interval = 3600;
+ EXPECT_TRUE(Register(sync_options_1_));
+ EXPECT_TRUE(Register(sync_options_2_));
+ EXPECT_TRUE(GetPeriodicSyncRegistrations());
- EXPECT_EQ(2u, callback_registrations_.size());
- sync_options_1_.Equals(*callback_registrations_[0]->options());
- sync_options_2_.Equals(*callback_registrations_[1]->options());
+ ASSERT_EQ(2u, callback_periodic_sync_registrations_.size());
+ sync_options_1_.Equals(*callback_periodic_sync_registrations_[0]->options());
+ sync_options_2_.Equals(*callback_periodic_sync_registrations_[1]->options());
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationsBadBackend) {
EXPECT_TRUE(Register(sync_options_1_));
test_background_sync_manager_->set_corrupt_backend(true);
- EXPECT_TRUE(GetRegistrations());
+ EXPECT_TRUE(GetOneShotSyncRegistrations());
EXPECT_FALSE(Register(sync_options_2_));
// Registration should have discovered the bad backend and disabled the
// BackgroundSyncManager.
- EXPECT_FALSE(GetRegistrations());
+ EXPECT_FALSE(GetOneShotSyncRegistrations());
test_background_sync_manager_->set_corrupt_backend(false);
- EXPECT_FALSE(GetRegistrations());
+ EXPECT_FALSE(GetOneShotSyncRegistrations());
}
@@ -672,7 +924,7 @@ TEST_F(BackgroundSyncManagerTest, RegisterMaxTagLength) {
sync_options_2_.tag = std::string(MaxTagLength() + 1, 'b');
EXPECT_FALSE(Register(sync_options_2_));
- EXPECT_EQ(BACKGROUND_SYNC_STATUS_NOT_ALLOWED, callback_status_);
+ EXPECT_EQ(BACKGROUND_SYNC_STATUS_NOT_ALLOWED, one_shot_sync_callback_status_);
}
TEST_F(BackgroundSyncManagerTest, RebootRecovery) {
@@ -692,19 +944,19 @@ TEST_F(BackgroundSyncManagerTest, RebootRecoveryTwoServiceWorkers) {
SetupBackgroundSyncManager();
- EXPECT_TRUE(GetRegistrationWithServiceWorkerId(sw_registration_id_1_,
- sync_options_1_));
- EXPECT_FALSE(GetRegistrationWithServiceWorkerId(sw_registration_id_1_,
- sync_options_2_));
- EXPECT_FALSE(GetRegistrationWithServiceWorkerId(sw_registration_id_2_,
- sync_options_1_));
- EXPECT_TRUE(GetRegistrationWithServiceWorkerId(sw_registration_id_2_,
- sync_options_2_));
+ EXPECT_TRUE(GetOneShotSyncRegistrationWithServiceWorkerId(
+ sw_registration_id_1_, sync_options_1_));
+ EXPECT_FALSE(GetOneShotSyncRegistrationWithServiceWorkerId(
+ sw_registration_id_1_, sync_options_2_));
+ EXPECT_FALSE(GetOneShotSyncRegistrationWithServiceWorkerId(
+ sw_registration_id_2_, sync_options_1_));
+ EXPECT_TRUE(GetOneShotSyncRegistrationWithServiceWorkerId(
+ sw_registration_id_2_, sync_options_2_));
- EXPECT_TRUE(GetRegistrationWithServiceWorkerId(sw_registration_id_1_,
- sync_options_1_));
- EXPECT_TRUE(GetRegistrationWithServiceWorkerId(sw_registration_id_2_,
- sync_options_2_));
+ EXPECT_TRUE(GetOneShotSyncRegistrationWithServiceWorkerId(
+ sw_registration_id_1_, sync_options_1_));
+ EXPECT_TRUE(GetOneShotSyncRegistrationWithServiceWorkerId(
+ sw_registration_id_2_, sync_options_2_));
EXPECT_TRUE(
RegisterWithServiceWorkerId(sw_registration_id_1_, sync_options_2_));
@@ -728,12 +980,14 @@ TEST_F(BackgroundSyncManagerTest, SequentialOperations) {
bool get_registrations_called = false;
test_background_sync_manager_->Register(
sw_registration_id_1_, sync_options_1_,
- base::BindOnce(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
- base::Unretained(this), &register_called));
- test_background_sync_manager_->GetRegistrations(
+ base::BindOnce(
+ &BackgroundSyncManagerTest::StatusAndOneShotSyncRegistrationCallback,
+ base::Unretained(this), &register_called));
+ test_background_sync_manager_->GetOneShotSyncRegistrations(
sw_registration_id_1_,
- base::BindOnce(&BackgroundSyncManagerTest::StatusAndRegistrationsCallback,
- base::Unretained(this), &get_registrations_called));
+ base::BindOnce(
+ &BackgroundSyncManagerTest::StatusAndOneShotSyncRegistrationsCallback,
+ base::Unretained(this), &get_registrations_called));
base::RunLoop().RunUntilIdle();
// Init should be blocked while loading from the backend.
@@ -749,7 +1003,7 @@ TEST_F(BackgroundSyncManagerTest, SequentialOperations) {
test_background_sync_manager_->ResumeBackendOperation();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(register_called);
- EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, callback_status_);
+ EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, one_shot_sync_callback_status_);
// GetRegistrations should run immediately as it doesn't write to disk.
EXPECT_TRUE(get_registrations_called);
}
@@ -763,13 +1017,15 @@ TEST_F(BackgroundSyncManagerTest, UnregisterServiceWorker) {
TEST_F(BackgroundSyncManagerTest,
UnregisterServiceWorkerDuringSyncRegistration) {
EXPECT_TRUE(Register(sync_options_1_));
+ sync_options_2_.min_interval = 3600;
test_background_sync_manager_->set_delay_backend(true);
bool callback_called = false;
test_background_sync_manager_->Register(
sw_registration_id_1_, sync_options_2_,
- base::BindOnce(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
- base::Unretained(this), &callback_called));
+ base::BindOnce(
+ &BackgroundSyncManagerTest::StatusAndPeriodicSyncRegistrationCallback,
+ base::Unretained(this), &callback_called));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(callback_called);
@@ -778,7 +1034,8 @@ TEST_F(BackgroundSyncManagerTest,
test_background_sync_manager_->ResumeBackendOperation();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback_called);
- EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback_status_);
+ EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
+ periodic_sync_callback_status_);
test_background_sync_manager_->set_delay_backend(false);
EXPECT_FALSE(GetRegistration(sync_options_1_));
@@ -847,21 +1104,23 @@ TEST_F(BackgroundSyncManagerTest, StoreAndRetrievePreservesValues) {
SetupBackgroundSyncManager();
EXPECT_TRUE(GetRegistration(options));
- EXPECT_TRUE(options.Equals(*callback_registration_->options()));
+ EXPECT_TRUE(options.Equals(*callback_one_shot_sync_registration_->options()));
}
TEST_F(BackgroundSyncManagerTest, EmptyTagSupported) {
sync_options_1_.tag = "";
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
- EXPECT_TRUE(sync_options_1_.Equals(*callback_registration_->options()));
+ EXPECT_TRUE(
+ sync_options_1_.Equals(*callback_one_shot_sync_registration_->options()));
}
TEST_F(BackgroundSyncManagerTest, PeriodicSyncOptions) {
sync_options_1_.min_interval = 2;
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
- EXPECT_TRUE(sync_options_1_.Equals(*callback_registration_->options()));
+ EXPECT_TRUE(
+ sync_options_1_.Equals(*callback_periodic_sync_registration_->options()));
}
TEST_F(BackgroundSyncManagerTest, BothTypesOfSyncShareATag) {
@@ -872,13 +1131,15 @@ TEST_F(BackgroundSyncManagerTest, BothTypesOfSyncShareATag) {
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
- EXPECT_EQ(callback_registration_->options()->tag, "foo");
- EXPECT_TRUE(sync_options_1_.Equals(*callback_registration_->options()));
+ EXPECT_EQ(callback_one_shot_sync_registration_->options()->tag, "foo");
+ EXPECT_TRUE(
+ sync_options_1_.Equals(*callback_one_shot_sync_registration_->options()));
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_TRUE(GetRegistration(sync_options_2_));
- EXPECT_TRUE(sync_options_2_.Equals(*callback_registration_->options()));
- EXPECT_EQ(callback_registration_->options()->tag, "foo");
+ EXPECT_TRUE(
+ sync_options_2_.Equals(*callback_periodic_sync_registration_->options()));
+ EXPECT_EQ(callback_periodic_sync_registration_->options()->tag, "foo");
}
TEST_F(BackgroundSyncManagerTest, FiresOnRegistration) {
@@ -889,18 +1150,21 @@ TEST_F(BackgroundSyncManagerTest, FiresOnRegistration) {
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
-// TODO(crbug.com/925297): Update once we support dispatching periodic sync
-// events.
-TEST_F(BackgroundSyncManagerTest, PeriodicSyncDoesNotFireOnRegistration) {
- InitSyncEventTest();
- sync_options_2_.min_interval = 36000;
-
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_EQ(1, sync_events_called_);
- EXPECT_FALSE(GetRegistration(sync_options_1_));
+TEST_F(BackgroundSyncManagerTest, PeriodicSyncFiresWhenExpected) {
+ InitPeriodicSyncEventTest();
+ int thirteen_hours_ms = 13 * 60 * 60 * 1000;
+ sync_options_2_.min_interval = thirteen_hours_ms;
EXPECT_TRUE(Register(sync_options_2_));
- EXPECT_EQ(1, sync_events_called_); // no increase.
+ EXPECT_EQ(0, periodic_sync_events_called_);
+ EXPECT_TRUE(GetRegistration(sync_options_2_));
+
+ // Advance clock.
+ test_clock_.Advance(base::TimeDelta::FromMilliseconds(thirteen_hours_ms));
+ FireReadyEvents();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1, periodic_sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_2_));
}
@@ -1169,7 +1433,8 @@ TEST_F(BackgroundSyncManagerTest, OverrideParameters) {
// Check that the manager is disabled
EXPECT_FALSE(Register(sync_options_1_));
- EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback_status_);
+ EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
+ one_shot_sync_callback_status_);
const BackgroundSyncParameters* manager_parameters =
test_background_sync_manager_->background_sync_parameters();
@@ -1205,14 +1470,16 @@ TEST_F(BackgroundSyncManagerTest, DisabledPermanently) {
// Check that the manager is disabled
EXPECT_FALSE(Register(sync_options_1_));
- EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback_status_);
+ EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
+ one_shot_sync_callback_status_);
// If the service worker is wiped and the manager is restarted, the manager
// should stay disabled.
DeleteServiceWorkerAndStartOver();
RegisterServiceWorkers();
EXPECT_FALSE(Register(sync_options_1_));
- EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback_status_);
+ EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
+ one_shot_sync_callback_status_);
}
TEST_F(BackgroundSyncManagerTest, NotifyBackgroundSyncRegistered) {
@@ -1594,6 +1861,24 @@ TEST_F(BackgroundSyncManagerTest, EmulateDispatchSyncEvent) {
EXPECT_EQ(2, sync_events_called_);
}
+TEST_F(BackgroundSyncManagerTest, DispatchPeriodicSyncEvent) {
+ InitPeriodicSyncEventTest();
+
+ EXPECT_TRUE(AreOptionConditionsMet());
+
+ bool was_called = false;
+ blink::ServiceWorkerStatusCode code =
+ blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected;
+ test_background_sync_manager_->DispatchPeriodicSyncEvent(
+ "test_tag", sw_registration_1_->active_version(),
+ base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(was_called);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, code);
+
+ EXPECT_EQ(1, periodic_sync_events_called_);
+}
+
TEST_F(BackgroundSyncManagerTest, EventsLoggedForRegistration) {
// Note that the dispatch is mocked out, so those events are not registered
// by these tests.
@@ -1675,4 +1960,26 @@ TEST_F(BackgroundSyncManagerTest, UkmRecordedAtCompletion) {
}
}
+TEST_F(BackgroundSyncManagerTest, MaxSyncAttemptsWithNotificationPermission) {
+ const int max_attempts = 5;
+ SetMaxSyncAttemptsAndRestartManager(max_attempts);
+ MockPermissionManager* mock_permission_manager =
+ GetPermissionControllerDelegate();
+
+ {
+ EXPECT_TRUE(Register(sync_options_1_));
+ EXPECT_EQ(callback_one_shot_sync_registration_->max_attempts(),
+ max_attempts);
+ }
+
+ {
+ ON_CALL(*mock_permission_manager,
+ GetPermissionStatus(PermissionType::NOTIFICATIONS, _, _))
+ .WillByDefault(Return(blink::mojom::PermissionStatus::GRANTED));
+ EXPECT_TRUE(Register(sync_options_2_));
+ EXPECT_EQ(callback_one_shot_sync_registration_->max_attempts(),
+ max_attempts + 1);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_metrics.cc b/chromium/content/browser/background_sync/background_sync_metrics.cc
index ce50b26d136..8bff40fc5fa 100644
--- a/chromium/content/browser/background_sync/background_sync_metrics.cc
+++ b/chromium/content/browser/background_sync/background_sync_metrics.cc
@@ -87,14 +87,19 @@ void BackgroundSyncMetrics::CountRegisterSuccess(
registration_could_fire == REGISTRATION_COULD_FIRE);
UMA_HISTOGRAM_BOOLEAN("BackgroundSync.Registration.OneShot.IsDuplicate",
registration_is_duplicate == REGISTRATION_IS_DUPLICATE);
- return;
}
// static
void BackgroundSyncMetrics::CountRegisterFailure(BackgroundSyncStatus result) {
UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.OneShot", result,
BACKGROUND_SYNC_STATUS_MAX + 1);
- return;
+}
+
+// static
+void BackgroundSyncMetrics::CountUnregisterPeriodicSync(
+ BackgroundSyncStatus status) {
+ UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Unregistration.Periodic", status,
+ BACKGROUND_SYNC_STATUS_MAX + 1);
}
} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_metrics.h b/chromium/content/browser/background_sync/background_sync_metrics.h
index 5dfd6509c4c..36bb7dedb3f 100644
--- a/chromium/content/browser/background_sync/background_sync_metrics.h
+++ b/chromium/content/browser/background_sync/background_sync_metrics.h
@@ -54,6 +54,10 @@ class BackgroundSyncMetrics {
// Records the status of a failed sync registration.
static void CountRegisterFailure(BackgroundSyncStatus status);
+ // Records the status of an attempt to remove a Periodic Background
+ // Sync registration.
+ static void CountUnregisterPeriodicSync(BackgroundSyncStatus status);
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(BackgroundSyncMetrics);
};
diff --git a/chromium/content/browser/background_sync/background_sync_registration.h b/chromium/content/browser/background_sync/background_sync_registration.h
index b534eca8e7f..b458210fa75 100644
--- a/chromium/content/browser/background_sync/background_sync_registration.h
+++ b/chromium/content/browser/background_sync/background_sync_registration.h
@@ -41,6 +41,8 @@ class CONTENT_EXPORT BackgroundSyncRegistration {
int num_attempts() const { return num_attempts_; }
void set_num_attempts(int num_attempts) { num_attempts_ = num_attempts; }
+ int max_attempts() const { return max_attempts_; }
+ void set_max_attempts(int max_attempts) { max_attempts_ = max_attempts; }
base::Time delay_until() const { return delay_until_; }
void set_delay_until(base::Time delay_until) { delay_until_ = delay_until; }
@@ -62,6 +64,7 @@ class CONTENT_EXPORT BackgroundSyncRegistration {
blink::mojom::BackgroundSyncState sync_state_ =
blink::mojom::BackgroundSyncState::PENDING;
int num_attempts_ = 0;
+ int max_attempts_ = 0;
base::Time delay_until_;
// This member is not persisted to disk. It should be false until the client
diff --git a/chromium/content/browser/background_sync/background_sync_service_impl.cc b/chromium/content/browser/background_sync/background_sync_service_impl.cc
index 24a642713c5..0808e034865 100644
--- a/chromium/content/browser/background_sync/background_sync_service_impl.cc
+++ b/chromium/content/browser/background_sync/background_sync_service_impl.cc
@@ -84,14 +84,14 @@ void BackgroundSyncServiceImpl::DidResolveRegistration(
background_sync_manager->DidResolveRegistration(std::move(registration_info));
}
-void BackgroundSyncServiceImpl::GetRegistrations(
+void BackgroundSyncServiceImpl::GetOneShotSyncRegistrations(
int64_t sw_registration_id,
- GetRegistrationsCallback callback) {
+ GetOneShotSyncRegistrationsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BackgroundSyncManager* background_sync_manager =
background_sync_context_->background_sync_manager();
DCHECK(background_sync_manager);
- background_sync_manager->GetRegistrations(
+ background_sync_manager->GetOneShotSyncRegistrations(
sw_registration_id,
base::BindOnce(&BackgroundSyncServiceImpl::OnGetRegistrationsResult,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
@@ -119,7 +119,7 @@ void BackgroundSyncServiceImpl::OnRegisterResult(
}
void BackgroundSyncServiceImpl::OnGetRegistrationsResult(
- GetRegistrationsCallback callback,
+ GetOneShotSyncRegistrationsCallback callback,
BackgroundSyncStatus status,
std::vector<std::unique_ptr<BackgroundSyncRegistration>>
result_registrations) {
diff --git a/chromium/content/browser/background_sync/background_sync_service_impl.h b/chromium/content/browser/background_sync/background_sync_service_impl.h
index 8c0f6f5f816..91cfefe60c8 100644
--- a/chromium/content/browser/background_sync/background_sync_service_impl.h
+++ b/chromium/content/browser/background_sync/background_sync_service_impl.h
@@ -40,14 +40,15 @@ class CONTENT_EXPORT BackgroundSyncServiceImpl
RegisterCallback callback) override;
void DidResolveRegistration(blink::mojom::BackgroundSyncRegistrationInfoPtr
registration_info) override;
- void GetRegistrations(int64_t sw_registration_id,
- GetRegistrationsCallback callback) override;
+ void GetOneShotSyncRegistrations(
+ int64_t sw_registration_id,
+ GetOneShotSyncRegistrationsCallback callback) override;
void OnRegisterResult(RegisterCallback callback,
BackgroundSyncStatus status,
std::unique_ptr<BackgroundSyncRegistration> result);
void OnGetRegistrationsResult(
- GetRegistrationsCallback callback,
+ GetOneShotSyncRegistrationsCallback callback,
BackgroundSyncStatus status,
std::vector<std::unique_ptr<BackgroundSyncRegistration>> result);
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 73254d2c985..45f6a28e610 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
@@ -205,8 +205,10 @@ class BackgroundSyncServiceImplTest : public testing::Test {
}
void GetRegistrations(
- blink::mojom::BackgroundSyncService::GetRegistrationsCallback callback) {
- service_impl_->GetRegistrations(sw_registration_id_, std::move(callback));
+ blink::mojom::BackgroundSyncService::GetOneShotSyncRegistrationsCallback
+ callback) {
+ service_impl_->GetOneShotSyncRegistrations(sw_registration_id_,
+ std::move(callback));
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/content/browser/bad_message.h b/chromium/content/browser/bad_message.h
index a0b902329bb..bba79b3f614 100644
--- a/chromium/content/browser/bad_message.h
+++ b/chromium/content/browser/bad_message.h
@@ -126,7 +126,7 @@ enum BadMessageReason {
RFH_OWNER_PROPERTY = 99,
OBSOLETE_BDH_EMPTY_OR_INVALID_FILTERS = 100,
OBSOLETE_WC_CONTENT_WITH_CERT_ERRORS_BAD_SECURITY_INFO = 101,
- RFMF_RENDERER_FAKED_ITS_OWN_DEATH = 102,
+ OBSOLETE_RFMF_RENDERER_FAKED_ITS_OWN_DEATH = 102,
DWNLD_INVALID_SAVABLE_RESOURCE_LINKS_RESPONSE = 103,
OBSOLETE_DWNLD_INVALID_SERIALIZE_AS_MHTML_RESPONSE = 104,
BDH_DEVICE_NOT_ALLOWED_FOR_ORIGIN = 105,
@@ -241,6 +241,7 @@ enum BadMessageReason {
INVALID_INITIATOR_ORIGIN = 213,
RFHI_BEGIN_NAVIGATION_MISSING_INITIATOR_ORIGIN = 214,
RFHI_BEGIN_NAVIGATION_NON_WEBBY_TRANSITION = 215,
+ RFH_NO_MATCHING_NAVIGATION_REQUEST_ON_COMMIT = 216,
// Please add new elements here. The naming convention is abbreviated class
// name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc b/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
index 5610c0df1c7..94588aa5822 100644
--- a/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
+++ b/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
@@ -122,7 +122,7 @@ ChromeBlobStorageContext* ChromeBlobStorageContext::GetFor(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
// Removes our old blob directories if they exist.
- BrowserThread::PostAfterStartupTask(
+ BrowserThread::PostBestEffortTask(
FROM_HERE, file_task_runner,
base::BindOnce(&RemoveOldBlobStorageDirectories,
std::move(blob_storage_parent), blob_storage_dir));
@@ -149,9 +149,8 @@ void ChromeBlobStorageContext::InitializeOnIOThread(
std::move(file_task_runner)));
// Signal the BlobMemoryController when it's appropriate to calculate its
// storage limits.
- BrowserThread::PostAfterStartupTask(
- FROM_HERE,
- base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO, base::TaskPriority::BEST_EFFORT},
base::BindOnce(&storage::BlobMemoryController::CalculateBlobStorageLimits,
context_->mutable_memory_controller()->GetWeakPtr()));
}
diff --git a/chromium/content/browser/bluetooth/bluetooth_allowed_devices.h b/chromium/content/browser/bluetooth/bluetooth_allowed_devices.h
index ce9d66dd7e5..d59608a5579 100644
--- a/chromium/content/browser/bluetooth/bluetooth_allowed_devices.h
+++ b/chromium/content/browser/bluetooth/bluetooth_allowed_devices.h
@@ -14,7 +14,7 @@
#include "base/optional.h"
#include "content/common/bluetooth/web_bluetooth_device_id.h"
#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
namespace device {
class BluetoothUUID;
diff --git a/chromium/content/browser/bluetooth/bluetooth_blocklist.h b/chromium/content/browser/bluetooth/bluetooth_blocklist.h
index 103e8c2da42..1e5ee0461e1 100644
--- a/chromium/content/browser/bluetooth/bluetooth_blocklist.h
+++ b/chromium/content/browser/bluetooth/bluetooth_blocklist.h
@@ -13,7 +13,7 @@
#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
#include "device/bluetooth/bluetooth_uuid.h"
-#include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
namespace content {
diff --git a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h
index b2e16cb09f8..383477d9b52 100644
--- a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h
+++ b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h
@@ -14,7 +14,7 @@
#include "base/timer/timer.h"
#include "content/common/content_export.h"
#include "content/public/browser/bluetooth_chooser.h"
-#include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
namespace device {
class BluetoothAdapter;
diff --git a/chromium/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.cc b/chromium/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.cc
new file mode 100644
index 00000000000..276f52f302b
--- /dev/null
+++ b/chromium/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.cc
@@ -0,0 +1,61 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "content/browser/bluetooth/web_bluetooth_service_impl.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+
+namespace content {
+
+BluetoothDeviceScanningPromptController::
+ BluetoothDeviceScanningPromptController(
+ WebBluetoothServiceImpl* web_bluetooth_service,
+ RenderFrameHost* render_frame_host)
+ : web_bluetooth_service_(web_bluetooth_service),
+ render_frame_host_(render_frame_host),
+ web_contents_(WebContents::FromRenderFrameHost(render_frame_host_)) {}
+
+BluetoothDeviceScanningPromptController::
+ ~BluetoothDeviceScanningPromptController() {
+ if (!prompt_event_received_)
+ OnBluetoothScanningPromptEvent(BluetoothScanningPrompt::Event::kCanceled);
+}
+
+void BluetoothDeviceScanningPromptController::ShowPermissionPrompt() {
+ BluetoothScanningPrompt::EventHandler prompt_event_handler = base::Bind(
+ &BluetoothDeviceScanningPromptController::OnBluetoothScanningPromptEvent,
+ base::Unretained(this));
+ WebContentsDelegate* delegate =
+ WebContents::FromRenderFrameHost(render_frame_host_)->GetDelegate();
+ if (delegate) {
+ prompt_ = delegate->ShowBluetoothScanningPrompt(
+ render_frame_host_, std::move(prompt_event_handler));
+ }
+}
+
+void BluetoothDeviceScanningPromptController::OnBluetoothScanningPromptEvent(
+ BluetoothScanningPrompt::Event event) {
+ DCHECK(web_bluetooth_service_);
+
+ web_bluetooth_service_->OnBluetoothScanningPromptEvent(event, this);
+ prompt_event_received_ = true;
+
+ // Close prompt.
+ prompt_.reset();
+}
+
+void BluetoothDeviceScanningPromptController::AddFilteredDevice(
+ const std::string& device_id,
+ bool should_update_name,
+ const base::string16& device_name) {
+ if (prompt_)
+ prompt_->AddOrUpdateDevice(device_id, should_update_name, device_name);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.h b/chromium/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.h
new file mode 100644
index 00000000000..2473df415a5
--- /dev/null
+++ b/chromium/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.h
@@ -0,0 +1,66 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_DEVICE_SCANNING_PROMPT_CONTROLLER_H_
+#define CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_DEVICE_SCANNING_PROMPT_CONTROLLER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/bluetooth_scanning_prompt.h"
+
+namespace content {
+
+class RenderFrameHost;
+class WebContents;
+class WebBluetoothServiceImpl;
+
+// Class that interacts with a prompt.
+class CONTENT_EXPORT BluetoothDeviceScanningPromptController final {
+ public:
+ // |web_bluetooth_service_| service that owns this class.
+ // |render_frame_host| should be the RenderFrameHost that owns the
+ // |web_bluetooth_service_|.
+ BluetoothDeviceScanningPromptController(
+ WebBluetoothServiceImpl* web_bluetooth_service,
+ RenderFrameHost* render_frame_host);
+ ~BluetoothDeviceScanningPromptController();
+
+ void ShowPermissionPrompt();
+
+ void OnBluetoothScanningPromptEvent(BluetoothScanningPrompt::Event event);
+
+ // Adds a device to the prompt. Should only be called after
+ // ShowPermissionPrompt() is called.
+ void AddFilteredDevice(const std::string& device_id,
+ bool should_update_name,
+ const base::string16& device_name);
+
+ private:
+ // The WebBluetoothServiceImpl that owns this instance.
+ WebBluetoothServiceImpl* const web_bluetooth_service_;
+ // The RenderFrameHost that owns |web_bluetooth_service_|.
+ RenderFrameHost* const render_frame_host_;
+ // The WebContents that owns |render_frame_host_|.
+ WebContents* const web_contents_;
+
+ // The currently opened BluetoothScanningPrompt.
+ std::unique_ptr<BluetoothScanningPrompt> prompt_;
+
+ bool prompt_event_received_ = false;
+
+ // Weak pointer factory for generating 'this' pointers that might live longer
+ // than we do.
+ // Note: This should remain the last member so it'll be destroyed and
+ // invalidate its weak pointers before any other members are destroyed.
+ base::WeakPtrFactory<BluetoothDeviceScanningPromptController>
+ weak_ptr_factory_{this};
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_DEVICE_SCANNING_PROMPT_CONTROLLER_H_
diff --git a/chromium/content/browser/bluetooth/bluetooth_metrics.h b/chromium/content/browser/bluetooth/bluetooth_metrics.h
index f381a6894df..68ec45c465e 100644
--- a/chromium/content/browser/bluetooth/bluetooth_metrics.h
+++ b/chromium/content/browser/bluetooth/bluetooth_metrics.h
@@ -8,7 +8,7 @@
#include <string>
#include <vector>
-#include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
namespace base {
class TimeDelta;
diff --git a/chromium/content/browser/bluetooth/bluetooth_util.cc b/chromium/content/browser/bluetooth/bluetooth_util.cc
new file mode 100644
index 00000000000..ce002db480b
--- /dev/null
+++ b/chromium/content/browser/bluetooth/bluetooth_util.cc
@@ -0,0 +1,45 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/bluetooth/bluetooth_util.h"
+
+namespace content {
+
+bool AreScanFiltersSame(
+ const blink::mojom::WebBluetoothLeScanFilter& filter_1,
+ const blink::mojom::WebBluetoothLeScanFilter& filter_2) {
+ if (filter_1.name.has_value() != filter_2.name.has_value())
+ return false;
+
+ if (filter_1.name.has_value() &&
+ filter_1.name.value() != filter_2.name.value()) {
+ return false;
+ }
+
+ if (filter_1.name_prefix.has_value() != filter_2.name_prefix.has_value())
+ return false;
+
+ if (filter_1.name_prefix.has_value() &&
+ filter_1.name_prefix.value() != filter_2.name_prefix.value())
+ return false;
+
+ if (filter_1.services.has_value() != filter_2.services.has_value())
+ return false;
+
+ if (filter_1.services.has_value()) {
+ std::vector<device::BluetoothUUID> services_1 = filter_1.services.value();
+ std::vector<device::BluetoothUUID> services_2 = filter_2.services.value();
+ if (services_1.size() != services_2.size())
+ return false;
+
+ std::sort(services_1.begin(), services_1.end());
+ std::sort(services_2.begin(), services_2.end());
+ if (services_1 != services_2)
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_util.h b/chromium/content/browser/bluetooth/bluetooth_util.h
new file mode 100644
index 00000000000..131d50c4d2c
--- /dev/null
+++ b/chromium/content/browser/bluetooth/bluetooth_util.h
@@ -0,0 +1,18 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_UTIL_H_
+#define CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_UTIL_H_
+
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
+
+namespace content {
+
+CONTENT_EXPORT bool AreScanFiltersSame(
+ const blink::mojom::WebBluetoothLeScanFilter& filter_1,
+ const blink::mojom::WebBluetoothLeScanFilter& filter_2);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_UTIL_H_
diff --git a/chromium/content/browser/bluetooth/bluetooth_util_unittest.cc b/chromium/content/browser/bluetooth/bluetooth_util_unittest.cc
new file mode 100644
index 00000000000..8f6868602b7
--- /dev/null
+++ b/chromium/content/browser/bluetooth/bluetooth_util_unittest.cc
@@ -0,0 +1,158 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/bluetooth/bluetooth_util.h"
+
+#include "base/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+const char kBatteryServiceUUIDString[] = "0000180f-0000-1000-8000-00805f9b34fb";
+const char kCyclingPowerUUIDString[] = "00001818-0000-1000-8000-00805f9b34fb";
+
+} // namespace
+
+class BluetoothUtilTest : public testing::Test {
+ public:
+ BluetoothUtilTest() = default;
+ ~BluetoothUtilTest() override = default;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BluetoothUtilTest);
+};
+
+TEST_F(BluetoothUtilTest, SameFilters) {
+ base::Optional<std::vector<device::BluetoothUUID>> services;
+ services.emplace();
+ services->push_back(device::BluetoothUUID(kBatteryServiceUUIDString));
+ auto filter_1 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services, "ab", "a");
+ auto filter_2 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services, "ab", "a");
+ EXPECT_TRUE(AreScanFiltersSame(*filter_1, *filter_2));
+}
+
+TEST_F(BluetoothUtilTest, BothNoName) {
+ base::Optional<std::vector<device::BluetoothUUID>> services;
+ services.emplace();
+ services->push_back(device::BluetoothUUID(kBatteryServiceUUIDString));
+ auto filter_1 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services, base::nullopt, "a");
+ auto filter_2 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services, base::nullopt, "a");
+ EXPECT_TRUE(AreScanFiltersSame(*filter_1, *filter_2));
+}
+
+TEST_F(BluetoothUtilTest, OnlyOneHasName) {
+ base::Optional<std::vector<device::BluetoothUUID>> services;
+ services.emplace();
+ services->push_back(device::BluetoothUUID(kBatteryServiceUUIDString));
+ auto filter_1 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services, "ab", "a");
+ auto filter_2 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services, base::nullopt, "a");
+ EXPECT_FALSE(AreScanFiltersSame(*filter_1, *filter_2));
+}
+
+TEST_F(BluetoothUtilTest, DifferentName) {
+ base::Optional<std::vector<device::BluetoothUUID>> services;
+ services.emplace();
+ services->push_back(device::BluetoothUUID(kBatteryServiceUUIDString));
+ auto filter_1 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services, "ab", "a");
+ auto filter_2 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services, "cd", "a");
+ EXPECT_FALSE(AreScanFiltersSame(*filter_1, *filter_2));
+}
+
+TEST_F(BluetoothUtilTest, BothNoNamePrefix) {
+ base::Optional<std::vector<device::BluetoothUUID>> services;
+ services.emplace();
+ services->push_back(device::BluetoothUUID(kBatteryServiceUUIDString));
+ auto filter_1 = blink::mojom::WebBluetoothLeScanFilter::New(services, "ab",
+ base::nullopt);
+ auto filter_2 = blink::mojom::WebBluetoothLeScanFilter::New(services, "ab",
+ base::nullopt);
+ EXPECT_TRUE(AreScanFiltersSame(*filter_1, *filter_2));
+}
+
+TEST_F(BluetoothUtilTest, OnlyOneHasNamePrefix) {
+ base::Optional<std::vector<device::BluetoothUUID>> services;
+ services.emplace();
+ services->push_back(device::BluetoothUUID(kBatteryServiceUUIDString));
+ auto filter_1 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services, "ab", "a");
+ auto filter_2 = blink::mojom::WebBluetoothLeScanFilter::New(services, "ab",
+ base::nullopt);
+ EXPECT_FALSE(AreScanFiltersSame(*filter_1, *filter_2));
+}
+
+TEST_F(BluetoothUtilTest, DifferentNamePrefix) {
+ base::Optional<std::vector<device::BluetoothUUID>> services;
+ services.emplace();
+ services->push_back(device::BluetoothUUID(kBatteryServiceUUIDString));
+ auto filter_1 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services, "ab", "a");
+ auto filter_2 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services, "ab", "ab");
+ EXPECT_FALSE(AreScanFiltersSame(*filter_1, *filter_2));
+}
+
+TEST_F(BluetoothUtilTest, BothNoServicesUUID) {
+ auto filter_1 =
+ blink::mojom::WebBluetoothLeScanFilter::New(base::nullopt, "ab", "a");
+ auto filter_2 =
+ blink::mojom::WebBluetoothLeScanFilter::New(base::nullopt, "ab", "a");
+ EXPECT_TRUE(AreScanFiltersSame(*filter_1, *filter_2));
+}
+
+TEST_F(BluetoothUtilTest, OnlyOneHasServicesUUID) {
+ base::Optional<std::vector<device::BluetoothUUID>> services;
+ services.emplace();
+ services->push_back(device::BluetoothUUID(kBatteryServiceUUIDString));
+ auto filter_1 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services, "ab", "a");
+ auto filter_2 =
+ blink::mojom::WebBluetoothLeScanFilter::New(base::nullopt, "ab", "ab");
+ EXPECT_FALSE(AreScanFiltersSame(*filter_1, *filter_2));
+}
+
+TEST_F(BluetoothUtilTest, DifferentServicesUUID) {
+ base::Optional<std::vector<device::BluetoothUUID>> services_1;
+ services_1.emplace();
+ services_1->push_back(device::BluetoothUUID(kBatteryServiceUUIDString));
+ auto filter_1 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services_1, "ab", "a");
+
+ base::Optional<std::vector<device::BluetoothUUID>> services_2;
+ services_2.emplace();
+ services_2->push_back(device::BluetoothUUID(kCyclingPowerUUIDString));
+ auto filter_2 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services_2, "ab", "a");
+
+ EXPECT_FALSE(AreScanFiltersSame(*filter_1, *filter_2));
+}
+
+TEST_F(BluetoothUtilTest, SameServicesUUIDButDifferentOrder) {
+ base::Optional<std::vector<device::BluetoothUUID>> services_1;
+ services_1.emplace();
+ services_1->push_back(device::BluetoothUUID(kBatteryServiceUUIDString));
+ services_1->push_back(device::BluetoothUUID(kCyclingPowerUUIDString));
+ auto filter_1 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services_1, "ab", "a");
+
+ base::Optional<std::vector<device::BluetoothUUID>> services_2;
+ services_2.emplace();
+ services_2->push_back(device::BluetoothUUID(kBatteryServiceUUIDString));
+ services_2->push_back(device::BluetoothUUID(kCyclingPowerUUIDString));
+ auto filter_2 =
+ blink::mojom::WebBluetoothLeScanFilter::New(services_2, "ab", "a");
+
+ EXPECT_TRUE(AreScanFiltersSame(*filter_1, *filter_2));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/bluetooth/frame_connected_bluetooth_devices.h b/chromium/content/browser/bluetooth/frame_connected_bluetooth_devices.h
index d8adcbd5953..802068212ad 100644
--- a/chromium/content/browser/bluetooth/frame_connected_bluetooth_devices.h
+++ b/chromium/content/browser/bluetooth/frame_connected_bluetooth_devices.h
@@ -12,7 +12,7 @@
#include "base/optional.h"
#include "content/common/bluetooth/web_bluetooth_device_id.h"
#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
#include "url/origin.h"
namespace device {
diff --git a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
index 6952610f8c8..35460350eca 100644
--- a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
+++ b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -19,16 +19,21 @@
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/bluetooth/bluetooth_blocklist.h"
#include "content/browser/bluetooth/bluetooth_device_chooser_controller.h"
+#include "content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.h"
#include "content/browser/bluetooth/bluetooth_metrics.h"
+#include "content/browser/bluetooth/bluetooth_util.h"
#include "content/browser/bluetooth/frame_connected_bluetooth_devices.h"
+#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/common/bluetooth/web_bluetooth_device_id.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
#include "device/bluetooth/bluetooth_adapter_factory_wrapper.h"
#include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
#include "device/bluetooth/bluetooth_remote_gatt_descriptor.h"
@@ -245,10 +250,51 @@ bool WebBluetoothServiceImpl::IsDevicePaired(
return allowed_devices().GetDeviceId(device_address) != nullptr;
}
+void WebBluetoothServiceImpl::OnBluetoothScanningPromptEvent(
+ BluetoothScanningPrompt::Event event,
+ BluetoothDeviceScanningPromptController* prompt_controller) {
+ DCHECK(!scanning_clients_.empty());
+
+ auto client = scanning_clients_.end() - 1;
+
+ DCHECK((*client)->prompt_controller() == prompt_controller);
+
+ auto result = blink::mojom::WebBluetoothResult::SUCCESS;
+ if (event == BluetoothScanningPrompt::Event::kAllow) {
+ result = blink::mojom::WebBluetoothResult::SUCCESS;
+ StoreAllowedScanOptions((*client)->scan_options());
+ } else if (event == BluetoothScanningPrompt::Event::kBlock) {
+ result = blink::mojom::WebBluetoothResult::SCANNING_BLOCKED;
+ const url::Origin requesting_origin =
+ render_frame_host_->GetLastCommittedOrigin();
+ const url::Origin embedding_origin =
+ web_contents()->GetMainFrame()->GetLastCommittedOrigin();
+ GetContentClient()->browser()->BlockBluetoothScanning(
+ web_contents()->GetBrowserContext(), requesting_origin,
+ embedding_origin);
+ } else if (event == BluetoothScanningPrompt::Event::kCanceled) {
+ result = blink::mojom::WebBluetoothResult::PROMPT_CANCELED;
+ } else {
+ NOTREACHED();
+ }
+
+ (*client)->RunRequestScanningStartCallback(std::move(result));
+ (*client)->set_prompt_controller(nullptr);
+ if (event == BluetoothScanningPrompt::Event::kAllow)
+ (*client)->set_allow_send_event(true);
+ else
+ scanning_clients_.erase(client);
+}
+
WebBluetoothServiceImpl::ScanningClient::ScanningClient(
blink::mojom::WebBluetoothScanClientAssociatedPtr client,
- blink::mojom::WebBluetoothRequestLEScanOptionsPtr options)
- : client_(std::move(client)), options_(std::move(options)) {
+ blink::mojom::WebBluetoothRequestLEScanOptionsPtr options,
+ RequestScanningStartCallback callback,
+ BluetoothDeviceScanningPromptController* prompt_controller)
+ : client_(std::move(client)),
+ options_(std::move(options)),
+ callback_(std::move(callback)),
+ prompt_controller_(prompt_controller) {
DCHECK(options_->filters.has_value() || options_->accept_all_advertisements);
client_.set_connection_error_handler(base::BindRepeating(
&ScanningClient::DisconnectionHandler, base::Unretained(this)));
@@ -262,7 +308,12 @@ bool WebBluetoothServiceImpl::ScanningClient::SendEvent(
return false;
if (options_->accept_all_advertisements) {
- client_->ScanEvent(std::move(result));
+ if (prompt_controller_)
+ AddFilteredDeviceToPrompt(result->device->id.str(), result->name);
+
+ if (allow_send_event_)
+ client_->ScanEvent(std::move(result));
+
return true;
}
@@ -308,7 +359,11 @@ bool WebBluetoothServiceImpl::ScanningClient::SendEvent(
}
// TODO(crbug.com/707635): Support manufacturerData and serviceData filters.
- client_->ScanEvent(std::move(result));
+ if (prompt_controller_)
+ AddFilteredDeviceToPrompt(result->device->id.str(), result->name);
+
+ if (allow_send_event_)
+ client_->ScanEvent(std::move(result));
return true;
}
@@ -316,10 +371,36 @@ bool WebBluetoothServiceImpl::ScanningClient::SendEvent(
return true;
}
+void WebBluetoothServiceImpl::ScanningClient::RunRequestScanningStartCallback(
+ blink::mojom::WebBluetoothResult result) {
+ if (result == blink::mojom::WebBluetoothResult::SUCCESS) {
+ auto scanning_result =
+ blink::mojom::RequestScanningStartResult::NewOptions(options_.Clone());
+ std::move(callback_).Run(std::move(scanning_result));
+ } else if (result == blink::mojom::WebBluetoothResult::SCANNING_BLOCKED ||
+ result == blink::mojom::WebBluetoothResult::PROMPT_CANCELED) {
+ auto scanning_result =
+ blink::mojom::RequestScanningStartResult::NewErrorResult(result);
+ std::move(callback_).Run(std::move(scanning_result));
+ } else {
+ NOTREACHED();
+ }
+}
+
void WebBluetoothServiceImpl::ScanningClient::DisconnectionHandler() {
disconnected_ = true;
}
+void WebBluetoothServiceImpl::ScanningClient::AddFilteredDeviceToPrompt(
+ const std::string& device_id,
+ const base::Optional<std::string>& device_name) {
+ bool should_update_name = device_name.has_value();
+ base::string16 device_name_for_display =
+ base::UTF8ToUTF16(device_name.value_or(""));
+ prompt_controller_->AddFilteredDevice(device_id, should_update_name,
+ device_name_for_display);
+}
+
void WebBluetoothServiceImpl::DidFinishNavigation(
NavigationHandle* navigation_handle) {
if (navigation_handle->HasCommitted() &&
@@ -1077,21 +1158,58 @@ void WebBluetoothServiceImpl::RequestScanningStartImpl(
return;
}
- if (discovery_session_) {
- scanning_clients_.push_back(
- std::make_unique<ScanningClient>(std::move(client), options.Clone()));
- auto result = blink::mojom::RequestScanningStartResult::NewOptions(
- std::move(options));
+ const url::Origin requesting_origin =
+ render_frame_host_->GetLastCommittedOrigin();
+ const url::Origin embedding_origin =
+ web_contents()->GetMainFrame()->GetLastCommittedOrigin();
+
+ bool blocked = GetContentClient()->browser()->IsBluetoothScanningBlocked(
+ web_contents()->GetBrowserContext(), requesting_origin, embedding_origin);
+
+ if (blocked) {
+ auto result = blink::mojom::RequestScanningStartResult::NewErrorResult(
+ blink::mojom::WebBluetoothResult::SCANNING_BLOCKED);
std::move(callback).Run(std::move(result));
return;
}
- discovery_callbacks_.push_back(std::move(callback));
+ if (discovery_callback_) {
+ auto result = blink::mojom::RequestScanningStartResult::NewErrorResult(
+ blink::mojom::WebBluetoothResult::PROMPT_CANCELED);
+ std::move(callback).Run(std::move(result));
+ return;
+ }
+
+ if (discovery_session_) {
+ if (AreScanFiltersAllowed(options->filters)) {
+ auto scanning_client = std::make_unique<ScanningClient>(
+ std::move(client), std::move(options), std::move(callback), nullptr);
+ scanning_client->RunRequestScanningStartCallback(
+ blink::mojom::WebBluetoothResult::SUCCESS);
+ scanning_client->set_allow_send_event(true);
+ scanning_clients_.push_back(std::move(scanning_client));
+ return;
+ }
+
+ // TODO(https://crbug.com/953075): If the scan filters aren't allowed by
+ // user, we need to update the filters which are used on the previously
+ // started discovery session.
- if (discovery_request_pending_)
+ // By resetting |device_scanning_prompt_controller_|, it returns an error if
+ // there are duplicate calls to RequestScanningStart().
+ device_scanning_prompt_controller_ =
+ std::make_unique<BluetoothDeviceScanningPromptController>(
+ this, render_frame_host_);
+
+ scanning_clients_.push_back(std::make_unique<ScanningClient>(
+ std::move(client), std::move(options), std::move(callback),
+ device_scanning_prompt_controller_.get()));
+ device_scanning_prompt_controller_->ShowPermissionPrompt();
return;
+ }
+
+ discovery_callback_ = std::move(callback);
- discovery_request_pending_ = true;
adapter->StartDiscoverySession(
base::Bind(&WebBluetoothServiceImpl::OnStartDiscoverySession,
weak_ptr_factory_.GetWeakPtr(), base::Passed(&client),
@@ -1107,31 +1225,37 @@ void WebBluetoothServiceImpl::OnStartDiscoverySession(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!discovery_session_);
- discovery_request_pending_ = false;
discovery_session_ = std::move(session);
- scanning_clients_.push_back(
- std::make_unique<ScanningClient>(std::move(client), options.Clone()));
- for (auto& callback : discovery_callbacks_) {
- auto result =
- blink::mojom::RequestScanningStartResult::NewOptions(options.Clone());
- std::move(callback).Run(std::move(result));
+ if (AreScanFiltersAllowed(options->filters)) {
+ auto scanning_client = std::make_unique<ScanningClient>(
+ std::move(client), std::move(options), std::move(discovery_callback_),
+ nullptr);
+ scanning_client->RunRequestScanningStartCallback(
+ blink::mojom::WebBluetoothResult::SUCCESS);
+ scanning_client->set_allow_send_event(true);
+ scanning_clients_.push_back(std::move(scanning_client));
+ return;
}
- discovery_callbacks_.clear();
+ device_scanning_prompt_controller_ =
+ std::make_unique<BluetoothDeviceScanningPromptController>(
+ this, render_frame_host_);
+
+ scanning_clients_.push_back(std::make_unique<ScanningClient>(
+ std::move(client), std::move(options), std::move(discovery_callback_),
+ device_scanning_prompt_controller_.get()));
+ device_scanning_prompt_controller_->ShowPermissionPrompt();
}
void WebBluetoothServiceImpl::OnDiscoverySessionError() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- discovery_request_pending_ = false;
- for (auto& callback : discovery_callbacks_) {
- auto result = blink::mojom::RequestScanningStartResult::NewErrorResult(
- blink::mojom::WebBluetoothResult::NO_BLUETOOTH_ADAPTER);
- std::move(callback).Run(std::move(result));
- }
+ device_scanning_prompt_controller_.reset();
- discovery_callbacks_.clear();
+ auto result = blink::mojom::RequestScanningStartResult::NewErrorResult(
+ blink::mojom::WebBluetoothResult::NO_BLUETOOTH_ADAPTER);
+ std::move(discovery_callback_).Run(std::move(result));
}
void WebBluetoothServiceImpl::RequestDeviceImpl(
@@ -1562,6 +1686,50 @@ BluetoothAllowedDevices& WebBluetoothServiceImpl::allowed_devices() {
return allowed_devices_map->GetOrCreateAllowedDevices(GetOrigin());
}
+void WebBluetoothServiceImpl::StoreAllowedScanOptions(
+ const blink::mojom::WebBluetoothRequestLEScanOptions& options) {
+ if (options.filters.has_value()) {
+ for (const auto& filter : options.filters.value())
+ allowed_scan_filters_.push_back(filter.Clone());
+ } else {
+ accept_all_advertisements_ = true;
+ }
+}
+
+bool WebBluetoothServiceImpl::AreScanFiltersAllowed(
+ const base::Optional<ScanFilters>& filters) const {
+ if (accept_all_advertisements_) {
+ // Previously allowed accepting all advertisements and no filters. In this
+ // case since filtered advertisements are a subset of all advertisements,
+ // any filters should be allowed.
+ return true;
+ }
+
+ if (!filters.has_value()) {
+ // |acceptAllAdvertisements| is set in the Bluetooth scanning options, but
+ // accepting all advertisements has not been allowed yet, in this case the
+ // permission prompt needs to be shown to the user.
+ return false;
+ }
+
+ // If each |filter| in |filters| can be found in |allowed_scan_filters_|,
+ // then |filters| are allowed, otherwise |filters| are not allowed.
+ for (const auto& filter : filters.value()) {
+ bool allowed = false;
+ for (const auto& allowed_filter : allowed_scan_filters_) {
+ if (AreScanFiltersSame(*filter, *allowed_filter)) {
+ allowed = true;
+ break;
+ }
+ }
+
+ if (!allowed)
+ return false;
+ }
+
+ return true;
+}
+
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.
@@ -1576,6 +1744,9 @@ void WebBluetoothServiceImpl::ClearState() {
connected_devices_.reset(
new FrameConnectedBluetoothDevices(render_frame_host_));
device_chooser_controller_.reset();
+ device_scanning_prompt_controller_.reset();
+ allowed_scan_filters_.clear();
+ accept_all_advertisements_ = false;
BluetoothAdapterFactoryWrapper::Get().ReleaseAdapter(this);
}
diff --git a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
index 6a3c47118f6..70033cee06d 100644
--- a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
+++ b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -14,6 +14,7 @@
#include "content/browser/bad_message.h"
#include "content/browser/bluetooth/bluetooth_allowed_devices.h"
#include "content/common/content_export.h"
+#include "content/public/browser/bluetooth_scanning_prompt.h"
#include "content/public/browser/web_contents_observer.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_discovery_session.h"
@@ -23,7 +24,7 @@
#include "device/bluetooth/bluetooth_remote_gatt_service.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_ptr_set.h"
-#include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
namespace url {
class Origin;
@@ -32,6 +33,7 @@ class Origin;
namespace content {
class BluetoothDeviceChooserController;
+class BluetoothDeviceScanningPromptController;
struct CacheQueryResult;
class FrameConnectedBluetoothDevices;
struct GATTNotifySessionAndCharacteristicClient;
@@ -72,24 +74,59 @@ class CONTENT_EXPORT WebBluetoothServiceImpl
// GetLastCommittedOrigin().
bool IsDevicePaired(const std::string& device_address);
+ // Informs each client in |scanning_clients_| of the user's permission
+ // decision.
+ void OnBluetoothScanningPromptEvent(
+ BluetoothScanningPrompt::Event event,
+ BluetoothDeviceScanningPromptController* prompt_controller);
+
private:
friend class FrameConnectedBluetoothDevicesTest;
using PrimaryServicesRequestCallback =
base::OnceCallback<void(device::BluetoothDevice*)>;
+ using ScanFilters = std::vector<blink::mojom::WebBluetoothLeScanFilterPtr>;
class ScanningClient {
public:
ScanningClient(blink::mojom::WebBluetoothScanClientAssociatedPtr client,
- blink::mojom::WebBluetoothRequestLEScanOptionsPtr options);
+ blink::mojom::WebBluetoothRequestLEScanOptionsPtr options,
+ RequestScanningStartCallback callback,
+ BluetoothDeviceScanningPromptController* prompt_controller);
~ScanningClient();
bool SendEvent(blink::mojom::WebBluetoothScanResultPtr result);
+ void set_prompt_controller(
+ BluetoothDeviceScanningPromptController* prompt_controller) {
+ prompt_controller_ = prompt_controller;
+ }
+
+ BluetoothDeviceScanningPromptController* prompt_controller() {
+ return prompt_controller_;
+ }
+
+ void set_allow_send_event(bool allow_send_event) {
+ allow_send_event_ = allow_send_event;
+ }
+
+ void RunRequestScanningStartCallback(
+ blink::mojom::WebBluetoothResult result);
+
+ const blink::mojom::WebBluetoothRequestLEScanOptions& scan_options() {
+ return *options_;
+ }
+
private:
void DisconnectionHandler();
+ void AddFilteredDeviceToPrompt(
+ const std::string& device_id,
+ const base::Optional<std::string>& device_name);
bool disconnected_ = false;
+ bool allow_send_event_ = false;
mojo::AssociatedInterfacePtr<blink::mojom::WebBluetoothScanClient> client_;
blink::mojom::WebBluetoothRequestLEScanOptionsPtr options_;
+ RequestScanningStartCallback callback_;
+ BluetoothDeviceScanningPromptController* prompt_controller_;
};
// WebContentsObserver:
@@ -303,12 +340,20 @@ class CONTENT_EXPORT WebBluetoothServiceImpl
url::Origin GetOrigin();
BluetoothAllowedDevices& allowed_devices();
+ void StoreAllowedScanOptions(
+ const blink::mojom::WebBluetoothRequestLEScanOptions& options);
+ bool AreScanFiltersAllowed(const base::Optional<ScanFilters>& filters) const;
+
// Clears all state (maps, sets, etc).
void ClearState();
// Used to open a BluetoothChooser and start a device discovery session.
std::unique_ptr<BluetoothDeviceChooserController> device_chooser_controller_;
+ // Used to open a BluetoothScanningPrompt.
+ std::unique_ptr<BluetoothDeviceScanningPromptController>
+ device_scanning_prompt_controller_;
+
// Maps to get the object's parent based on its instanceID.
std::unordered_map<std::string, std::string> service_id_to_device_address_;
std::unordered_map<std::string, std::string> characteristic_id_to_service_id_;
@@ -331,19 +376,23 @@ class CONTENT_EXPORT WebBluetoothServiceImpl
// The RFH that owns this instance.
RenderFrameHost* render_frame_host_;
- // True, if there is a pending request to start or stop discovery.
- bool discovery_request_pending_ = false;
-
// Keeps track of our BLE scanning session.
std::unique_ptr<device::BluetoothDiscoverySession> discovery_session_;
- // This vector queues up start callbacks so that we only have one
+ // This queues up start callback so that we only have one
// BluetoothDiscoverySession start request at a time.
- std::vector<RequestScanningStartCallback> discovery_callbacks_;
+ RequestScanningStartCallback discovery_callback_;
// List of clients that we must broadcast scan changes to.
std::vector<std::unique_ptr<ScanningClient>> scanning_clients_;
+ // Allowed Bluetooth scanning filters.
+ ScanFilters allowed_scan_filters_;
+
+ // Whether a site has been allowed to receive all Bluetooth advertisement
+ // packets.
+ bool accept_all_advertisements_ = false;
+
// The lifetime of this instance is exclusively managed by the RFH that
// owns it so we use a "Binding" as opposed to a "StrongBinding" which deletes
// the service on pipe connection errors.
diff --git a/chromium/content/browser/browser_context.cc b/chromium/content/browser/browser_context.cc
index b2b3920da3b..0d95af0ef88 100644
--- a/chromium/content/browser/browser_context.cc
+++ b/chromium/content/browser/browser_context.cc
@@ -25,6 +25,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
+#include "base/metrics/field_trial_params.h"
#include "base/no_destructor.h"
#include "base/rand_util.h"
#include "base/supports_user_data.h"
@@ -38,7 +39,6 @@
#include "content/browser/child_process_security_policy_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/media/browser_feature_provider.h"
#include "content/browser/permissions/permission_controller_impl.h"
@@ -50,17 +50,19 @@
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/indexed_db_context.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/browser/site_instance.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
+#include "media/base/media_switches.h"
+#include "media/capabilities/in_memory_video_decode_stats_db_impl.h"
#include "media/capabilities/video_decode_stats_db_impl.h"
#include "media/mojo/services/video_decode_perf_history.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "net/cookies/cookie_store.h"
-#include "net/ssl/channel_id_service.h"
-#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"
@@ -225,7 +227,7 @@ void SaveSessionStateOnIOThread(
}
void SaveSessionStateOnIndexedDBThread(
- scoped_refptr<IndexedDBContextImpl> indexed_db_context) {
+ scoped_refptr<IndexedDBContext> indexed_db_context) {
indexed_db_context->SetForceKeepSessionState();
}
@@ -511,12 +513,13 @@ void BrowserContext::DeliverPushMessage(
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
+ const std::string& message_id,
base::Optional<std::string> payload,
- const base::Callback<void(mojom::PushDeliveryStatus)>& callback) {
+ const base::Callback<void(blink::mojom::PushDeliveryStatus)>& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PushMessagingRouter::DeliverMessage(browser_context, origin,
service_worker_registration_id,
- std::move(payload), callback);
+ message_id, std::move(payload), callback);
}
// static
@@ -598,7 +601,6 @@ void BrowserContext::SaveSessionState(BrowserContext* browser_context) {
if (BrowserThread::IsThreadInitialized(BrowserThread::IO)) {
scoped_refptr<net::URLRequestContextGetter> context_getter;
- // Channel ID isn't supported with network service.
if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
context_getter = storage_partition->GetURLRequestContext();
base::PostTaskWithTraits(
@@ -616,16 +618,12 @@ void BrowserContext::SaveSessionState(BrowserContext* browser_context) {
storage_partition->GetDOMStorageContext());
dom_storage_context_proxy->SetForceKeepSessionState();
- IndexedDBContextImpl* indexed_db_context_impl =
- static_cast<IndexedDBContextImpl*>(
- storage_partition->GetIndexedDBContext());
- // No task runner in unit tests.
- if (indexed_db_context_impl->TaskRunner()) {
- indexed_db_context_impl->TaskRunner()->PostTask(
- FROM_HERE,
- base::BindOnce(&SaveSessionStateOnIndexedDBThread,
- base::WrapRefCounted(indexed_db_context_impl)));
- }
+ scoped_refptr<IndexedDBContext> indexed_db_context =
+ storage_partition->GetIndexedDBContext();
+ IndexedDBContext* const indexed_db_context_ptr = indexed_db_context.get();
+ indexed_db_context_ptr->TaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&SaveSessionStateOnIndexedDBThread,
+ std::move(indexed_db_context)));
}
void BrowserContext::SetDownloadManagerForTesting(
@@ -658,20 +656,20 @@ void BrowserContext::Initialize(
// NOTE: Many unit tests create a TestBrowserContext without initializing
// Mojo or the global service manager connection.
- service_manager::mojom::ServicePtr service;
- auto service_request = mojo::MakeRequest(&service);
+ mojo::PendingRemote<service_manager::mojom::Service> service;
+ auto service_receiver = service.InitWithNewPipeAndPassReceiver();
- service_manager::mojom::PIDReceiverPtr pid_receiver;
+ mojo::Remote<service_manager::mojom::ProcessMetadata> metadata;
service_manager::Identity identity(mojom::kBrowserServiceName, new_group,
base::Token{},
base::Token::CreateRandom());
service_manager_connection->GetConnector()->RegisterServiceInstance(
- identity, std::move(service), mojo::MakeRequest(&pid_receiver));
- pid_receiver->SetPID(base::GetCurrentProcId());
+ identity, std::move(service), metadata.BindNewPipeAndPassReceiver());
+ metadata->SetPID(base::GetCurrentProcId());
BrowserContextServiceManagerConnectionHolder* connection_holder =
new BrowserContextServiceManagerConnectionHolder(
- browser_context, std::move(service_request),
+ browser_context, std::move(service_receiver),
base::SequencedTaskRunnerHandle::Get());
browser_context->SetUserData(kServiceManagerConnection,
base::WrapUnique(connection_holder));
@@ -790,9 +788,21 @@ media::VideoDecodePerfHistory* BrowserContext::GetVideoDecodePerfHistory() {
// occurs later upon first VideoDecodePerfHistory API request that requires DB
// access. DB operations will not block the UI thread.
if (!decode_history) {
- std::unique_ptr<media::VideoDecodeStatsDBImpl> stats_db =
- media::VideoDecodeStatsDBImpl::Create(
- GetPath().Append(FILE_PATH_LITERAL("VideoDecodeStats")));
+ const char kUseInMemoryDBParamName[] = "db_in_memory";
+ const bool kUseInMemoryDBDefault = false;
+ bool use_in_memory_db = base::GetFieldTrialParamByFeatureAsBool(
+ media::kMediaCapabilitiesWithParameters, kUseInMemoryDBParamName,
+ kUseInMemoryDBDefault);
+
+ std::unique_ptr<media::VideoDecodeStatsDB> stats_db;
+ if (use_in_memory_db) {
+ stats_db =
+ std::make_unique<media::InMemoryVideoDecodeStatsDBImpl>(nullptr);
+ } else {
+ stats_db = media::VideoDecodeStatsDBImpl::Create(
+ GetPath().Append(FILE_PATH_LITERAL("VideoDecodeStats")));
+ }
+
auto new_decode_history = std::make_unique<media::VideoDecodePerfHistory>(
std::move(stats_db), BrowserFeatureProvider::GetFactoryCB());
decode_history = new_decode_history.get();
@@ -825,4 +835,8 @@ BrowserContext::GetSharedCorsOriginAccessList() const {
return empty_list->get();
}
+SmsService* BrowserContext::GetSmsService() {
+ return nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index 6e3dfde1019..dc34314c001 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -145,7 +145,6 @@
#include "skia/ext/skia_memory_dump_provider.h"
#include "sql/sql_memory_dump_provider.h"
#include "ui/base/clipboard/clipboard.h"
-#include "ui/base/ui_base_features.h"
#include "ui/display/display_features.h"
#include "ui/gfx/font_render_params.h"
#include "ui/gfx/switches.h"
@@ -198,6 +197,7 @@
#if defined(OS_CHROMEOS)
#include "base/memory/memory_pressure_monitor_chromeos.h"
+#include "base/memory/memory_pressure_monitor_notifying_chromeos.h"
#include "chromeos/constants/chromeos_switches.h"
#endif
@@ -313,32 +313,6 @@ NOINLINE void ResetThread_IO(
base::debug::Alias(&line_number);
}
-#if defined(OS_WIN)
-// Creates a memory pressure monitor using automatic thresholds, or those
-// specified on the command-line. Ownership is passed to the caller.
-std::unique_ptr<base::win::MemoryPressureMonitor>
-CreateWinMemoryPressureMonitor(const base::CommandLine& parsed_command_line) {
- std::vector<std::string> thresholds =
- base::SplitString(parsed_command_line.GetSwitchValueASCII(
- switches::kMemoryPressureThresholdsMb),
- ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-
- int moderate_threshold_mb = 0;
- int critical_threshold_mb = 0;
- if (thresholds.size() == 2 &&
- base::StringToInt(thresholds[0], &moderate_threshold_mb) &&
- base::StringToInt(thresholds[1], &critical_threshold_mb) &&
- moderate_threshold_mb >= critical_threshold_mb &&
- critical_threshold_mb >= 0) {
- return std::make_unique<base::win::MemoryPressureMonitor>(
- moderate_threshold_mb, critical_threshold_mb);
- }
-
- // In absence of valid switches use the automatic defaults.
- return std::make_unique<base::win::MemoryPressureMonitor>();
-}
-#endif // defined(OS_WIN)
-
enum WorkerPoolType : size_t {
BACKGROUND = 0,
BACKGROUND_BLOCKING,
@@ -409,6 +383,15 @@ std::unique_ptr<base::MemoryPressureMonitor> CreateMemoryPressureMonitor(
// concrete class.
#if defined(OS_CHROMEOS)
if (chromeos::switches::MemoryPressureHandlingEnabled()) {
+ if (base::chromeos::MemoryPressureMonitorNotifying::
+ SupportsKernelNotifications()) {
+ // We will use the MemoryPressureNotifying instance as our kernel supports
+ // notifications on memory level changes.
+ return std::make_unique<base::chromeos::MemoryPressureMonitorNotifying>();
+ }
+
+ // Our kernel does support notifications, so use the old 1s polling
+ // implementation.
return std::make_unique<base::chromeos::MemoryPressureMonitor>(
chromeos::switches::GetMemoryPressureThresholds());
}
@@ -416,7 +399,7 @@ std::unique_ptr<base::MemoryPressureMonitor> CreateMemoryPressureMonitor(
#elif defined(OS_MACOSX)
return std::make_unique<base::mac::MemoryPressureMonitor>();
#elif defined(OS_WIN)
- return CreateWinMemoryPressureMonitor(command_line);
+ return std::make_unique<base::win::MemoryPressureMonitor>();
#else
// No memory monitor on other platforms...
return nullptr;
@@ -449,8 +432,8 @@ class GpuDataManagerVisualProxy : public GpuDataManagerObserver {
!gpu_data_manager_->GpuAccessAllowed(nullptr),
gpu_info.system_visual, gpu_info.rgba_visual)) {
// The GPU process sent back bad visuals, which should never happen.
- auto* gpu_process_host = GpuProcessHost::Get(
- GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false);
+ auto* gpu_process_host =
+ GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED, false);
if (gpu_process_host)
gpu_process_host->ForceShutdown();
}
@@ -486,7 +469,7 @@ class HDRProxy {
private:
static void RequestOnIOThread() {
auto* gpu_process_host =
- GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false);
+ GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED, false);
if (gpu_process_host) {
auto* gpu_service = gpu_process_host->gpu_host()->gpu_service();
gpu_service->RequestHDRStatus(
@@ -540,7 +523,7 @@ media::AudioManager* BrowserMainLoop::GetAudioManager() {
BrowserMainLoop::BrowserMainLoop(
const MainFunctionParams& parameters,
- std::unique_ptr<base::ThreadPool::ScopedExecutionFence>
+ std::unique_ptr<base::ThreadPoolInstance::ScopedExecutionFence>
scoped_execution_fence)
: parameters_(parameters),
parsed_command_line_(parameters.command_line),
@@ -553,7 +536,7 @@ BrowserMainLoop::BrowserMainLoop(
g_current_browser_main_loop = this;
if (GetContentClient()->browser()->ShouldCreateThreadPool()) {
- DCHECK(base::ThreadPool::GetInstance());
+ DCHECK(base::ThreadPoolInstance::Get());
}
}
@@ -576,10 +559,10 @@ void BrowserMainLoop::Init() {
// resets it).
io_thread_ = std::move(startup_data->thread);
service_manager_context_ = startup_data->service_manager_context;
+ power_monitor_ = std::move(startup_data->power_monitor);
}
- parts_.reset(
- GetContentClient()->browser()->CreateBrowserMainParts(parameters_));
+ parts_ = GetContentClient()->browser()->CreateBrowserMainParts(parameters_);
}
// BrowserMainLoop stages ==================================================
@@ -701,10 +684,10 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
}
{
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:PowerMonitor");
- std::unique_ptr<base::PowerMonitorSource> power_monitor_source(
- new base::PowerMonitorDeviceSource());
- power_monitor_.reset(
- new base::PowerMonitor(std::move(power_monitor_source)));
+ if (!power_monitor_) {
+ power_monitor_ = std::make_unique<base::PowerMonitor>(
+ std::make_unique<base::PowerMonitorDeviceSource>());
+ }
}
{
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:HighResTimerManager");
@@ -712,7 +695,10 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
}
{
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:NetworkChangeNotifier");
- network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
+ // On Android if reduced mode started network service this would already be
+ // created.
+ if (!net::NetworkChangeNotifier::HasNetworkChangeNotifier())
+ network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
}
{
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:ScreenlockMonitor");
@@ -742,15 +728,13 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}));
}
- if (!features::IsMultiProcessMash()) {
- discardable_shared_memory_manager_ =
- std::make_unique<discardable_memory::DiscardableSharedMemoryManager>();
- // TODO(boliu): kSingleProcess check is a temporary workaround for
- // in-process Android WebView. crbug.com/503724 tracks proper fix.
- if (!parsed_command_line_.HasSwitch(switches::kSingleProcess)) {
- base::DiscardableMemoryAllocator::SetInstance(
- discardable_shared_memory_manager_.get());
- }
+ discardable_shared_memory_manager_ =
+ std::make_unique<discardable_memory::DiscardableSharedMemoryManager>();
+ // TODO(boliu): kSingleProcess check is a temporary workaround for
+ // in-process Android WebView. crbug.com/503724 tracks proper fix.
+ if (!parsed_command_line_.HasSwitch(switches::kSingleProcess)) {
+ base::DiscardableMemoryAllocator::SetInstance(
+ discardable_shared_memory_manager_.get());
}
if (parts_)
@@ -960,9 +944,19 @@ int BrowserMainLoop::CreateThreads() {
// CreateThreads() (as such maintaining the invariant that PreCreateThreads()
// et al. "happen-before" BrowserThread::IO is "brought up").
if (!io_thread_) {
- io_thread_ = BrowserProcessSubThread::CreateIOThread();
+ io_thread_ = BrowserTaskExecutor::CreateIOThread();
}
io_thread_->RegisterAsBrowserThread();
+ BrowserTaskExecutor::InitializeIOThread();
+
+ // TODO(https://crbug.com/863341): Replace with a better API
+ GetContentClient()->browser()->PostAfterStartupTask(
+ FROM_HERE, base::SequencedTaskRunnerHandle::Get(), base::BindOnce([]() {
+ // Non best effort queues will already have been enabled
+ // This will enable all queues on all browser threads, so we need to do
+ // this after the threads have been created, i.e. here.
+ content::BrowserTaskExecutor::EnableAllQueues();
+ }));
created_threads_ = true;
return result_code_;
@@ -1032,8 +1026,8 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
// Also allow waiting to join threads.
// TODO(https://crbug.com/800808): Ideally this (and the above SetIOAllowed()
// would be scoped allowances). That would be one of the first step to ensure
- // no persistent work is being done after ThreadPool::Shutdown() in order
- // to move towards atomic shutdown.
+ // no persistent work is being done after ThreadPoolInstance::Shutdown() in
+ // order to move towards atomic shutdown.
base::ThreadRestrictions::SetWaitAllowed(true);
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
@@ -1121,7 +1115,7 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
{
TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:ThreadPool");
- base::ThreadPool::GetInstance()->Shutdown();
+ base::ThreadPoolInstance::Get()->Shutdown();
}
// Must happen after the IO thread is shutdown since this may be accessed from
@@ -1189,12 +1183,6 @@ void BrowserMainLoop::GetCompositingModeReporter(
// CompositingModeReporter.
return;
#else
- if (features::IsMultiProcessMash()) {
- // Mash == ChromeOS, which doesn't support software compositing, so no need
- // to report compositing mode.
- return;
- }
-
compositing_mode_reporter_impl_->BindRequest(std::move(request));
#endif
}
@@ -1209,11 +1197,6 @@ void BrowserMainLoop::InitializeMainThread() {
DCHECK(base::ThreadTaskRunnerHandle::IsSet());
main_thread_.reset(new BrowserThreadImpl(
BrowserThread::UI, base::ThreadTaskRunnerHandle::Get()));
- // TODO(https://crbug.com/863341): Replace with a better API
- GetContentClient()->browser()->PostAfterStartupTask(
- FROM_HERE, base::SequencedTaskRunnerHandle::Get(), base::BindOnce([]() {
- content::BrowserTaskExecutor::NotifyBrowserStartupCompleted();
- }));
}
int BrowserMainLoop::BrowserThreadsStarted() {
@@ -1224,13 +1207,6 @@ int BrowserMainLoop::BrowserThreadsStarted() {
// so this cannot happen any earlier than now.
InitializeMojo();
-#if BUILDFLAG(ENABLE_MUS)
- if (features::IsUsingWindowService()) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableSurfaceSynchronization);
- }
-#endif
-
HistogramSynchronizer::GetInstance();
// cc assumes a single client name for metrics in a process, which is
@@ -1259,9 +1235,6 @@ int BrowserMainLoop::BrowserThreadsStarted() {
&viz::GpuHostImpl::InitFontRenderParams,
gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr)));
- // If ash/ws is not hosting viz, then the browser must.
- bool browser_is_viz_host = !features::IsMultiProcessMash();
-
bool always_uses_gpu = true;
bool established_gpu_channel = false;
#if defined(OS_ANDROID)
@@ -1273,49 +1246,45 @@ int BrowserMainLoop::BrowserThreadsStarted() {
established_gpu_channel = true;
if (parsed_command_line_.HasSwitch(switches::kDisableGpu) ||
parsed_command_line_.HasSwitch(switches::kDisableGpuCompositing) ||
- parsed_command_line_.HasSwitch(switches::kDisableGpuEarlyInit) ||
- !browser_is_viz_host) {
+ parsed_command_line_.HasSwitch(switches::kDisableGpuEarlyInit)) {
established_gpu_channel = always_uses_gpu = false;
}
- if (browser_is_viz_host) {
- host_frame_sink_manager_ = std::make_unique<viz::HostFrameSinkManager>();
- BrowserGpuChannelHostFactory::Initialize(established_gpu_channel);
- compositing_mode_reporter_impl_ =
- std::make_unique<viz::CompositingModeReporterImpl>();
+ host_frame_sink_manager_ = std::make_unique<viz::HostFrameSinkManager>();
+ BrowserGpuChannelHostFactory::Initialize(established_gpu_channel);
+ compositing_mode_reporter_impl_ =
+ std::make_unique<viz::CompositingModeReporterImpl>();
+
+ if (features::IsVizDisplayCompositorEnabled()) {
+ auto transport_factory = std::make_unique<VizProcessTransportFactory>(
+ BrowserGpuChannelHostFactory::instance(), GetResizeTaskRunner(),
+ compositing_mode_reporter_impl_.get());
+ transport_factory->ConnectHostFrameSinkManager();
+ ImageTransportFactory::SetFactory(std::move(transport_factory));
+ } else {
+ server_shared_bitmap_manager_ =
+ std::make_unique<viz::ServerSharedBitmapManager>();
+ viz::FrameSinkManagerImpl::InitParams params;
+ params.shared_bitmap_manager = server_shared_bitmap_manager_.get();
+ params.activation_deadline_in_frames =
+ switches::GetDeadlineToSynchronizeSurfaces();
+ frame_sink_manager_impl_ =
+ std::make_unique<viz::FrameSinkManagerImpl>(params);
+
+ surface_utils::ConnectWithLocalFrameSinkManager(
+ host_frame_sink_manager_.get(), frame_sink_manager_impl_.get(),
+ base::ThreadTaskRunnerHandle::Get());
- if (features::IsVizDisplayCompositorEnabled()) {
- auto transport_factory = std::make_unique<VizProcessTransportFactory>(
- BrowserGpuChannelHostFactory::instance(), GetResizeTaskRunner(),
- compositing_mode_reporter_impl_.get());
- 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(),
- base::ThreadTaskRunnerHandle::Get());
-
- ImageTransportFactory::SetFactory(
- std::make_unique<GpuProcessTransportFactory>(
- BrowserGpuChannelHostFactory::instance(),
- compositing_mode_reporter_impl_.get(),
- server_shared_bitmap_manager_.get(), GetResizeTaskRunner()));
- }
+ ImageTransportFactory::SetFactory(
+ std::make_unique<GpuProcessTransportFactory>(
+ BrowserGpuChannelHostFactory::instance(),
+ compositing_mode_reporter_impl_.get(),
+ server_shared_bitmap_manager_.get(), GetResizeTaskRunner()));
}
#if defined(USE_AURA)
- // In single process mash mode the aura::Env created here uses the
- // WindowService, and needs to use the context-factory from aura.
- if (browser_is_viz_host && !features::IsSingleProcessMash()) {
- env_->set_context_factory(GetContextFactory());
- env_->set_context_factory_private(GetContextFactoryPrivate());
- }
+ env_->set_context_factory(GetContextFactory());
+ env_->set_context_factory_private(GetContextFactoryPrivate());
#endif // defined(USE_AURA)
#endif // !defined(OS_ANDROID)
@@ -1344,8 +1313,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
}
#if defined(OS_WIN)
- if (base::FeatureList::IsEnabled(display::features::kHighDynamicRange))
- HDRProxy::Initialize();
+ HDRProxy::Initialize();
system_message_window_.reset(new media::SystemMessageWindowWin);
#elif defined(OS_LINUX) && defined(USE_UDEV)
device_monitor_linux_ = std::make_unique<media::DeviceMonitorLinux>();
@@ -1442,14 +1410,13 @@ int BrowserMainLoop::BrowserThreadsStarted() {
ui::Clipboard::SetAllowedThreads(allowed_clipboard_threads);
if (GpuDataManagerImpl::GetInstance()->GpuProcessStartAllowed() &&
- !established_gpu_channel && always_uses_gpu && browser_is_viz_host) {
+ !established_gpu_channel && always_uses_gpu) {
TRACE_EVENT_INSTANT0("gpu", "Post task to launch GPU process",
TRACE_EVENT_SCOPE_THREAD);
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(base::IgnoreResult(&GpuProcessHost::Get),
- GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- true /* force_create */));
+ GPU_PROCESS_KIND_SANDBOXED, true /* force_create */));
}
#if defined(OS_WIN)
@@ -1460,7 +1427,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
if (base::FeatureList::IsEnabled(features::kFontSrcLocalMatching)) {
content::DWriteFontLookupTableBuilder::GetInstance()
- ->SchedulePrepareFontUniqueNameTable();
+ ->SchedulePrepareFontUniqueNameTableIfNeeded();
}
#endif
@@ -1541,9 +1508,7 @@ 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::IsUsingWindowService()
- ? aura::Env::Mode::MUS
- : aura::Env::Mode::LOCAL);
+ env_ = aura::Env::CreateInstance();
#endif // defined(USE_AURA)
if (parts_)
@@ -1662,9 +1627,9 @@ void BrowserMainLoop::InitializeAudio() {
if (base::FeatureList::IsEnabled(features::kAudioServiceLaunchOnStartup)) {
// Schedule the audio service startup on the main thread.
- BrowserThread::PostAfterStartupTask(
+ base::PostTaskWithTraits(
FROM_HERE,
- base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}),
+ {content::BrowserThread::UI, base::TaskPriority::BEST_EFFORT},
base::BindOnce([]() {
TRACE_EVENT0("audio", "Starting audio service");
ServiceManagerConnection* connection =
diff --git a/chromium/content/browser/browser_main_loop.h b/chromium/content/browser/browser_main_loop.h
index 1fae7242c6c..aa4e4e29c77 100644
--- a/chromium/content/browser/browser_main_loop.h
+++ b/chromium/content/browser/browser_main_loop.h
@@ -129,11 +129,11 @@ class CONTENT_EXPORT BrowserMainLoop {
static media::AudioManager* GetAudioManager();
- // The ThreadPool instance must exist but not to be started when building
+ // The ThreadPoolInstance must exist but not to be started when building
// BrowserMainLoop.
explicit BrowserMainLoop(
const MainFunctionParams& parameters,
- std::unique_ptr<base::ThreadPool::ScopedExecutionFence> fence);
+ std::unique_ptr<base::ThreadPoolInstance::ScopedExecutionFence> fence);
virtual ~BrowserMainLoop();
void Init();
@@ -175,14 +175,16 @@ class CONTENT_EXPORT BrowserMainLoop {
media::UserInputMonitor* user_input_monitor() const {
return user_input_monitor_.get();
}
- net::NetworkChangeNotifier* network_change_notifier() const {
- return network_change_notifier_.get();
- }
MediaKeysListenerManagerImpl* media_keys_listener_manager() const {
return media_keys_listener_manager_.get();
}
#if defined(OS_CHROMEOS)
+ // Only expose this on ChromeOS since it's only needed there. On Android this
+ // be null if this process started in reduced mode.
+ net::NetworkChangeNotifier* network_change_notifier() const {
+ return network_change_notifier_.get();
+ }
KeyboardMicRegistration* keyboard_mic_registration() {
return &keyboard_mic_registration_;
}
@@ -241,6 +243,9 @@ class CONTENT_EXPORT BrowserMainLoop {
private:
FRIEND_TEST_ALL_PREFIXES(BrowserMainLoopTest, CreateThreadsInSingleProcess);
+ FRIEND_TEST_ALL_PREFIXES(
+ BrowserMainLoopTest,
+ PostTaskToIOThreadBeforeThreadCreationDoesNotRunTask);
void InitializeMainThread();
@@ -295,9 +300,9 @@ class CONTENT_EXPORT BrowserMainLoop {
// initialize-once happens-before relationship with all eventual content tasks
// running on other threads. This ScopedExecutionFence ensures that no tasks
// posted to ThreadPool gets to run before CreateThreads(); satisfying this
- // requirement even though the ThreadPool is created and started before
- // content is entered.
- std::unique_ptr<base::ThreadPool::ScopedExecutionFence>
+ // requirement even though the ThreadPoolInstance is created and started
+ // before content is entered.
+ std::unique_ptr<base::ThreadPoolInstance::ScopedExecutionFence>
scoped_execution_fence_;
// Members initialized in |MainMessageLoopStart()| ---------------------------
diff --git a/chromium/content/browser/browser_main_loop_unittest.cc b/chromium/content/browser/browser_main_loop_unittest.cc
index 66b7e9c8ee9..4c9e0734004 100644
--- a/chromium/content/browser/browser_main_loop_unittest.cc
+++ b/chromium/content/browser/browser_main_loop_unittest.cc
@@ -7,49 +7,108 @@
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/system/sys_info.h"
+#include "base/task/post_task.h"
#include "base/task/thread_pool/thread_pool.h"
+#include "base/test/mock_callback.h"
#include "base/test/scoped_command_line.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/scheduler/browser_task_executor.h"
+#include "content/browser/service_manager/service_manager_context.h"
+#include "content/browser/startup_data_impl.h"
#include "content/browser/startup_helper.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
+#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
-// Verify that a single-process browser process has at least as many threads as
-// the number of cores in its foreground pool.
-TEST(BrowserMainLoopTest, CreateThreadsInSingleProcess) {
- {
+using StrickMockTask =
+ testing::StrictMock<base::MockCallback<base::RepeatingCallback<void()>>>;
+
+class BrowserMainLoopTest : public testing::Test {
+ protected:
+ BrowserMainLoopTest() {
base::test::ScopedCommandLine scoped_command_line;
scoped_command_line.GetProcessCommandLine()->AppendSwitch(
switches::kSingleProcess);
- base::ThreadPool::Create("Browser");
+ base::ThreadPoolInstance::Create("Browser");
StartBrowserThreadPool();
BrowserTaskExecutor::Create();
- MainFunctionParams main_function_params(
- *scoped_command_line.GetProcessCommandLine());
+ }
+
+ ~BrowserMainLoopTest() override {
+ BrowserTaskExecutor::ResetForTesting();
+ for (int id = BrowserThread::UI; id < BrowserThread::ID_COUNT; ++id) {
+ BrowserThreadImpl::ResetGlobalsForTesting(
+ static_cast<BrowserThread::ID>(id));
+ }
+ base::ThreadPoolInstance::Get()->JoinForTesting();
+ base::ThreadPoolInstance::Set(nullptr);
+ }
+
+ const base::CommandLine& GetProcessCommandLine() {
+ return *scoped_command_line_.GetProcessCommandLine();
+ }
+
+ private:
+ base::test::ScopedCommandLine scoped_command_line_;
+}; // namespace content
+
+// Verify that a single-process browser process has at least as many threads as
+// the number of cores in its foreground pool.
+TEST_F(BrowserMainLoopTest, CreateThreadsInSingleProcess) {
+ {
+ MainFunctionParams main_function_params(GetProcessCommandLine());
+
BrowserMainLoop browser_main_loop(
main_function_params,
- std::make_unique<base::ThreadPool::ScopedExecutionFence>());
+ std::make_unique<base::ThreadPoolInstance::ScopedExecutionFence>());
browser_main_loop.MainMessageLoopStart();
browser_main_loop.Init();
browser_main_loop.CreateThreads();
- EXPECT_GE(base::ThreadPool::GetInstance()
+ EXPECT_GE(base::ThreadPoolInstance::Get()
->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
{base::TaskPriority::USER_VISIBLE}),
base::SysInfo::NumberOfProcessors() - 1);
browser_main_loop.ShutdownThreadsAndCleanUp();
}
- BrowserTaskExecutor::ResetForTesting();
- for (int id = BrowserThread::UI; id < BrowserThread::ID_COUNT; ++id) {
- BrowserThreadImpl::ResetGlobalsForTesting(
- static_cast<BrowserThread::ID>(id));
- }
- base::ThreadPool::GetInstance()->JoinForTesting();
- base::ThreadPool::SetInstance(nullptr);
+}
+
+TEST_F(BrowserMainLoopTest,
+ PostTaskToIOThreadBeforeThreadCreationDoesNotRunTask) {
+ MainFunctionParams main_function_params(GetProcessCommandLine());
+
+ auto service_manager_thread = BrowserTaskExecutor::CreateIOThread();
+ ServiceManagerContext service_manager_context(
+ service_manager_thread->task_runner());
+
+ StartupDataImpl startup_data;
+ startup_data.thread = std::move(service_manager_thread);
+ startup_data.service_manager_context = &service_manager_context;
+ main_function_params.startup_data = &startup_data;
+
+ BrowserMainLoop browser_main_loop(
+ main_function_params,
+ std::make_unique<base::ThreadPoolInstance::ScopedExecutionFence>());
+ browser_main_loop.MainMessageLoopStart();
+ browser_main_loop.Init();
+
+ StrickMockTask task;
+
+ // No task should run because IO thread has not been initialized yet.
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, task.Get());
+ base::CreateTaskRunnerWithTraits({BrowserThread::IO})
+ ->PostTask(FROM_HERE, task.Get());
+
+ content::RunAllPendingInMessageLoop(BrowserThread::IO);
+
+ EXPECT_CALL(task, Run).Times(2);
+ browser_main_loop.CreateThreads();
+ content::RunAllPendingInMessageLoop(BrowserThread::IO);
+
+ browser_main_loop.ShutdownThreadsAndCleanUp();
}
} // namespace content
diff --git a/chromium/content/browser/browser_main_runner_impl.cc b/chromium/content/browser/browser_main_runner_impl.cc
index 11845c22119..ec00bd53ac2 100644
--- a/chromium/content/browser/browser_main_runner_impl.cc
+++ b/chromium/content/browser/browser_main_runner_impl.cc
@@ -13,8 +13,6 @@
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "base/run_loop.h"
-#include "base/sampling_heap_profiler/sampling_heap_profiler.h"
-#include "base/strings/string_number_conversions.h"
#include "base/synchronization/atomic_flag.h"
#include "base/time/time.h"
#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
@@ -57,7 +55,7 @@ BrowserMainRunnerImpl::BrowserMainRunnerImpl()
: initialization_started_(false),
is_shutdown_(false),
scoped_execution_fence_(
- std::make_unique<base::ThreadPool::ScopedExecutionFence>()) {}
+ std::make_unique<base::ThreadPoolInstance::ScopedExecutionFence>()) {}
BrowserMainRunnerImpl::~BrowserMainRunnerImpl() {
if (initialization_started_ && !is_shutdown_)
@@ -78,19 +76,6 @@ int BrowserMainRunnerImpl::Initialize(const MainFunctionParams& parameters) {
const base::TimeTicks start_time_step1 = base::TimeTicks::Now();
- base::SamplingHeapProfiler::Init();
- if (parameters.command_line.HasSwitch(switches::kSamplingHeapProfiler)) {
- base::SamplingHeapProfiler* profiler = base::SamplingHeapProfiler::Get();
- unsigned sampling_interval = 0;
- bool parsed =
- base::StringToUint(parameters.command_line.GetSwitchValueASCII(
- switches::kSamplingHeapProfiler),
- &sampling_interval);
- if (parsed && sampling_interval > 0)
- profiler->SetSamplingInterval(sampling_interval * 1024);
- profiler->Start();
- }
-
SkGraphics::Init();
if (parameters.command_line.HasSwitch(switches::kWaitForDebugger))
diff --git a/chromium/content/browser/browser_main_runner_impl.h b/chromium/content/browser/browser_main_runner_impl.h
index a4f400a203a..1ea40b6930e 100644
--- a/chromium/content/browser/browser_main_runner_impl.h
+++ b/chromium/content/browser/browser_main_runner_impl.h
@@ -48,7 +48,7 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
// Prevents execution of ThreadPool tasks from the moment content is
// entered. Handed off to |main_loop_| later so it can decide when to release
// worker threads again.
- std::unique_ptr<base::ThreadPool::ScopedExecutionFence>
+ std::unique_ptr<base::ThreadPoolInstance::ScopedExecutionFence>
scoped_execution_fence_;
std::unique_ptr<NotificationServiceImpl> notification_service_;
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
index 5ec2e846138..dfd38d5252a 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -126,7 +126,7 @@ BrowserPluginGuest::BrowserPluginGuest(bool has_render_view,
has_render_view_(has_render_view),
is_in_destruction_(false),
initialized_(false),
- guest_proxy_routing_id_(MSG_ROUTING_NONE),
+ guest_render_view_routing_id_(MSG_ROUTING_NONE),
last_drag_status_(blink::kWebDragStatusUnknown),
seen_embedder_system_drag_ended_(false),
seen_embedder_drag_source_ended_at_(false),
@@ -139,54 +139,10 @@ BrowserPluginGuest::BrowserPluginGuest(bool has_render_view,
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
}
-int BrowserPluginGuest::GetGuestProxyRoutingID() {
- if (GuestMode::IsCrossProcessFrameGuest(GetWebContents())) {
- // We don't use the proxy to send postMessage in --site-per-process, since
- // we use the contentWindow directly from the frame element instead.
- return MSG_ROUTING_NONE;
- }
-
- if (guest_proxy_routing_id_ != MSG_ROUTING_NONE)
- return guest_proxy_routing_id_;
-
- // In order to enable the embedder to post messages to the
- // guest, we need to create a RenderFrameProxyHost in root node of guest
- // WebContents' frame tree (i.e., create a RenderFrameProxy in the embedder
- // process which can be used by the embedder to post messages to the guest).
- // The creation of RFPH for the reverse path, which enables the guest to post
- // messages to the embedder, will be postponed to when the embedder posts its
- // first message to the guest.
- //
- // TODO(fsamuel): Make sure this works for transferring guests across
- // owners in different processes. We probably need to clear the
- // |guest_proxy_routing_id_| and perform any necessary cleanup on Detach
- // to enable this.
- //
- // TODO(ekaramad): If the guest is embedded inside a cross-process <iframe>
- // (e.g., <embed>-ed PDF), the reverse proxy will not be created and the
- // posted message's source attribute will be null which in turn breaks the
- // two-way messaging between the guest and the embedder. We should either
- // create a RenderFrameProxyHost for the reverse path, or implement
- // MimeHandlerViewGuest using OOPIF (https://crbug.com/659750).
- SiteInstance* owner_site_instance = delegate_->GetOwnerSiteInstance();
- if (!owner_site_instance)
- return MSG_ROUTING_NONE;
- int proxy_routing_id = GetWebContents()
- ->GetFrameTree()
- ->root()
- ->render_manager()
- ->CreateRenderFrameProxy(owner_site_instance);
- guest_proxy_routing_id_ = RenderFrameProxyHost::FromID(
- owner_site_instance->GetProcess()->GetID(), proxy_routing_id)
- ->GetRenderViewHost()->GetRoutingID();
-
- return guest_proxy_routing_id_;
-}
-
int BrowserPluginGuest::LoadURLWithParams(
const NavigationController::LoadURLParams& load_params) {
GetWebContents()->GetController().LoadURLWithParams(load_params);
- return GetGuestProxyRoutingID();
+ return GetGuestRenderViewRoutingID();
}
void BrowserPluginGuest::EnableAutoResize(const gfx::Size& min_size,
@@ -226,6 +182,10 @@ RenderWidgetHostImpl* BrowserPluginGuest::GetOwnerRenderWidgetHost() const {
delegate_->GetOwnerRenderWidgetHost());
}
+RenderFrameHostImpl* BrowserPluginGuest::GetEmbedderFrame() const {
+ return static_cast<RenderFrameHostImpl*>(delegate_->GetEmbedderFrame());
+}
+
void BrowserPluginGuest::Init() {
if (initialized_)
return;
@@ -699,7 +659,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() && !features::IsMultiProcessMash()) {
+ if (attached()) {
RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
web_contents()->GetRenderWidgetHostView());
if (rwhv) {
@@ -871,7 +831,7 @@ void BrowserPluginGuest::OnWillAttachComplete(
attached_ = true;
SendQueuedMessages();
- delegate_->DidAttach(GetGuestProxyRoutingID());
+ delegate_->DidAttach(GetGuestRenderViewRoutingID());
RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
web_contents()->GetRenderWidgetHostView());
if (rwhv)
@@ -1162,4 +1122,48 @@ void BrowserPluginGuest::OnTakeFocus(bool reverse) {
browser_plugin_instance_id(), reverse));
}
+int BrowserPluginGuest::GetGuestRenderViewRoutingID() {
+ if (GuestMode::IsCrossProcessFrameGuest(GetWebContents())) {
+ // We don't use the proxy to send postMessage in --site-per-process, since
+ // we use the contentWindow directly from the frame element instead.
+ return MSG_ROUTING_NONE;
+ }
+
+ if (guest_render_view_routing_id_ != MSG_ROUTING_NONE)
+ return guest_render_view_routing_id_;
+
+ // In order to enable the embedder to post messages to the
+ // guest, we need to create a RenderFrameProxyHost in root node of guest
+ // WebContents' frame tree (i.e., create a RenderFrameProxy in the embedder
+ // process which can be used by the embedder to post messages to the guest).
+ // The creation of RFPH for the reverse path, which enables the guest to post
+ // messages to the embedder, will be postponed to when the embedder posts its
+ // first message to the guest.
+ //
+ // TODO(fsamuel): Make sure this works for transferring guests across
+ // owners in different processes. We probably need to clear the
+ // |guest_render_view_routing_id_| and perform any necessary cleanup on Detach
+ // to enable this.
+ //
+ // TODO(ekaramad): If the guest is embedded inside a cross-process <iframe>
+ // (e.g., <embed>-ed PDF), the reverse proxy will not be created and the
+ // posted message's source attribute will be null which in turn breaks the
+ // two-way messaging between the guest and the embedder. We should either
+ // create a RenderFrameProxyHost for the reverse path, or implement
+ // MimeHandlerViewGuest using OOPIF (https://crbug.com/659750).
+ SiteInstance* owner_site_instance = delegate_->GetOwnerSiteInstance();
+ if (!owner_site_instance)
+ return MSG_ROUTING_NONE;
+
+ RenderFrameHostManager* rfh_manager =
+ GetWebContents()->GetFrameTree()->root()->render_manager();
+ rfh_manager->CreateRenderFrameProxy(owner_site_instance);
+ guest_render_view_routing_id_ =
+ rfh_manager->GetRenderFrameProxyHost(owner_site_instance)
+ ->GetRenderViewHost()
+ ->GetRoutingID();
+
+ return guest_render_view_routing_id_;
+}
+
} // namespace content
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.h b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
index ca85a5dcfff..dbc5aa621f0 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
@@ -69,6 +69,7 @@ class LocalSurfaceIdAllocation;
namespace content {
class BrowserPluginGuestManager;
+class RenderFrameHostImpl;
class RenderViewHostImpl;
class RenderWidgetHost;
class RenderWidgetHostImpl;
@@ -153,10 +154,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
WebContentsImpl* CreateNewGuestWindow(
const WebContents::CreateParams& params);
- // Creates, if necessary, and returns the routing ID of a proxy for the guest
- // in the owner's renderer process.
- int GetGuestProxyRoutingID();
-
// Returns the identifier that uniquely identifies a browser plugin guest
// within an embedder.
int browser_plugin_instance_id() const { return browser_plugin_instance_id_; }
@@ -177,6 +174,9 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
// Returns nullptr otherwise.
RenderWidgetHostView* GetOwnerRenderWidgetHostView();
+ // Returns the embedder frame.
+ RenderFrameHostImpl* GetEmbedderFrame() const;
+
bool focused() const { return focused_; }
bool visible() const { return guest_visible_; }
@@ -397,6 +397,10 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
void SendTextInputTypeChangedToView(RenderWidgetHostViewBase* guest_rwhv);
+ // Creates, if necessary, and returns the routing ID of a render view for the
+ // guest in the owner's renderer process.
+ int GetGuestRenderViewRoutingID();
+
// The last tooltip that was set with SetTooltipText().
base::string16 current_tooltip_text_;
@@ -438,7 +442,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
// The is the routing ID for a swapped out RenderView for the guest
// WebContents in the embedder's process.
- int guest_proxy_routing_id_;
+ int guest_render_view_routing_id_;
// Last seen state of drag status update.
blink::WebDragStatus last_drag_status_;
// Whether or not our embedder has seen a SystemDragEnded() call.
diff --git a/chromium/content/browser/browser_process_sub_thread.cc b/chromium/content/browser/browser_process_sub_thread.cc
index 3e4873e4baf..e9d0f68e68d 100644
--- a/chromium/content/browser/browser_process_sub_thread.cc
+++ b/chromium/content/browser/browser_process_sub_thread.cc
@@ -76,24 +76,6 @@ void BrowserProcessSubThread::AllowBlockingForTesting() {
is_blocking_allowed_for_testing_ = true;
}
-// static
-std::unique_ptr<BrowserProcessSubThread>
-BrowserProcessSubThread::CreateIOThread() {
- TRACE_EVENT0("startup", "BrowserProcessSubThread::CreateIOThread");
- base::Thread::Options options;
- options.message_loop_type = base::MessageLoop::TYPE_IO;
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(USE_OZONE)
- // Up the priority of the |io_thread_| as some of its IPCs relate to
- // display tasks.
- options.priority = base::ThreadPriority::DISPLAY;
-#endif
- std::unique_ptr<BrowserProcessSubThread> io_thread(
- new BrowserProcessSubThread(BrowserThread::IO));
- if (!io_thread->StartWithOptions(options))
- LOG(FATAL) << "Failed to start BrowserThread:IO";
- return io_thread;
-}
-
void BrowserProcessSubThread::Init() {
DCHECK_CALLED_ON_VALID_THREAD(browser_thread_checker_);
diff --git a/chromium/content/browser/browser_process_sub_thread.h b/chromium/content/browser/browser_process_sub_thread.h
index edc223865ba..f4b87997e3f 100644
--- a/chromium/content/browser/browser_process_sub_thread.h
+++ b/chromium/content/browser/browser_process_sub_thread.h
@@ -53,10 +53,6 @@ class CONTENT_EXPORT BrowserProcessSubThread : public base::Thread {
// starting this BrowserProcessSubThread.
void AllowBlockingForTesting();
- // Creates and starts the IO thread. It should not be promoted to
- // BrowserThread::IO until BrowserMainLoop::CreateThreads().
- static std::unique_ptr<BrowserProcessSubThread> CreateIOThread();
-
protected:
void Init() override;
void Run(base::RunLoop* run_loop) override;
diff --git a/chromium/content/browser/browser_thread_browsertest.cc b/chromium/content/browser/browser_thread_browsertest.cc
index 34f5eb0e934..96fc0e0b5c4 100644
--- a/chromium/content/browser/browser_thread_browsertest.cc
+++ b/chromium/content/browser/browser_thread_browsertest.cc
@@ -2,13 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/run_loop.h"
#include "base/task/post_task.h"
#include "base/test/gtest_util.h"
#include "build/build_config.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/content_browser_test.h"
+#include "content/public/test/test_utils.h"
namespace content {
@@ -30,30 +36,4 @@ class BrowserThreadPostTaskBeforeInitBrowserTest : public ContentBrowserTest {
IN_PROC_BROWSER_TEST_F(BrowserThreadPostTaskBeforeInitBrowserTest,
ExpectFailures) {}
-class BrowserThreadPostTaskBeforeThreadCreationBrowserTest
- : public ContentBrowserTest {
- protected:
- void CreatedBrowserMainParts(BrowserMainParts* browser_main_parts) override {
- // This should fail because the IO thread hasn't been initialized yet.
- EXPECT_DCHECK_DEATH(base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
- base::DoNothing()));
-
- // Obtaining a TaskRunner should work, because the TaskExecutor was
- // registered already.
- auto task_runner = base::CreateTaskRunnerWithTraits({BrowserThread::IO});
- // But posting should still fail.
- EXPECT_DCHECK_DEATH(task_runner->PostTask(FROM_HERE, base::DoNothing()));
- }
-};
-
-// Flaky on Chrome OS and Linux. https://crbug.com/910834
-#if defined(OS_CHROMEOS) || defined(OS_LINUX)
-#define MAYBE_ExpectFailures DISABLED_ExpectFailures
-#else
-#define MAYBE_ExpectFailures ExpectFailures
-#endif
-
-IN_PROC_BROWSER_TEST_F(BrowserThreadPostTaskBeforeThreadCreationBrowserTest,
- MAYBE_ExpectFailures) {}
-
} // namespace content
diff --git a/chromium/content/browser/browser_thread_impl.cc b/chromium/content/browser/browser_thread_impl.cc
index 40fd3dcd741..500b4ebc1af 100644
--- a/chromium/content/browser/browser_thread_impl.cc
+++ b/chromium/content/browser/browser_thread_impl.cc
@@ -260,4 +260,15 @@ void BrowserThread::RunAllPendingTasksOnThreadForTesting(ID identifier) {
BrowserTaskExecutor::RunAllPendingTasksOnThreadForTesting(identifier);
}
+// static
+void BrowserThread::PostBestEffortTask(
+ const base::Location& from_here,
+ scoped_refptr<base::TaskRunner> task_runner,
+ base::OnceClosure task) {
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO, base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(base::IgnoreResult(&base::TaskRunner::PostTask),
+ std::move(task_runner), from_here, std::move(task)));
+}
+
} // namespace content
diff --git a/chromium/content/browser/browser_thread_unittest.cc b/chromium/content/browser/browser_thread_unittest.cc
index 7763d782514..49e1530eec4 100644
--- a/chromium/content/browser/browser_thread_unittest.cc
+++ b/chromium/content/browser/browser_thread_unittest.cc
@@ -2,23 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/public/browser/browser_thread.h"
+
#include <memory>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/location.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_pump.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner_helpers.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
#include "base/task/sequence_manager/sequence_manager_impl.h"
+#include "base/test/mock_callback.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/browser_process_sub_thread.h"
#include "content/browser/browser_thread_impl.h"
+#include "content/browser/scheduler/browser_io_task_environment.h"
#include "content/browser/scheduler/browser_task_executor.h"
#include "content/browser/scheduler/browser_ui_thread_scheduler.h"
#include "content/public/browser/browser_task_traits.h"
@@ -30,14 +34,30 @@ namespace content {
namespace {
+using ::testing::Invoke;
+
+using StrictMockTask =
+ testing::StrictMock<base::MockCallback<base::Callback<void()>>>;
+
class SequenceManagerTaskEnvironment : public base::Thread::TaskEnvironment {
public:
- SequenceManagerTaskEnvironment(
- std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager,
- scoped_refptr<base::SingleThreadTaskRunner> default_task_runner)
- : sequence_manager_(std::move(sequence_manager)),
- default_task_runner_(std::move(default_task_runner)) {
+ SequenceManagerTaskEnvironment() {
+ sequence_manager_ =
+ base::sequence_manager::internal::SequenceManagerImpl::CreateUnbound(
+ base::sequence_manager::SequenceManager::Settings());
+ auto browser_ui_thread_scheduler =
+ BrowserUIThreadScheduler::CreateForTesting(
+ sequence_manager_.get(), sequence_manager_->GetRealTimeDomain());
+
+ default_task_runner_ =
+ browser_ui_thread_scheduler->GetHandle().GetDefaultTaskRunner();
+
sequence_manager_->SetDefaultTaskRunner(default_task_runner_);
+
+ BrowserTaskExecutor::CreateForTesting(
+ std::move(browser_ui_thread_scheduler),
+ std::make_unique<BrowserIOTaskEnvironment>());
+ BrowserTaskExecutor::EnableAllQueues();
}
~SequenceManagerTaskEnvironment() override {
@@ -51,8 +71,7 @@ class SequenceManagerTaskEnvironment : public base::Thread::TaskEnvironment {
void BindToCurrentThread(base::TimerSlack timer_slack) override {
sequence_manager_->BindToMessagePump(
- base::MessageLoop::CreateMessagePumpForType(
- base::MessageLoop::TYPE_DEFAULT));
+ base::MessagePump::Create(base::MessagePump::Type::DEFAULT));
sequence_manager_->SetTimerSlack(timer_slack);
}
@@ -80,28 +99,11 @@ class BrowserThreadTest : public testing::Test {
protected:
void SetUp() override {
ui_thread_ = std::make_unique<BrowserProcessSubThread>(BrowserThread::UI);
- std::unique_ptr<base::sequence_manager::internal::SequenceManagerImpl>
- sequence_manager = base::sequence_manager::internal::
- SequenceManagerImpl::CreateUnbound(
- base::sequence_manager::SequenceManager::Settings());
- std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler =
- BrowserUIThreadScheduler::CreateForTesting(
- sequence_manager.get(), sequence_manager->GetRealTimeDomain());
-
base::Thread::Options ui_options;
- ui_options.task_environment = new SequenceManagerTaskEnvironment(
- std::move(sequence_manager),
- browser_ui_thread_scheduler->GetTaskRunnerForTesting(
- BrowserUIThreadScheduler::QueueType::kDefault));
-
- BrowserTaskExecutor::CreateWithBrowserUIThreadSchedulerForTesting(
- std::move(browser_ui_thread_scheduler));
+ ui_options.task_environment = new SequenceManagerTaskEnvironment();
ui_thread_->StartWithOptions(ui_options);
- io_thread_ = std::make_unique<BrowserProcessSubThread>(BrowserThread::IO);
- base::Thread::Options io_options;
- io_options.message_loop_type = base::MessageLoop::TYPE_IO;
- io_thread_->StartWithOptions(io_options);
+ io_thread_ = BrowserTaskExecutor::CreateIOThread();
ui_thread_->RegisterAsBrowserThread();
io_thread_->RegisterAsBrowserThread();
@@ -293,4 +295,68 @@ TEST_F(BrowserThreadTest, RunsTasksInCurrentSequencedDuringShutdown) {
EXPECT_TRUE(did_shutdown);
}
+class BrowserThreadWithCustomSchedulerTest : public testing::Test {
+ private:
+ class ScopedTaskEnvironmentWithCustomScheduler
+ : public base::test::ScopedTaskEnvironment {
+ public:
+ ScopedTaskEnvironmentWithCustomScheduler()
+ : base::test::ScopedTaskEnvironment(
+ SubclassCreatesDefaultTaskRunner{}) {
+ std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler =
+ BrowserUIThreadScheduler::CreateForTesting(sequence_manager(),
+ GetTimeDomain());
+ DeferredInitFromSubclass(
+ browser_ui_thread_scheduler->GetHandle().GetBrowserTaskRunner(
+ QueueType::kDefault));
+ BrowserTaskExecutor::CreateForTesting(
+ std::move(browser_ui_thread_scheduler),
+ std::make_unique<BrowserIOTaskEnvironment>());
+
+ ui_thread_ = BrowserTaskExecutor::CreateIOThread();
+ BrowserTaskExecutor::InitializeIOThread();
+ ui_thread_->RegisterAsBrowserThread();
+ }
+
+ ~ScopedTaskEnvironmentWithCustomScheduler() override {
+ ui_thread_.reset();
+ BrowserThreadImpl::ResetGlobalsForTesting(BrowserThread::IO);
+ BrowserTaskExecutor::ResetForTesting();
+ }
+
+ private:
+ std::unique_ptr<BrowserProcessSubThread> ui_thread_;
+ };
+
+ public:
+ using QueueType = BrowserTaskQueues::QueueType;
+
+ protected:
+ ScopedTaskEnvironmentWithCustomScheduler scoped_task_environment_;
+};
+
+TEST_F(BrowserThreadWithCustomSchedulerTest, PostBestEffortTask) {
+ StrictMockTask best_effort_task;
+ StrictMockTask regular_task;
+
+ auto task_runner = base::CreateTaskRunnerWithTraits(
+ {BrowserThread::UI, base::TaskPriority::HIGHEST});
+
+ task_runner->PostTask(FROM_HERE, regular_task.Get());
+ BrowserThread::PostBestEffortTask(FROM_HERE, task_runner,
+ best_effort_task.Get());
+
+ EXPECT_CALL(regular_task, Run);
+ scoped_task_environment_.RunUntilIdle();
+
+ testing::Mock::VerifyAndClearExpectations(&regular_task);
+
+ BrowserTaskExecutor::EnableAllQueues();
+ base::RunLoop run_loop;
+ EXPECT_CALL(best_effort_task, Run).WillOnce(Invoke([&]() {
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+}
+
} // namespace content
diff --git a/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.cc b/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.cc
index b06695ab36a..fd1a877a071 100644
--- a/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.cc
+++ b/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.cc
@@ -117,17 +117,17 @@ void BrowsingDataFilterBuilderImpl::AddRegisterableDomain(
domains_.insert(domain);
}
-bool BrowsingDataFilterBuilderImpl::IsEmptyBlacklist() const {
+bool BrowsingDataFilterBuilderImpl::IsEmptyBlacklist() {
return mode_ == Mode::BLACKLIST && origins_.empty() && domains_.empty();
}
base::RepeatingCallback<bool(const GURL&)>
-BrowsingDataFilterBuilderImpl::BuildGeneralFilter() const {
+BrowsingDataFilterBuilderImpl::BuildGeneralFilter() {
return base::BindRepeating(&MatchesURL, origins_, domains_, mode_);
}
network::mojom::ClearDataFilterPtr
-BrowsingDataFilterBuilderImpl::BuildNetworkServiceFilter() const {
+BrowsingDataFilterBuilderImpl::BuildNetworkServiceFilter() {
if (IsEmptyBlacklist())
return nullptr;
network::mojom::ClearDataFilterPtr filter =
@@ -143,7 +143,7 @@ BrowsingDataFilterBuilderImpl::BuildNetworkServiceFilter() const {
}
network::mojom::CookieDeletionFilterPtr
-BrowsingDataFilterBuilderImpl::BuildCookieDeletionFilter() const {
+BrowsingDataFilterBuilderImpl::BuildCookieDeletionFilter() {
DCHECK(origins_.empty())
<< "Origin-based deletion is not suitable for cookies. Please use "
"different scoping, such as RegistrableDomainFilterBuilder.";
@@ -163,7 +163,7 @@ BrowsingDataFilterBuilderImpl::BuildCookieDeletionFilter() const {
}
base::RepeatingCallback<bool(const std::string& site)>
-BrowsingDataFilterBuilderImpl::BuildPluginFilter() const {
+BrowsingDataFilterBuilderImpl::BuildPluginFilter() {
DCHECK(origins_.empty()) <<
"Origin-based deletion is not suitable for plugins. Please use "
"different scoping, such as RegistrableDomainFilterBuilder.";
@@ -171,13 +171,12 @@ BrowsingDataFilterBuilderImpl::BuildPluginFilter() const {
domains_, mode_);
}
-BrowsingDataFilterBuilderImpl::Mode
-BrowsingDataFilterBuilderImpl::GetMode() const {
+BrowsingDataFilterBuilderImpl::Mode BrowsingDataFilterBuilderImpl::GetMode() {
return mode_;
}
std::unique_ptr<BrowsingDataFilterBuilder>
-BrowsingDataFilterBuilderImpl::Copy() const {
+BrowsingDataFilterBuilderImpl::Copy() {
std::unique_ptr<BrowsingDataFilterBuilderImpl> copy =
std::make_unique<BrowsingDataFilterBuilderImpl>(mode_);
copy->origins_ = origins_;
@@ -186,7 +185,7 @@ BrowsingDataFilterBuilderImpl::Copy() const {
}
bool BrowsingDataFilterBuilderImpl::operator==(
- const BrowsingDataFilterBuilder& other) const {
+ const BrowsingDataFilterBuilder& other) {
// This is the only implementation of BrowsingDataFilterBuilder, so we can
// downcast |other|.
const BrowsingDataFilterBuilderImpl* other_impl =
diff --git a/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.h b/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.h
index a310963340d..6ce2caabca6 100644
--- a/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.h
+++ b/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.h
@@ -21,17 +21,15 @@ class CONTENT_EXPORT BrowsingDataFilterBuilderImpl
// BrowsingDataFilterBuilder implementation:
void AddOrigin(const url::Origin& origin) override;
void AddRegisterableDomain(const std::string& registrable_domain) override;
- bool IsEmptyBlacklist() const override;
- base::RepeatingCallback<bool(const GURL&)>
- BuildGeneralFilter() const override;
- network::mojom::ClearDataFilterPtr BuildNetworkServiceFilter() const override;
- network::mojom::CookieDeletionFilterPtr BuildCookieDeletionFilter()
- const override;
- base::RepeatingCallback<bool(const std::string& site)>
- BuildPluginFilter() const override;
- Mode GetMode() const override;
- std::unique_ptr<BrowsingDataFilterBuilder> Copy() const override;
- bool operator==(const BrowsingDataFilterBuilder& other) const override;
+ bool IsEmptyBlacklist() override;
+ base::RepeatingCallback<bool(const GURL&)> BuildGeneralFilter() override;
+ network::mojom::ClearDataFilterPtr BuildNetworkServiceFilter() override;
+ network::mojom::CookieDeletionFilterPtr BuildCookieDeletionFilter() override;
+ base::RepeatingCallback<bool(const std::string& site)> BuildPluginFilter()
+ override;
+ Mode GetMode() override;
+ std::unique_ptr<BrowsingDataFilterBuilder> Copy() override;
+ bool operator==(const BrowsingDataFilterBuilder& other) override;
private:
Mode mode_;
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 ef003102f1c..636748dea39 100644
--- a/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
+++ b/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
@@ -246,7 +246,7 @@ void BrowsingDataRemoverImpl::RunNextTask() {
kSlowTaskTimeout);
RemoveImpl(removal_task.delete_begin, removal_task.delete_end,
- removal_task.remove_mask, *removal_task.filter_builder,
+ removal_task.remove_mask, removal_task.filter_builder.get(),
removal_task.origin_type_mask);
}
@@ -254,7 +254,7 @@ void BrowsingDataRemoverImpl::RemoveImpl(
const base::Time& delete_begin,
const base::Time& delete_end,
int remove_mask,
- const BrowsingDataFilterBuilder& filter_builder,
+ BrowsingDataFilterBuilder* filter_builder,
int origin_type_mask) {
// =============== README before adding more storage backends ===============
//
@@ -297,12 +297,12 @@ void BrowsingDataRemoverImpl::RemoveImpl(
//////////////////////////////////////////////////////////////////////////////
// INITIALIZATION
base::RepeatingCallback<bool(const GURL& url)> filter =
- filter_builder.BuildGeneralFilter();
+ filter_builder->BuildGeneralFilter();
// Some backends support a filter that |is_null()| to make complete deletion
// more efficient.
base::RepeatingCallback<bool(const GURL&)> nullable_filter =
- filter_builder.IsEmptyBlacklist()
+ filter_builder->IsEmptyBlacklist()
? base::RepeatingCallback<bool(const GURL&)>()
: filter;
@@ -318,27 +318,6 @@ void BrowsingDataRemoverImpl::RemoveImpl(
}
//////////////////////////////////////////////////////////////////////////////
- // DATA_TYPE_CHANNEL_IDS
- // Channel IDs are not separated for protected and unprotected web
- // origins. We check the origin_type_mask_ to prevent unintended deletion.
- if (remove_mask & DATA_TYPE_CHANNEL_IDS &&
- !(remove_mask & DATA_TYPE_AVOID_CLOSING_CONNECTIONS) &&
- origin_type_mask_ & ORIGIN_TYPE_UNPROTECTED_WEB) {
- base::RecordAction(UserMetricsAction("ClearBrowsingData_ChannelIDs"));
-
- network::mojom::ClearDataFilterPtr service_filter =
- filter_builder.BuildNetworkServiceFilter();
- DCHECK(!service_filter || service_filter->origins.empty())
- << "Origin-based deletion is not suitable for channel IDs.";
-
- BrowserContext::GetDefaultStoragePartition(browser_context_)
- ->GetNetworkContext()
- ->ClearChannelIds(
- delete_begin, delete_end, std::move(service_filter),
- CreateTaskCompletionClosureForMojo(TracingDataType::kChannelIds));
- }
-
- //////////////////////////////////////////////////////////////////////////////
// STORAGE PARTITION DATA
uint32_t storage_partition_remove_mask = 0;
@@ -414,10 +393,10 @@ void BrowsingDataRemoverImpl::RemoveImpl(
// If cookies are supposed to be conditionally deleted from the storage
// partition, create the deletion info object.
network::mojom::CookieDeletionFilterPtr deletion_filter;
- if (!filter_builder.IsEmptyBlacklist() &&
+ if (!filter_builder->IsEmptyBlacklist() &&
(storage_partition_remove_mask &
StoragePartition::REMOVE_DATA_MASK_COOKIES)) {
- deletion_filter = filter_builder.BuildCookieDeletionFilter();
+ deletion_filter = filter_builder->BuildCookieDeletionFilter();
} else {
deletion_filter = network::mojom::CookieDeletionFilter::New();
}
@@ -427,7 +406,7 @@ void BrowsingDataRemoverImpl::RemoveImpl(
embedder_matcher = embedder_delegate_->GetOriginTypeMatcher();
bool perform_storage_cleanup =
delete_begin_.is_null() && delete_end_.is_max() &&
- filter_builder.GetMode() == BrowsingDataFilterBuilder::BLACKLIST;
+ filter_builder->GetMode() == BrowsingDataFilterBuilder::BLACKLIST;
storage_partition->ClearData(
storage_partition_remove_mask, quota_storage_remove_mask,
@@ -454,7 +433,7 @@ void BrowsingDataRemoverImpl::RemoveImpl(
// when enabled. Note that we've deprecated the concept of a media cache,
// and are now using a single cache for both purposes.
network_context->ClearHttpCache(
- delete_begin, delete_end, filter_builder.BuildNetworkServiceFilter(),
+ delete_begin, delete_end, filter_builder->BuildNetworkServiceFilter(),
CreateTaskCompletionClosureForMojo(TracingDataType::kHttpCache));
} else {
storage_partition->ClearHttpAndMediaCaches(
@@ -486,10 +465,10 @@ void BrowsingDataRemoverImpl::RemoveImpl(
BrowserContext::GetDefaultStoragePartition(browser_context_)
->GetNetworkContext();
network_context->ClearReportingCacheClients(
- filter_builder.BuildNetworkServiceFilter(),
+ filter_builder->BuildNetworkServiceFilter(),
CreateTaskCompletionClosureForMojo(TracingDataType::kReportingCache));
network_context->ClearNetworkErrorLogging(
- filter_builder.BuildNetworkServiceFilter(),
+ filter_builder->BuildNetworkServiceFilter(),
CreateTaskCompletionClosureForMojo(
TracingDataType::kNetworkErrorLogging));
}
diff --git a/chromium/content/browser/browsing_data/browsing_data_remover_impl.h b/chromium/content/browser/browsing_data/browsing_data_remover_impl.h
index fbbd8dbc02c..69d02065d75 100644
--- a/chromium/content/browser/browsing_data/browsing_data_remover_impl.h
+++ b/chromium/content/browser/browsing_data/browsing_data_remover_impl.h
@@ -157,7 +157,7 @@ class CONTENT_EXPORT BrowsingDataRemoverImpl
void RemoveImpl(const base::Time& delete_begin,
const base::Time& delete_end,
int remove_mask,
- const BrowsingDataFilterBuilder& filter_builder,
+ BrowsingDataFilterBuilder* filter_builder,
int origin_type_mask);
// Notifies observers and transitions to the idle state.
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 799bb79fd03..d2d7504a8d4 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
@@ -48,13 +48,12 @@
#include "net/cookies/cookie_store.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
-#include "net/ssl/channel_id_service.h"
-#include "net/ssl/channel_id_store.h"
#include "net/ssl/ssl_client_cert_type.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/network/cookie_manager.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/test/test_network_context.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -62,6 +61,7 @@
#include "url/origin.h"
#if BUILDFLAG(ENABLE_REPORTING)
+#include "net/network_error_logging/mock_persistent_nel_store.h"
#include "net/network_error_logging/network_error_logging_service.h"
#include "net/reporting/reporting_cache.h"
#include "net/reporting/reporting_report.h"
@@ -96,7 +96,7 @@ const char kTestOrigin3[] = "http://host3.com:1/";
const char kTestRegisterableDomain3[] = "host3.com";
const char kTestOrigin4[] = "https://host3.com:1/";
const char kTestOriginExt[] = "chrome-extension://abcdefghijklmnopqrstuvwxyz/";
-const char kTestOriginDevTools[] = "chrome-devtools://abcdefghijklmnopqrstuvw/";
+const char kTestOriginDevTools[] = "devtools://abcdefghijklmnopqrstuvw/";
// For HTTP auth.
const char kTestRealm[] = "TestRealm";
@@ -306,68 +306,6 @@ bool FilterMatchesCookie(const CookieDeletionFilterPtr& filter,
// Testers -------------------------------------------------------------------
-class RemoveChannelIDTester : public net::SSLConfigService::Observer {
- public:
- explicit RemoveChannelIDTester(BrowserContext* browser_context) {
- net::URLRequestContext* url_request_context =
- BrowserContext::GetDefaultStoragePartition(browser_context)
- ->GetURLRequestContext()
- ->GetURLRequestContext();
- channel_id_service_ = url_request_context->channel_id_service();
- ssl_config_service_ = url_request_context->ssl_config_service();
- ssl_config_service_->AddObserver(this);
- }
-
- ~RemoveChannelIDTester() override {
- ssl_config_service_->RemoveObserver(this);
- }
-
- int ChannelIDCount() { return channel_id_service_->channel_id_count(); }
-
- // Add a server bound cert for |server| with specific creation and expiry
- // times. The cert and key data will be filled with dummy values.
- void AddChannelIDWithTimes(const std::string& server_identifier,
- base::Time creation_time) {
- GetChannelIDStore()->SetChannelID(
- std::make_unique<net::ChannelIDStore::ChannelID>(
- server_identifier, creation_time, crypto::ECPrivateKey::Create()));
- }
-
- // Add a server bound cert for |server|, with the current time as the
- // creation time. The cert and key data will be filled with dummy values.
- void AddChannelID(const std::string& server_identifier) {
- base::Time now = base::Time::Now();
- AddChannelIDWithTimes(server_identifier, now);
- }
-
- void GetChannelIDList(net::ChannelIDStore::ChannelIDList* channel_ids) {
- GetChannelIDStore()->GetAllChannelIDs(base::BindOnce(
- &RemoveChannelIDTester::GetAllChannelIDsCallback, channel_ids));
- }
-
- net::ChannelIDStore* GetChannelIDStore() {
- return channel_id_service_->GetChannelIDStore();
- }
-
- int ssl_config_changed_count() const { return ssl_config_changed_count_; }
-
- // net::SSLConfigService::Observer implementation:
- void OnSSLConfigChanged() override { ssl_config_changed_count_++; }
-
- private:
- static void GetAllChannelIDsCallback(
- net::ChannelIDStore::ChannelIDList* dest,
- const net::ChannelIDStore::ChannelIDList& result) {
- *dest = result;
- }
-
- net::ChannelIDService* channel_id_service_;
- net::SSLConfigService* ssl_config_service_;
- int ssl_config_changed_count_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(RemoveChannelIDTester);
-};
-
class RemoveDownloadsTester {
public:
explicit RemoveDownloadsTester(BrowserContext* browser_context)
@@ -577,6 +515,11 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveCookiesDomainBlacklist) {
// Test that removing cookies clears HTTP auth data.
TEST_F(BrowsingDataRemoverImplTest, ClearHttpAuthCache_RemoveCookies) {
+ // TODO: rewrite this test to work with Network Service objects.
+ // https://crbug.com/967698
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
net::HttpNetworkSession* http_session =
BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
->GetURLRequestContext()
@@ -605,6 +548,11 @@ TEST_F(BrowsingDataRemoverImplTest, ClearHttpAuthCache_RemoveCookies) {
// closing connections.
TEST_F(BrowsingDataRemoverImplTest,
ClearHttpAuthCache_AvoidClosingConnections) {
+ // TODO: rewrite this test to work with Network Service objects.
+ // https://crbug.com/967698
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
net::HttpNetworkSession* http_session =
BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
->GetURLRequestContext()
@@ -634,93 +582,6 @@ TEST_F(BrowsingDataRemoverImplTest,
net::HttpAuth::AUTH_SCHEME_BASIC));
}
-TEST_F(BrowsingDataRemoverImplTest, RemoveChannelIDForever) {
- RemoveChannelIDTester tester(GetBrowserContext());
-
- tester.AddChannelID(kTestOrigin1);
- EXPECT_EQ(0, tester.ssl_config_changed_count());
- EXPECT_EQ(1, tester.ChannelIDCount());
-
- BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
- BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS,
- false);
-
- EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS, GetRemovalMask());
- EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
- GetOriginTypeMask());
- EXPECT_EQ(1, tester.ssl_config_changed_count());
- EXPECT_EQ(0, tester.ChannelIDCount());
-}
-
-TEST_F(BrowsingDataRemoverImplTest, RemoveChannelIDLastHour) {
- RemoveChannelIDTester tester(GetBrowserContext());
-
- base::Time now = base::Time::Now();
- tester.AddChannelID(kTestOrigin1);
- tester.AddChannelIDWithTimes(kTestOrigin2,
- now - base::TimeDelta::FromHours(2));
- EXPECT_EQ(0, tester.ssl_config_changed_count());
- EXPECT_EQ(2, tester.ChannelIDCount());
-
- BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
- BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS,
- false);
-
- EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS, GetRemovalMask());
- EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
- GetOriginTypeMask());
- EXPECT_EQ(1, tester.ssl_config_changed_count());
- ASSERT_EQ(1, tester.ChannelIDCount());
- net::ChannelIDStore::ChannelIDList channel_ids;
- tester.GetChannelIDList(&channel_ids);
- ASSERT_EQ(1U, channel_ids.size());
- EXPECT_EQ(kTestOrigin2, channel_ids.front().server_identifier());
-}
-
-TEST_F(BrowsingDataRemoverImplTest, RemoveChannelIDsForServerIdentifiers) {
- RemoveChannelIDTester tester(GetBrowserContext());
-
- tester.AddChannelID(kTestRegisterableDomain1);
- tester.AddChannelID(kTestRegisterableDomain3);
- EXPECT_EQ(2, tester.ChannelIDCount());
-
- std::unique_ptr<BrowsingDataFilterBuilder> filter_builder(
- BrowsingDataFilterBuilder::Create(BrowsingDataFilterBuilder::WHITELIST));
- filter_builder->AddRegisterableDomain(kTestRegisterableDomain1);
-
- BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
- BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS,
- std::move(filter_builder));
-
- EXPECT_EQ(1, tester.ChannelIDCount());
- net::ChannelIDStore::ChannelIDList channel_ids;
- tester.GetChannelIDList(&channel_ids);
- EXPECT_EQ(kTestRegisterableDomain3, channel_ids.front().server_identifier());
-}
-
-TEST_F(BrowsingDataRemoverImplTest, RemoveChannelIDsAvoidClosingConnections) {
- RemoveChannelIDTester tester(GetBrowserContext());
-
- tester.AddChannelID(kTestOrigin1);
- EXPECT_EQ(0, tester.ssl_config_changed_count());
- EXPECT_EQ(1, tester.ChannelIDCount());
-
- int remove_mask = BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS |
- BrowsingDataRemover::DATA_TYPE_AVOID_CLOSING_CONNECTIONS;
-
- BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(), remove_mask,
- false);
-
- EXPECT_EQ(remove_mask, GetRemovalMask());
- EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
- GetOriginTypeMask());
-
- // No deletion took place because the AVOID_CLOSING_CONNECTIONS flag
- // was specified.
- EXPECT_EQ(0, tester.ssl_config_changed_count());
- EXPECT_EQ(1, tester.ChannelIDCount());
-}
-
TEST_F(BrowsingDataRemoverImplTest, RemoveUnprotectedLocalStorageForever) {
MockSpecialStoragePolicy* policy = CreateMockPolicy();
// Protect kOrigin1.
@@ -1425,6 +1286,11 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveCodeCache) {
#if BUILDFLAG(ENABLE_REPORTING)
TEST_F(BrowsingDataRemoverImplTest, RemoveReportingCache) {
+ // TODO: rewrite this test to work with Network Service objects.
+ // https://crbug.com/967698
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
auto reporting_context = std::make_unique<net::TestReportingContext>(
base::DefaultClock::GetInstance(), base::DefaultTickClock::GetInstance(),
net::ReportingPolicy());
@@ -1438,22 +1304,25 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveReportingCache) {
->set_reporting_service(reporting_service.get());
GURL domain("https://google.com");
- reporting_cache->SetClient(url::Origin::Create(domain), domain,
- net::ReportingClient::Subdomains::EXCLUDE, "group",
- base::TimeTicks::Max(), 0, 1);
+ reporting_cache->SetEndpointForTesting(url::Origin::Create(domain), "group",
+ domain, net::OriginSubdomains::DEFAULT,
+ base::Time::Max(), 1 /* priority */,
+ 1 /* weight */);
- std::vector<const net::ReportingClient*> clients;
- reporting_cache->GetClients(&clients);
- ASSERT_EQ(1u, clients.size());
+ ASSERT_EQ(1u, reporting_cache->GetEndpointCount());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_COOKIES, false);
- reporting_cache->GetClients(&clients);
- EXPECT_TRUE(clients.empty());
+ EXPECT_EQ(0u, reporting_cache->GetEndpointCount());
}
TEST_F(BrowsingDataRemoverImplTest, RemoveReportingCache_SpecificOrigins) {
+ // TODO: rewrite this test to work with Network Service objects.
+ // https://crbug.com/967698
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
auto reporting_context = std::make_unique<net::TestReportingContext>(
base::DefaultClock::GetInstance(), base::DefaultTickClock::GetInstance(),
net::ReportingPolicy());
@@ -1467,25 +1336,27 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveReportingCache_SpecificOrigins) {
->set_reporting_service(reporting_service.get());
GURL domain1("https://google.com");
- reporting_cache->SetClient(url::Origin::Create(domain1), domain1,
- net::ReportingClient::Subdomains::EXCLUDE, "group",
- base::TimeTicks::Max(), 0, 1);
+ reporting_cache->SetEndpointForTesting(
+ url::Origin::Create(domain1), "group", domain1,
+ net::OriginSubdomains::DEFAULT, base::Time::Max(), 1 /* priority */,
+ 1 /* weight */);
GURL domain2("https://host2.com");
- reporting_cache->SetClient(url::Origin::Create(domain2), domain2,
- net::ReportingClient::Subdomains::EXCLUDE, "group",
- base::TimeTicks::Max(), 0, 1);
+ reporting_cache->SetEndpointForTesting(
+ url::Origin::Create(domain2), "group", domain2,
+ net::OriginSubdomains::DEFAULT, base::Time::Max(), 1 /* priority */,
+ 1 /* weight */);
GURL domain3("https://host3.com");
- reporting_cache->SetClient(url::Origin::Create(domain3), domain3,
- net::ReportingClient::Subdomains::EXCLUDE, "group",
- base::TimeTicks::Max(), 0, 1);
+ reporting_cache->SetEndpointForTesting(
+ url::Origin::Create(domain3), "group", domain3,
+ net::OriginSubdomains::DEFAULT, base::Time::Max(), 1 /* priority */,
+ 1 /* weight */);
GURL domain4("https://host4.com");
- reporting_cache->SetClient(url::Origin::Create(domain4), domain4,
- net::ReportingClient::Subdomains::EXCLUDE, "group",
- base::TimeTicks::Max(), 0, 1);
+ reporting_cache->SetEndpointForTesting(
+ url::Origin::Create(domain4), "group", domain4,
+ net::OriginSubdomains::EXCLUDE, base::Time::Max(), 1 /* priority */,
+ 1 /* weight */);
- std::vector<const net::ReportingClient*> clients;
- reporting_cache->GetClients(&clients);
- ASSERT_EQ(4u, clients.size());
+ ASSERT_EQ(4u, reporting_cache->GetEndpointCount());
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder(
BrowsingDataFilterBuilder::Create(BrowsingDataFilterBuilder::WHITELIST));
@@ -1495,16 +1366,18 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveReportingCache_SpecificOrigins) {
BrowsingDataRemover::DATA_TYPE_COOKIES,
std::move(filter_builder));
- reporting_cache->GetClients(&clients);
- EXPECT_EQ(2u, clients.size());
- std::vector<GURL> origins;
- for (const net::ReportingClient* client : clients) {
- origins.push_back(client->endpoint);
- }
- EXPECT_THAT(origins, UnorderedElementsAre(domain2, domain4));
+ EXPECT_EQ(2u, reporting_cache->GetEndpointCount());
+ std::vector<url::Origin> origins = reporting_cache->GetAllOrigins();
+ EXPECT_THAT(origins, UnorderedElementsAre(url::Origin::Create(domain2),
+ url::Origin::Create(domain4)));
}
TEST_F(BrowsingDataRemoverImplTest, RemoveReportingCache_NoService) {
+ // TODO: rewrite this test to work with Network Service objects.
+ // https://crbug.com/967698
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
ASSERT_FALSE(BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
->GetURLRequestContext()
->GetURLRequestContext()
@@ -1514,9 +1387,54 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveReportingCache_NoService) {
BrowsingDataRemover::DATA_TYPE_COOKIES, false);
}
-// TODO(chlily): Use a PersistentNELStore and test that entries are removed from
-// it.
TEST_F(BrowsingDataRemoverImplTest, RemoveNetworkErrorLogging) {
+ // TODO: rewrite this test to work with Network Service objects.
+ // https://crbug.com/967698
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
+ auto store = std::make_unique<net::MockPersistentNelStore>();
+ std::unique_ptr<net::NetworkErrorLoggingService> logging_service =
+ net::NetworkErrorLoggingService::Create(store.get());
+ BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
+ ->GetURLRequestContext()
+ ->GetURLRequestContext()
+ ->set_network_error_logging_service(logging_service.get());
+
+ GURL domain("https://google.com");
+ logging_service->OnHeader(url::Origin::Create(domain),
+ net::IPAddress(192, 168, 0, 1),
+ "{\"report_to\":\"group\",\"max_age\":86400}");
+ store->FinishLoading(true /* load_success */);
+ store->Flush();
+
+ ASSERT_EQ(1u, logging_service->GetPolicyOriginsForTesting().size());
+ ASSERT_EQ(1, store->StoredPoliciesCount());
+
+ BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
+ BrowsingDataRemover::DATA_TYPE_COOKIES, false);
+
+ EXPECT_TRUE(logging_service->GetPolicyOriginsForTesting().empty());
+ EXPECT_EQ(0, store->StoredPoliciesCount());
+
+ // Check that the persistent store was told to delete the policy.
+ net::NetworkErrorLoggingService::NelPolicy deleted_policy;
+ deleted_policy.origin = url::Origin::Create(domain);
+ EXPECT_THAT(store->GetAllCommands(),
+ testing::Contains(net::MockPersistentNelStore::Command(
+ net::MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY,
+ deleted_policy)));
+}
+
+// Test that removal of in-memory browsing data works without a persistent
+// store.
+TEST_F(BrowsingDataRemoverImplTest,
+ RemoveNetworkErrorLogging_NoPersistentStore) {
+ // TODO: rewrite this test to work with Network Service objects.
+ // https://crbug.com/967698
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
std::unique_ptr<net::NetworkErrorLoggingService> logging_service =
net::NetworkErrorLoggingService::Create(nullptr /* store */);
BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
@@ -1537,11 +1455,15 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveNetworkErrorLogging) {
EXPECT_TRUE(logging_service->GetPolicyOriginsForTesting().empty());
}
-// TODO(chlily): Use a PersistentNELStore and test that entries are removed from
-// it.
TEST_F(BrowsingDataRemoverImplTest, RemoveNetworkErrorLogging_SpecificOrigins) {
+ // TODO: rewrite this test to work with Network Service objects.
+ // https://crbug.com/967698
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
+ auto store = std::make_unique<net::MockPersistentNelStore>();
std::unique_ptr<net::NetworkErrorLoggingService> logging_service =
- net::NetworkErrorLoggingService::Create(nullptr /* store */);
+ net::NetworkErrorLoggingService::Create(store.get());
BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
->GetURLRequestContext()
->GetURLRequestContext()
@@ -1563,8 +1485,11 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveNetworkErrorLogging_SpecificOrigins) {
logging_service->OnHeader(url::Origin::Create(domain4),
net::IPAddress(192, 168, 0, 1),
"{\"report_to\":\"group\",\"max_age\":86400}");
+ store->FinishLoading(true /* load_success */);
+ store->Flush();
ASSERT_EQ(4u, logging_service->GetPolicyOriginsForTesting().size());
+ ASSERT_EQ(4, store->StoredPoliciesCount());
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder(
BrowsingDataFilterBuilder::Create(BrowsingDataFilterBuilder::WHITELIST));
@@ -1580,9 +1505,29 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveNetworkErrorLogging_SpecificOrigins) {
EXPECT_THAT(policy_origins,
UnorderedElementsAre(url::Origin::Create(domain2),
url::Origin::Create(domain4)));
+ EXPECT_EQ(2, store->StoredPoliciesCount());
+
+ // Check that the persistent store was told to delete the policies.
+ net::NetworkErrorLoggingService::NelPolicy deleted_policy1;
+ deleted_policy1.origin = url::Origin::Create(domain1);
+ net::NetworkErrorLoggingService::NelPolicy deleted_policy2;
+ deleted_policy2.origin = url::Origin::Create(domain3);
+ EXPECT_THAT(store->GetAllCommands(),
+ testing::Contains(net::MockPersistentNelStore::Command(
+ net::MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY,
+ deleted_policy1)));
+ EXPECT_THAT(store->GetAllCommands(),
+ testing::Contains(net::MockPersistentNelStore::Command(
+ net::MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY,
+ deleted_policy2)));
}
TEST_F(BrowsingDataRemoverImplTest, RemoveNetworkErrorLogging_NoService) {
+ // TODO: rewrite this test to work with Network Service objects.
+ // https://crbug.com/967698
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
ASSERT_FALSE(BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
->GetURLRequestContext()
->GetURLRequestContext()
@@ -1679,11 +1624,6 @@ TEST_F(BrowsingDataRemoverImplTest, MultipleTasks) {
BrowsingDataRemover::DATA_TYPE_WEB_SQL,
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
std::move(filter_builder_1), observer.target_b());
- tasks.emplace_back(base::Time::UnixEpoch(), base::Time::Now(),
- BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS,
- BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
- BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
- std::move(filter_builder_2), nullptr);
for (BrowsingDataRemoverImpl::RemovalTask& task : tasks) {
// All tasks can be directly translated to a RemoveInternal() call. Since
diff --git a/chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc b/chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
index 6db75d543ad..c9b296dc4b7 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
+++ b/chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
@@ -13,7 +13,10 @@
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/lock.h"
#include "base/task/post_task.h"
+#include "base/test/bind_test_util.h"
+#include "base/thread_annotations.h"
#include "build/build_config.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "content/browser/browsing_data/browsing_data_filter_builder_impl.h"
@@ -104,7 +107,7 @@ class TestBrowsingDataRemoverDelegate : public MockBrowsingDataRemoverDelegate {
BrowsingDataFilterBuilder::WHITELIST);
filter_builder.AddRegisterableDomain(origin.host());
ExpectCall(base::Time(), base::Time::Max(), data_type_mask,
- kOriginTypeMask, std::move(filter_builder));
+ kOriginTypeMask, &filter_builder);
}
if (storage || cache) {
int data_type_mask =
@@ -115,7 +118,7 @@ class TestBrowsingDataRemoverDelegate : public MockBrowsingDataRemoverDelegate {
BrowsingDataFilterBuilder::WHITELIST);
filter_builder.AddOrigin(origin);
ExpectCall(base::Time(), base::Time::Max(), data_type_mask,
- kOriginTypeMask, std::move(filter_builder));
+ kOriginTypeMask, &filter_builder);
}
}
@@ -350,6 +353,7 @@ class ClearSiteDataHandlerBrowserTest : public ContentBrowserTest {
// Set a Clear-Site-Data header that |HandleRequest| will use for every
// following request.
void SetClearSiteDataHeader(const std::string& header) {
+ base::AutoLock lock(clear_site_data_header_lock_);
clear_site_data_header_ = header;
}
@@ -389,8 +393,11 @@ class ClearSiteDataHandlerBrowserTest : public ContentBrowserTest {
std::unique_ptr<net::test_server::BasicHttpResponse> response(
new net::test_server::BasicHttpResponse());
- if (!clear_site_data_header_.empty())
- response->AddCustomHeader("Clear-Site-Data", clear_site_data_header_);
+ {
+ base::AutoLock lock(clear_site_data_header_lock_);
+ if (!clear_site_data_header_.empty())
+ response->AddCustomHeader("Clear-Site-Data", clear_site_data_header_);
+ }
std::string value;
if (net::GetValueForKeyInQuery(request.GetURL(), "header", &value))
@@ -490,7 +497,8 @@ class ClearSiteDataHandlerBrowserTest : public ContentBrowserTest {
bool is_network_service_enabled_ = false;
// If this is set, |HandleRequest| will always respond with Clear-Site-Data.
- std::string clear_site_data_header_;
+ base::Lock clear_site_data_header_lock_;
+ std::string clear_site_data_header_ GUARDED_BY(clear_site_data_header_lock_);
// Only used when |is_network_service_enabled_| is false.
std::unique_ptr<CacheTestUtil> cache_test_util_ = nullptr;
@@ -1007,18 +1015,23 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest,
// Update the service worker and send C-S-D during update.
delegate()->ExpectClearSiteDataCall(url::Origin::Create(url), false, true,
false);
+
+ base::RunLoop loop;
+ auto* remover = BrowserContext::GetBrowsingDataRemover(browser_context());
+ remover->SetWouldCompleteCallbackForTesting(
+ base::BindLambdaForTesting([&](const base::RepeatingClosure& callback) {
+ callback.Run();
+ loop.Quit();
+ }));
+
SetClearSiteDataHeader("\"storage\"");
// Expect the update to fail and the service worker to be removed.
EXPECT_FALSE(RunScriptAndGetBool("updateServiceWorker()"));
delegate()->VerifyAndClearExpectations();
- // The service worker should be gone but a few tests are flaky and fail
- // because it hasn't been removed. To find out if this is just a
- // timing issue, add some delay if the first call returns true.
- // TODO(crbug.com/912313): Check if this worked and find out why.
- if (RunScriptAndGetBool("hasServiceWorker()")) {
- LOG(ERROR) << "There was a service worker, checking again in a second";
- EXPECT_FALSE(RunScriptAndGetBool("setTimeout(hasServiceWorker, 1000)"));
- }
+ loop.Run();
+
+ // Notify crbug.com/912313 if the test fails here again.
+ EXPECT_FALSE(RunScriptAndGetBool("hasServiceWorker()"));
}
} // namespace content
diff --git a/chromium/content/browser/browsing_data/clear_site_data_throttle.cc b/chromium/content/browser/browsing_data/clear_site_data_throttle.cc
index 87784c1eb67..2ab93d457b6 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_throttle.cc
+++ b/chromium/content/browser/browsing_data/clear_site_data_throttle.cc
@@ -183,7 +183,7 @@ ClearSiteDataThrottle::~ClearSiteDataThrottle() {
OutputConsoleMessages();
}
-const char* ClearSiteDataThrottle::GetNameForLogging() const {
+const char* ClearSiteDataThrottle::GetNameForLogging() {
return kNameForLogging2;
}
diff --git a/chromium/content/browser/browsing_data/clear_site_data_throttle.h b/chromium/content/browser/browsing_data/clear_site_data_throttle.h
index 45bd0231dcc..2238a695ec5 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_throttle.h
+++ b/chromium/content/browser/browsing_data/clear_site_data_throttle.h
@@ -89,7 +89,7 @@ class CONTENT_EXPORT ClearSiteDataThrottle : public ResourceThrottle {
~ClearSiteDataThrottle() override;
// ResourceThrottle implementation:
- const char* GetNameForLogging() const override;
+ const char* GetNameForLogging() override;
void WillRedirectRequest(const net::RedirectInfo& redirect_info,
bool* defer) override;
void WillProcessResponse(bool* defer) override;
diff --git a/chromium/content/browser/browsing_data/clear_site_data_throttle_unittest.cc b/chromium/content/browser/browsing_data/clear_site_data_throttle_unittest.cc
index 7be862724f0..a2eaa62a10f 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_throttle_unittest.cc
+++ b/chromium/content/browser/browsing_data/clear_site_data_throttle_unittest.cc
@@ -67,8 +67,8 @@ class TestThrottle : public ClearSiteDataThrottle {
void SetResponseHeaders(const std::string& headers) {
std::string headers_with_status_code = "HTTP/1.1 200\n" + headers;
- headers_ = new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
- headers_with_status_code.c_str(), headers_with_status_code.size()));
+ headers_ = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(headers_with_status_code));
}
MOCK_METHOD4(ClearSiteData,
diff --git a/chromium/content/browser/browsing_instance.cc b/chromium/content/browser/browsing_instance.cc
index ab8097fe3a8..88e2bfabe6c 100644
--- a/chromium/content/browser/browsing_instance.cc
+++ b/chromium/content/browser/browsing_instance.cc
@@ -17,10 +17,6 @@
namespace content {
-namespace {
-const char* const kDefaultInstanceSiteURL = "http://unisolated.invalid";
-} // namespace
-
// Start the BrowsingInstance ID counter from 1 to avoid a conflict with the
// invalid BrowsingInstanceId value, which is 0 in its underlying IdType32.
int BrowsingInstance::next_browsing_instance_id_ = 1;
@@ -60,9 +56,7 @@ bool BrowsingInstance::IsDefaultSiteInstance(
}
bool BrowsingInstance::HasSiteInstance(const GURL& url) {
- std::string site = SiteInstanceImpl::GetSiteForURL(isolation_context_, url)
- .possibly_invalid_spec();
-
+ std::string site = GetSiteForURL(url).possibly_invalid_spec();
return site_instance_map_.find(site) != site_instance_map_.end();
}
@@ -98,8 +92,7 @@ void BrowsingInstance::GetSiteAndLockForURL(const GURL& url,
return;
}
- *site_url = SiteInstanceImpl::GetSiteForURL(
- isolation_context_, url, true /* should_use_effective_urls */);
+ *site_url = GetSiteForURL(url);
*lock_url =
SiteInstanceImpl::DetermineProcessLockURL(isolation_context_, url);
}
@@ -107,9 +100,7 @@ void BrowsingInstance::GetSiteAndLockForURL(const GURL& url,
scoped_refptr<SiteInstanceImpl> BrowsingInstance::GetSiteInstanceForURLHelper(
const GURL& url,
bool allow_default_instance) {
- std::string site = SiteInstanceImpl::GetSiteForURL(isolation_context_, url)
- .possibly_invalid_spec();
-
+ std::string site = GetSiteForURL(url).possibly_invalid_spec();
auto i = site_instance_map_.find(site);
if (i != site_instance_map_.end())
return i->second;
@@ -119,8 +110,13 @@ scoped_refptr<SiteInstanceImpl> BrowsingInstance::GetSiteInstanceForURLHelper(
// have multiple unisolated sites share a process. We don't use the default
// instance when kProcessSharingWithStrictSiteInstances is enabled because in
// that case we want each site to have their own SiteInstance object and logic
- // elsewhere ensures that those SiteInstances share a process.
- if (allow_default_instance &&
+ // elsewhere ensures that those SiteInstances share a process. We also don't
+ // use default SiteInstances when SiteInstance doesn't assign a site URL for
+ // |url|, since in that case the SiteInstance should remain unused, and a
+ // subsequent navigation should always be able to reuse it, whether or not
+ // it's to a site requiring a dedicated process or to a site that will use
+ // the default SiteInstance.
+ if (allow_default_instance && SiteInstanceImpl::ShouldAssignSiteForURL(url) &&
!base::FeatureList::IsEnabled(
features::kProcessSharingWithStrictSiteInstances) &&
!SiteInstanceImpl::DoesSiteRequireDedicatedProcess(isolation_context_,
@@ -139,7 +135,7 @@ scoped_refptr<SiteInstanceImpl> BrowsingInstance::GetSiteInstanceForURLHelper(
// calls RegisterSiteInstance().
default_site_instance_ = site_instance.get();
- site_instance->SetSite(GURL(kDefaultInstanceSiteURL));
+ site_instance->SetSite(SiteInstanceImpl::GetDefaultSiteURL());
}
return site_instance;
}
@@ -206,4 +202,8 @@ BrowsingInstance::~BrowsingInstance() {
default_process_->RemoveObserver(this);
}
+GURL BrowsingInstance::GetSiteForURL(const GURL& url) const {
+ return SiteInstanceImpl::GetSiteForURL(isolation_context_, url);
+}
+
} // namespace content
diff --git a/chromium/content/browser/browsing_instance.h b/chromium/content/browser/browsing_instance.h
index b4a64417bca..775b64a8d20 100644
--- a/chromium/content/browser/browsing_instance.h
+++ b/chromium/content/browser/browsing_instance.h
@@ -161,6 +161,11 @@ class CONTENT_EXPORT BrowsingInstance final
bool IsDefaultSiteInstance(const SiteInstanceImpl* site_instance) const;
+ // Helper function used by other methods in this class to ensure consistent
+ // mapping between |url| and site URL.
+ // Note: This should not be used by code outside this class.
+ GURL GetSiteForURL(const GURL& url) const;
+
// Map of site to SiteInstance, to ensure we only have one SiteInstance per
// site.
typedef std::unordered_map<std::string, SiteInstanceImpl*> SiteInstanceMap;
diff --git a/chromium/content/browser/builtin_service_manifests.cc b/chromium/content/browser/builtin_service_manifests.cc
new file mode 100644
index 00000000000..1f6269beb2e
--- /dev/null
+++ b/chromium/content/browser/builtin_service_manifests.cc
@@ -0,0 +1,115 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/builtin_service_manifests.h"
+
+#include "base/feature_list.h"
+#include "base/no_destructor.h"
+#include "build/build_config.h"
+#include "components/services/heap_profiling/public/cpp/manifest.h"
+#include "content/public/app/content_browser_manifest.h"
+#include "content/public/app/content_gpu_manifest.h"
+#include "content/public/app/content_plugin_manifest.h"
+#include "content/public/app/content_renderer_manifest.h"
+#include "content/public/app/content_utility_manifest.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/network_service_util.h"
+#include "content/public/common/service_names.mojom.h"
+#include "media/mojo/buildflags.h"
+#include "media/mojo/services/cdm_manifest.h"
+#include "media/mojo/services/media_manifest.h"
+#include "services/audio/public/cpp/manifest.h"
+#include "services/data_decoder/public/cpp/manifest.h"
+#include "services/device/public/cpp/manifest.h"
+#include "services/media_session/public/cpp/manifest.h"
+#include "services/metrics/public/cpp/manifest.h"
+#include "services/network/public/cpp/manifest.h"
+#include "services/resource_coordinator/public/cpp/manifest.h"
+#include "services/service_manager/public/cpp/manifest_builder.h"
+#include "services/shape_detection/public/cpp/manifest.h"
+#include "services/tracing/manifest.h"
+#include "services/video_capture/public/cpp/manifest.h"
+#include "services/viz/public/cpp/manifest.h"
+
+#if defined(OS_LINUX)
+#include "components/services/font/public/cpp/manifest.h" // nogncheck
+#endif
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/assistant/buildflags.h"
+#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
+#include "chromeos/services/assistant/public/cpp/audio_decoder_manifest.h" // nogncheck
+#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
+#endif // defined(OS_CHROMEOS)
+
+namespace content {
+
+namespace {
+
+bool IsAudioServiceOutOfProcess() {
+ return base::FeatureList::IsEnabled(features::kAudioServiceOutOfProcess) &&
+ !GetContentClient()->browser()->OverridesAudioManager();
+}
+
+} // namespace
+
+const std::vector<service_manager::Manifest>& GetBuiltinServiceManifests() {
+ static base::NoDestructor<std::vector<service_manager::Manifest>> manifests{
+ std::vector<service_manager::Manifest>{
+ GetContentBrowserManifest(),
+
+ // NOTE: Content child processes are of course not running in the
+ // browser process, but the distinction between "in-process" and
+ // "out-of-process" manifests is temporary. For now, this is the right
+ // place for these manifests.
+ GetContentGpuManifest(),
+ GetContentPluginManifest(),
+ GetContentRendererManifest(),
+ GetContentUtilityManifest(),
+
+ heap_profiling::GetManifest(),
+ audio::GetManifest(IsAudioServiceOutOfProcess()
+ ? service_manager::Manifest::ExecutionMode::
+ kOutOfProcessBuiltin
+ : service_manager::Manifest::ExecutionMode::
+ kInProcessBuiltin),
+
+#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
+ media::GetCdmManifest(),
+#endif
+ media::GetMediaManifest(),
+ data_decoder::GetManifest(),
+ device::GetManifest(),
+ media_session::GetManifest(),
+ metrics::GetManifest(),
+ network::GetManifest(
+ IsInProcessNetworkService()
+ ? service_manager::Manifest::ExecutionMode::kInProcessBuiltin
+ : service_manager::Manifest::ExecutionMode::
+ kOutOfProcessBuiltin),
+ resource_coordinator::GetManifest(),
+ shape_detection::GetManifest(),
+ tracing::GetManifest(),
+ video_capture::GetManifest(
+ features::IsVideoCaptureServiceEnabledForOutOfProcess()
+ ? service_manager::Manifest::ExecutionMode::
+ kOutOfProcessBuiltin
+ : service_manager::Manifest::ExecutionMode::
+ kInProcessBuiltin),
+ viz::GetManifest(),
+#if defined(OS_LINUX)
+ font_service::GetManifest(),
+#endif
+#if defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
+ // TODO(https://crbug.com/929340): This doesn't belong here!
+ chromeos::assistant::GetAudioDecoderManifest(),
+#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
+#endif // defined(OS_CHROMEOS)
+ }};
+ return *manifests;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/builtin_service_manifests.h b/chromium/content/browser/builtin_service_manifests.h
new file mode 100644
index 00000000000..ca2f784cdf4
--- /dev/null
+++ b/chromium/content/browser/builtin_service_manifests.h
@@ -0,0 +1,20 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_BUILTIN_SERVICE_MANIFESTS_H_
+#define CONTENT_BROWSER_BUILTIN_SERVICE_MANIFESTS_H_
+
+#include <vector>
+
+#include "services/service_manager/public/cpp/manifest.h"
+
+namespace content {
+
+// Returns the list of manifests for all in-process and out-of-process services
+// built into the Content layer.
+const std::vector<service_manager::Manifest>& GetBuiltinServiceManifests();
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BUILTIN_SERVICE_MANIFESTS_H_
diff --git a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc
index f2ef2b2c363..f8d230de7ff 100644
--- a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc
@@ -30,7 +30,7 @@ CacheStorageBlobToDiskCache::CacheStorageBlobToDiskCache()
CacheStorageBlobToDiskCache::~CacheStorageBlobToDiskCache() = default;
void CacheStorageBlobToDiskCache::StreamBlobToCache(
- disk_cache::ScopedEntryPtr entry,
+ ScopedWritableEntry entry,
int disk_cache_body_index,
blink::mojom::BlobPtr blob,
uint64_t blob_size,
diff --git a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h
index efcfc5d5319..89964d8606d 100644
--- a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h
+++ b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h
@@ -11,9 +11,9 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "content/browser/cache_storage/scoped_writable_entry.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "net/disk_cache/disk_cache.h"
#include "services/network/public/cpp/net_adapters.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
@@ -24,7 +24,7 @@ class CONTENT_EXPORT CacheStorageBlobToDiskCache
: public blink::mojom::BlobReaderClient {
public:
using EntryAndBoolCallback =
- base::OnceCallback<void(disk_cache::ScopedEntryPtr, bool)>;
+ base::OnceCallback<void(ScopedWritableEntry, bool)>;
// The buffer size used for reading from blobs and writing to disk cache.
static const int kBufferSize;
@@ -35,7 +35,7 @@ class CONTENT_EXPORT CacheStorageBlobToDiskCache
// Writes the body of |blob| to |entry| with index
// |disk_cache_body_index|. |entry| is passed to the callback once complete.
// Only call this once per instantiation of CacheStorageBlobToDiskCache.
- void StreamBlobToCache(disk_cache::ScopedEntryPtr entry,
+ void StreamBlobToCache(ScopedWritableEntry entry,
int disk_cache_body_index,
blink::mojom::BlobPtr blob,
uint64_t blob_size,
@@ -57,7 +57,7 @@ class CONTENT_EXPORT CacheStorageBlobToDiskCache
void OnDataPipeReadable(MojoResult result);
int cache_entry_offset_ = 0;
- disk_cache::ScopedEntryPtr entry_;
+ ScopedWritableEntry entry_;
int disk_cache_body_index_ = 0;
EntryAndBoolCallback callback_;
diff --git a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc
index ddea197bcbe..b5ed62a5dfc 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
@@ -16,16 +16,13 @@
#include "base/test/null_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/cache_storage/scoped_writable_entry.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/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/disk_cache/disk_cache.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_job_factory_impl.h"
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_impl.h"
#include "storage/browser/blob/blob_storage_context.h"
@@ -40,30 +37,6 @@ const char kTestData[] = "Hello World";
const char kEntryKey[] = "FooEntry";
const int kCacheEntryIndex = 1;
-class NullURLRequestContextGetter : public net::URLRequestContextGetter {
- public:
- NullURLRequestContextGetter() : null_task_runner_(new base::NullTaskRunner) {}
-
- net::URLRequestContext* GetURLRequestContext() override { return nullptr; }
-
- scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
- const override {
- return null_task_runner_;
- }
-
- private:
- ~NullURLRequestContextGetter() override {}
-
- scoped_refptr<base::SingleThreadTaskRunner> null_task_runner_;
-};
-
-// Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
-// the memory.
-std::unique_ptr<storage::BlobProtocolHandler> CreateMockBlobProtocolHandler(
- storage::BlobStorageContext* blob_storage_context) {
- return std::make_unique<storage::BlobProtocolHandler>(blob_storage_context);
-}
-
// A CacheStorageBlobToDiskCache that can delay reading from blobs.
class TestCacheStorageBlobToDiskCache : public CacheStorageBlobToDiskCache {
public:
@@ -92,9 +65,6 @@ class CacheStorageBlobToDiskCacheTest : public testing::Test {
CacheStorageBlobToDiskCacheTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
browser_context_(new TestBrowserContext()),
- url_request_context_getter_(
- BrowserContext::GetDefaultStoragePartition(browser_context_.get())->
- GetURLRequestContext()),
cache_storage_blob_to_disk_cache_(
new TestCacheStorageBlobToDiskCache()),
data_(kTestData),
@@ -103,7 +73,6 @@ class CacheStorageBlobToDiskCacheTest : public testing::Test {
void SetUp() override {
InitBlobStorage();
- InitURLRequestJobFactory();
InitBlob();
InitCache();
}
@@ -116,17 +85,6 @@ class CacheStorageBlobToDiskCacheTest : public testing::Test {
blob_storage_context_ = blob_storage_context->context();
}
- void InitURLRequestJobFactory() {
- url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
- url_request_job_factory_->SetProtocolHandler(
- "blob", CreateMockBlobProtocolHandler(blob_storage_context_));
-
- net::URLRequestContext* url_request_context =
- url_request_context_getter_->GetURLRequestContext();
-
- url_request_context->set_job_factory(url_request_job_factory_.get());
- }
-
void InitBlob() {
auto blob_data =
std::make_unique<storage::BlobDataBuilder>("blob-id:myblob");
@@ -181,7 +139,7 @@ class CacheStorageBlobToDiskCacheTest : public testing::Test {
return callback_called_ && callback_success_;
}
- void StreamCallback(disk_cache::ScopedEntryPtr entry_ptr, bool success) {
+ void StreamCallback(ScopedWritableEntry entry_ptr, bool success) {
disk_cache_entry_ = std::move(entry_ptr);
callback_success_ = success;
callback_called_ = true;
@@ -189,12 +147,10 @@ class CacheStorageBlobToDiskCacheTest : public testing::Test {
TestBrowserThreadBundle browser_thread_bundle_;
std::unique_ptr<TestBrowserContext> browser_context_;
- std::unique_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
storage::BlobStorageContext* blob_storage_context_;
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
std::unique_ptr<storage::BlobDataHandle> blob_handle_;
std::unique_ptr<disk_cache::Backend> cache_backend_;
- disk_cache::ScopedEntryPtr disk_cache_entry_;
+ ScopedWritableEntry disk_cache_entry_;
std::unique_ptr<TestCacheStorageBlobToDiskCache>
cache_storage_blob_to_disk_cache_;
std::string data_;
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache_entry_handler.h b/chromium/content/browser/cache_storage/cache_storage_cache_entry_handler.h
index 358835dbd7b..688ec2ef6c9 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache_entry_handler.h
+++ b/chromium/content/browser/cache_storage/cache_storage_cache_entry_handler.h
@@ -12,6 +12,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
+#include "content/browser/cache_storage/scoped_writable_entry.h"
#include "content/common/content_export.h"
#include "net/disk_cache/disk_cache.h"
#include "storage/browser/blob/blob_data_builder.h"
@@ -51,7 +52,7 @@ struct PutContext {
// Provided while writing to the cache.
ErrorCallback callback;
- disk_cache::ScopedEntryPtr cache_entry;
+ ScopedWritableEntry cache_entry;
private:
DISALLOW_COPY_AND_ASSIGN(PutContext);
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 d436bbc158b..23b82b29d91 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/cache_storage/legacy/legacy_cache_storage_cache.h"
-
#include <stddef.h>
#include <stdint.h>
@@ -30,6 +28,8 @@
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_histogram_utils.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
+#include "content/browser/cache_storage/legacy/legacy_cache_storage.h"
+#include "content/browser/cache_storage/legacy/legacy_cache_storage_cache.h"
#include "content/common/background_fetch/background_fetch_types.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_thread.h"
@@ -40,11 +40,11 @@
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "crypto/symmetric_key.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/data_pipe_drainer.h"
#include "net/base/test_completion_callback.h"
#include "net/disk_cache/disk_cache.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_job_factory_impl.h"
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_data_snapshot.h"
@@ -52,6 +52,7 @@
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/blob/blob_url_request_job_factory.h"
#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/browser/test/fake_blob.h"
#include "storage/browser/test/mock_quota_manager_proxy.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "storage/common/blob_storage/blob_handle.h"
@@ -94,6 +95,22 @@ void SizeCallback(base::RunLoop* run_loop,
run_loop->Quit();
}
+// A blob that never finishes writing to its pipe.
+class SlowBlob : public storage::FakeBlob {
+ public:
+ explicit SlowBlob(base::OnceClosure quit_closure)
+ : FakeBlob("foo"), quit_closure_(std::move(quit_closure)) {}
+
+ void ReadAll(mojo::ScopedDataPipeProducerHandle producer_handle,
+ blink::mojom::BlobReaderClientPtr client) override {
+ // Don't respond, forcing the consumer to wait forever.
+ std::move(quit_closure_).Run();
+ }
+
+ private:
+ base::OnceClosure quit_closure_;
+};
+
// A disk_cache::Backend wrapper that can delay operations.
class DelayableBackend : public disk_cache::Backend {
public:
@@ -221,9 +238,9 @@ std::string CopySideData(blink::mojom::Blob* actual_blob) {
std::string output;
base::RunLoop loop;
actual_blob->ReadSideData(base::BindLambdaForTesting(
- [&](const base::Optional<std::vector<uint8_t>>& data) {
+ [&](const base::Optional<mojo_base::BigBuffer> data) {
ASSERT_TRUE(data);
- output.append(data->begin(), data->end());
+ output.append(data->data(), data->data() + data->size());
loop.Quit();
}));
loop.Run();
@@ -322,6 +339,7 @@ class TestCacheStorageCache : public LegacyCacheStorageCache {
cache_name,
path,
cache_storage,
+ base::ThreadTaskRunnerHandle::Get(),
quota_manager_proxy,
blob_context,
0 /* cache_size */,
@@ -382,14 +400,16 @@ class MockLegacyCacheStorage : public LegacyCacheStorage {
const base::FilePath& origin_path,
bool memory_only,
base::SequencedTaskRunner* cache_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
- CacheStorageManager* cache_storage_manager,
+ LegacyCacheStorageManager* cache_storage_manager,
const url::Origin& origin,
CacheStorageOwner owner)
: LegacyCacheStorage(origin_path,
memory_only,
cache_task_runner,
+ std::move(scheduler_task_runner),
std::move(quota_manager_proxy),
std::move(blob_context),
cache_storage_manager,
@@ -416,15 +436,14 @@ class CacheStorageCacheTest : public testing::Test {
blob_storage_context_ = blob_storage_context->context();
const bool is_incognito = MemoryOnly();
- base::FilePath temp_dir_path;
if (!is_incognito) {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- temp_dir_path = temp_dir_.GetPath();
+ temp_dir_path_ = temp_dir_.GetPath();
}
quota_policy_ = new MockSpecialStoragePolicy;
mock_quota_manager_ = new MockQuotaManager(
- is_incognito, temp_dir_path, base::ThreadTaskRunnerHandle::Get().get(),
+ is_incognito, temp_dir_path_, base::ThreadTaskRunnerHandle::Get().get(),
quota_policy_.get());
mock_quota_manager_->SetQuota(
kOrigin, blink::mojom::StorageType::kTemporary, 1024 * 1024 * 100);
@@ -432,16 +451,6 @@ class CacheStorageCacheTest : public testing::Test {
quota_manager_proxy_ = new MockQuotaManagerProxy(
mock_quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
- url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
- url_request_job_factory_->SetProtocolHandler(
- "blob", CreateMockBlobProtocolHandler(blob_storage_context->context()));
-
- net::URLRequestContext* url_request_context =
- BrowserContext::GetDefaultStoragePartition(&browser_context_)->
- GetURLRequestContext()->GetURLRequestContext();
-
- url_request_context->set_job_factory(url_request_job_factory_.get());
-
CreateRequests(blob_storage_context);
response_time_ = base::Time::Now();
@@ -456,13 +465,14 @@ class CacheStorageCacheTest : public testing::Test {
// CacheStorageCacheHandle reference counting. A LegacyCacheStorage
// must be present to be notified when a cache becomes unreferenced.
mock_cache_storage_ = std::make_unique<MockLegacyCacheStorage>(
- temp_dir_path, MemoryOnly(), base::ThreadTaskRunnerHandle::Get().get(),
- quota_manager_proxy_, blob_storage_context_->AsWeakPtr(),
+ temp_dir_path_, MemoryOnly(), base::ThreadTaskRunnerHandle::Get().get(),
+ base::ThreadTaskRunnerHandle::Get(), quota_manager_proxy_,
+ blob_storage_context_->AsWeakPtr(),
/* cache_storage_manager = */ nullptr, kOrigin,
CacheStorageOwner::kCacheAPI);
cache_ = std::make_unique<TestCacheStorageCache>(
- kOrigin, kCacheName, temp_dir_path, mock_cache_storage_.get(),
+ kOrigin, kCacheName, temp_dir_path_, mock_cache_storage_.get(),
quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr());
cache_->Init();
}
@@ -835,13 +845,13 @@ class CacheStorageCacheTest : public testing::Test {
base::ScopedTempDir temp_dir_;
TestBrowserThreadBundle browser_thread_bundle_;
TestBrowserContext browser_context_;
- std::unique_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
scoped_refptr<MockSpecialStoragePolicy> quota_policy_;
scoped_refptr<MockQuotaManager> mock_quota_manager_;
scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
storage::BlobStorageContext* blob_storage_context_;
std::unique_ptr<MockLegacyCacheStorage> mock_cache_storage_;
+ base::FilePath temp_dir_path_;
std::unique_ptr<TestCacheStorageCache> cache_;
blink::mojom::FetchAPIRequestPtr body_request_;
@@ -2211,6 +2221,53 @@ TEST_P(CacheStorageCacheTestP, OpsFailOnClosedBackend) {
VerifyAllOpsFail();
}
+// Shutdown the cache in the middle of its writing the response body. Upon
+// restarting, that response shouldn't be available. See crbug.com/617683.
+TEST_P(CacheStorageCacheTestP, UnfinishedPutsShouldNotBeReusable) {
+ // Create a response with a blob that takes forever to write its bytes to the
+ // mojo pipe. Guaranteeing that the response isn't finished writing by the
+ // time we close the backend.
+ base::RunLoop run_loop;
+ auto blob = blink::mojom::SerializedBlob::New();
+ blob->uuid = "mock blob";
+ blob->size = 100;
+ mojo::MakeStrongBinding(std::make_unique<SlowBlob>(run_loop.QuitClosure()),
+ MakeRequest(&blob->blob));
+ blink::mojom::FetchAPIResponsePtr response = CreateNoBodyResponse();
+ response->url_list = {kBodyUrl};
+ response->blob = std::move(blob);
+
+ blink::mojom::BatchOperationPtr operation =
+ blink::mojom::BatchOperation::New();
+ operation->operation_type = blink::mojom::OperationType::kPut;
+ operation->request = BackgroundFetchSettledFetch::CloneRequest(body_request_);
+ operation->response = std::move(response);
+ std::vector<blink::mojom::BatchOperationPtr> operations;
+ operations.emplace_back(std::move(operation));
+
+ // Start the put operation and let it run until the blob is supposed to write
+ // to its pipe.
+ cache_->BatchOperation(std::move(operations), /* trace_id = */ 0,
+ base::DoNothing(), base::DoNothing());
+ run_loop.Run();
+
+ // Shut down the cache. Doing so causes the write to cease, and the entry
+ // should be erased.
+ cache_ = nullptr;
+ base::RunLoop().RunUntilIdle();
+
+ // Create a new Cache in the same space.
+ ChromeBlobStorageContext* blob_storage_context =
+ ChromeBlobStorageContext::GetFor(&browser_context_);
+ cache_ = std::make_unique<TestCacheStorageCache>(
+ kOrigin, kCacheName, temp_dir_path_, nullptr /* CacheStorage */,
+ quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr());
+ cache_->Init();
+
+ // Now attempt to read the same response from the cache. It should fail.
+ EXPECT_FALSE(Match(body_request_));
+}
+
TEST_P(CacheStorageCacheTestP, BlobReferenceDelaysClose) {
// Create the backend and put something in it.
EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
@@ -2300,7 +2357,8 @@ TEST_P(CacheStorageCacheTestP, VerifySerialScheduling) {
#define MAYBE_KeysWithManyCacheEntries KeysWithManyCacheEntries
#endif
TEST_P(CacheStorageCacheTestP, MAYBE_KeysWithManyCacheEntries) {
- constexpr int kNumEntries = 1000;
+ // Use a smaller list in disk mode to reduce test runtime.
+ const int kNumEntries = MemoryOnly() ? 1000 : 250;
std::vector<std::string> expected_keys;
for (int i = 0; i < kNumEntries; ++i) {
@@ -2312,6 +2370,7 @@ TEST_P(CacheStorageCacheTestP, MAYBE_KeysWithManyCacheEntries) {
}
EXPECT_TRUE(Keys());
+ EXPECT_EQ(expected_keys.size(), callback_strings_.size());
EXPECT_EQ(expected_keys, callback_strings_);
}
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 01cbfcfff53..cc8bfd1619f 100644
--- a/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
@@ -8,8 +8,10 @@
#include "base/files/file_path.h"
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/browser/cache_storage/cache_storage_manager.h"
+#include "content/browser/cache_storage/cache_storage_dispatcher_host.h"
+#include "content/browser/cache_storage/legacy/legacy_cache_storage_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -21,11 +23,15 @@
namespace content {
CacheStorageContextImpl::CacheStorageContextImpl(
- BrowserContext* browser_context) {
+ BrowserContext* browser_context)
+ : task_runner_(
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})),
+ observers_(base::MakeRefCounted<ObserverList>()) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
CacheStorageContextImpl::~CacheStorageContextImpl() {
+ // Can be destroyed on any thread.
}
void CacheStorageContextImpl::Init(
@@ -42,29 +48,33 @@ void CacheStorageContextImpl::Init(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
- // This thread-hopping antipattern is needed here for some unit tests, where
- // browser threads are collapsed the quota manager is initialized before the
- // posted task can register the quota client.
- // TODO: Fix the tests to let the quota manager initialize normally.
- if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- CreateCacheStorageManager(user_data_directory, cache_task_runner,
- std::move(quota_manager_proxy));
- return;
- }
-
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
+ task_runner_->PostTask(
+ FROM_HERE,
base::BindOnce(&CacheStorageContextImpl::CreateCacheStorageManager, this,
- user_data_directory, cache_task_runner,
+ user_data_directory, std::move(cache_task_runner),
std::move(quota_manager_proxy)));
}
void CacheStorageContextImpl::Shutdown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&CacheStorageContextImpl::ShutdownOnIO, this));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&CacheStorageContextImpl::ShutdownOnTaskRunner, this));
+}
+
+void CacheStorageContextImpl::AddBinding(
+ blink::mojom::CacheStorageRequest request,
+ const url::Origin& origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!dispatcher_host_) {
+ dispatcher_host_ =
+ base::SequenceBound<CacheStorageDispatcherHost>(task_runner_);
+ dispatcher_host_.Post(FROM_HERE, &CacheStorageDispatcherHost::Init,
+ base::RetainedRef(this));
+ }
+ dispatcher_host_.Post(FROM_HERE, &CacheStorageDispatcherHost::AddBinding,
+ std::move(request), origin);
}
CacheStorageManager* CacheStorageContextImpl::cache_manager() const {
@@ -74,63 +84,83 @@ CacheStorageManager* CacheStorageContextImpl::cache_manager() const {
void CacheStorageContextImpl::SetBlobParametersForCache(
ChromeBlobStorageContext* blob_storage_context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (cache_manager_ && blob_storage_context) {
- cache_manager_->SetBlobParametersForCache(
- blob_storage_context->context()->AsWeakPtr());
- }
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &CacheStorageContextImpl::SetBlobParametersForCacheOnTaskRunner, this,
+ base::RetainedRef(blob_storage_context)));
}
void CacheStorageContextImpl::GetAllOriginsInfo(
CacheStorageContext::GetUsageInfoCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (!cache_manager_) {
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(std::move(callback), std::vector<StorageUsageInfo>()));
- return;
- }
-
- cache_manager_->GetAllOriginsUsage(CacheStorageOwner::kCacheAPI,
- std::move(callback));
+ // Can be called on any sequence.
+
+ callback = base::BindOnce(
+ [](scoped_refptr<base::SequencedTaskRunner> reply_task_runner,
+ GetUsageInfoCallback inner,
+ const std::vector<StorageUsageInfo>& entries) {
+ reply_task_runner->PostTask(FROM_HERE,
+ base::BindOnce(std::move(inner), entries));
+ },
+ base::SequencedTaskRunnerHandle::Get(), std::move(callback));
+
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](scoped_refptr<CacheStorageContextImpl> context,
+ GetUsageInfoCallback callback) {
+ if (!context->cache_manager()) {
+ std::move(callback).Run(std::vector<StorageUsageInfo>());
+ return;
+ }
+ context->cache_manager()->GetAllOriginsUsage(
+ CacheStorageOwner::kCacheAPI, std::move(callback));
+ },
+ base::RetainedRef(this), std::move(callback)));
}
void CacheStorageContextImpl::DeleteForOrigin(const GURL& origin) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (cache_manager_)
- cache_manager_->DeleteOriginData(url::Origin::Create(origin),
- CacheStorageOwner::kCacheAPI);
+ // Can be called on any sequence.
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(
+ [](scoped_refptr<CacheStorageContextImpl> context,
+ const GURL& origin) {
+ if (!context->cache_manager())
+ return;
+ context->cache_manager()->DeleteOriginData(
+ url::Origin::Create(origin),
+ CacheStorageOwner::kCacheAPI);
+ },
+ base::RetainedRef(this), origin));
}
void CacheStorageContextImpl::AddObserver(
CacheStorageContextImpl::Observer* observer) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (cache_manager_)
- cache_manager_->AddObserver(observer);
+ // Any sequence
+ observers_->AddObserver(observer);
}
void CacheStorageContextImpl::RemoveObserver(
CacheStorageContextImpl::Observer* observer) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (cache_manager_)
- cache_manager_->RemoveObserver(observer);
+ // Any sequence
+ observers_->RemoveObserver(observer);
}
void CacheStorageContextImpl::CreateCacheStorageManager(
const base::FilePath& user_data_directory,
scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK(!cache_manager_);
- cache_manager_ = CacheStorageManager::Create(
- user_data_directory, cache_task_runner, std::move(quota_manager_proxy));
+ cache_manager_ = LegacyCacheStorageManager::Create(
+ user_data_directory, std::move(cache_task_runner), task_runner_,
+ std::move(quota_manager_proxy), observers_);
}
-void CacheStorageContextImpl::ShutdownOnIO() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+void CacheStorageContextImpl::ShutdownOnTaskRunner() {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
// Delete session-only ("clear on exit") origins.
if (special_storage_policy_ &&
@@ -173,4 +203,14 @@ void CacheStorageContextImpl::ShutdownOnIO() {
cache_manager_ = nullptr;
}
+void CacheStorageContextImpl::SetBlobParametersForCacheOnTaskRunner(
+ ChromeBlobStorageContext* blob_storage_context) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
+ if (cache_manager_ && blob_storage_context) {
+ cache_manager_->SetBlobParametersForCache(
+ blob_storage_context->context()->AsWeakPtr());
+ }
+}
+
} // 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 e7342c2e1f2..d9f1e70460d 100644
--- a/chromium/content/browser/cache_storage/cache_storage_context_impl.h
+++ b/chromium/content/browser/cache_storage/cache_storage_context_impl.h
@@ -10,9 +10,12 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
+#include "base/observer_list_threadsafe.h"
+#include "base/threading/sequence_bound.h"
#include "content/common/content_export.h"
#include "content/public/browser/cache_storage_context.h"
#include "storage/browser/quota/special_storage_policy.h"
+#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-forward.h"
namespace base {
class FilePath;
@@ -31,6 +34,7 @@ namespace content {
class BrowserContext;
class ChromeBlobStorageContext;
+class CacheStorageDispatcherHost;
class CacheStorageManager;
// One instance of this exists per StoragePartition, and services multiple
@@ -51,6 +55,8 @@ class CONTENT_EXPORT CacheStorageContextImpl : public CacheStorageContext {
virtual ~Observer() {}
};
+ using ObserverList = base::ObserverListThreadSafe<Observer>;
+
// Init and Shutdown are for use on the UI thread when the profile,
// storagepartition is being setup and torn down.
void Init(const base::FilePath& user_data_directory,
@@ -58,13 +64,16 @@ class CONTENT_EXPORT CacheStorageContextImpl : public CacheStorageContext {
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
void Shutdown();
- // Only callable on the IO thread.
+ // Only callable on the UI thread.
+ void AddBinding(blink::mojom::CacheStorageRequest request,
+ const url::Origin& origin);
+
CacheStorageManager* cache_manager() const;
bool is_incognito() const { return is_incognito_; }
// This function must be called after this object is created but before any
- // CacheStorageCache operations. It must be called on the IO thread. If
+ // CacheStorageCache operations. It must be called on the UI thread. If
// |blob_storage_context| is NULL the function immediately returns without
// forwarding to the CacheStorageManager.
void SetBlobParametersForCache(
@@ -74,7 +83,7 @@ class CONTENT_EXPORT CacheStorageContextImpl : public CacheStorageContext {
void GetAllOriginsInfo(GetUsageInfoCallback callback) override;
void DeleteForOrigin(const GURL& origin) override;
- // Only callable on the IO thread.
+ // Callable on any sequence.
void AddObserver(CacheStorageContextImpl::Observer* observer);
void RemoveObserver(CacheStorageContextImpl::Observer* observer);
@@ -87,7 +96,14 @@ class CONTENT_EXPORT CacheStorageContextImpl : public CacheStorageContext {
scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
- void ShutdownOnIO();
+ void ShutdownOnTaskRunner();
+
+ void SetBlobParametersForCacheOnTaskRunner(
+ ChromeBlobStorageContext* blob_storage_context);
+
+ // Initialized at construction.
+ const scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ const scoped_refptr<ObserverList> observers_;
// Initialized in Init(); true if the user data directory is empty.
bool is_incognito_ = false;
@@ -97,6 +113,9 @@ class CONTENT_EXPORT CacheStorageContextImpl : public CacheStorageContext {
// Only accessed on the IO thread.
scoped_refptr<CacheStorageManager> cache_manager_;
+
+ // Initialized from the UI thread and bound to |task_runner_|.
+ base::SequenceBound<CacheStorageDispatcherHost> dispatcher_host_;
};
} // namespace content
diff --git a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
index 316370f3eb3..48f943a7f5b 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -4,37 +4,23 @@
#include "content/browser/cache_storage/cache_storage_dispatcher_host.h"
-#include <stddef.h>
-#include <utility>
-
#include "base/bind.h"
-#include "base/logging.h"
-#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
+#include "content/browser/cache_storage/cache_storage.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
-#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_histogram_utils.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/cache_storage/cache_storage_trace_utils.h"
#include "content/common/background_fetch/background_fetch_types.h"
-#include "content/common/service_worker/service_worker_utils.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/referrer_type_converters.h"
#include "mojo/public/cpp/bindings/message.h"
-#include "third_party/blink/public/common/cache_storage/cache_storage_utils.h"
-#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -88,13 +74,14 @@ class CacheStorageDispatcherHost::CacheImpl
explicit CacheImpl(CacheStorageCacheHandle cache_handle)
: cache_handle_(std::move(cache_handle)) {}
- ~CacheImpl() override = default;
+ ~CacheImpl() override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); }
// blink::mojom::CacheStorageCache implementation:
void Match(blink::mojom::FetchAPIRequestPtr request,
blink::mojom::CacheQueryOptionsPtr match_options,
int64_t trace_id,
MatchCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
TRACE_EVENT_WITH_FLOW2("CacheStorage",
"CacheStorageDispatchHost::CacheImpl::Match",
TRACE_ID_GLOBAL(trace_id),
@@ -157,6 +144,7 @@ class CacheStorageDispatcherHost::CacheImpl
blink::mojom::CacheQueryOptionsPtr match_options,
int64_t trace_id,
MatchAllCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
TRACE_EVENT_WITH_FLOW2("CacheStorage",
"CacheStorageDispatchHost::CacheImpl::MatchAll",
TRACE_ID_GLOBAL(trace_id),
@@ -210,6 +198,7 @@ class CacheStorageDispatcherHost::CacheImpl
blink::mojom::CacheQueryOptionsPtr match_options,
int64_t trace_id,
KeysCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
TRACE_EVENT_WITH_FLOW2("CacheStorage",
"CacheStorageDispatchHost::CacheImpl::Keys",
TRACE_ID_GLOBAL(trace_id),
@@ -266,6 +255,7 @@ class CacheStorageDispatcherHost::CacheImpl
void Batch(std::vector<blink::mojom::BatchOperationPtr> batch_operations,
int64_t trace_id,
BatchCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
TRACE_EVENT_WITH_FLOW1(
"CacheStorage", "CacheStorageDispatchHost::CacheImpl::Batch",
TRACE_ID_GLOBAL(trace_id),
@@ -334,6 +324,7 @@ class CacheStorageDispatcherHost::CacheImpl
const std::vector<uint8_t>& side_data,
int64_t trace_id,
SetSideDataCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
TRACE_EVENT_WITH_FLOW1("CacheStorage",
"CacheStorageDispatcherHost::CacheImpl::SetSideData",
TRACE_ID_GLOBAL(trace_id),
@@ -353,6 +344,7 @@ class CacheStorageDispatcherHost::CacheImpl
}
CacheStorageCacheHandle cache_handle_;
+ SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(CacheImpl);
};
@@ -370,11 +362,14 @@ class CacheStorageDispatcherHost::CacheStorageImpl final
// the backend when the mojo connection is created.
}
- ~CacheStorageImpl() override = default;
+ ~CacheStorageImpl() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ }
// Mojo CacheStorage Interface implementation:
void Keys(int64_t trace_id,
blink::mojom::CacheStorage::KeysCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
TRACE_EVENT_WITH_FLOW0(
"CacheStorage", "CacheStorageDispatchHost::CacheStorageImpl::Keys",
TRACE_ID_GLOBAL(trace_id),
@@ -413,6 +408,7 @@ class CacheStorageDispatcherHost::CacheStorageImpl final
void Delete(const base::string16& cache_name,
int64_t trace_id,
blink::mojom::CacheStorage::DeleteCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::string utf8_cache_name = base::UTF16ToUTF8(cache_name);
TRACE_EVENT_WITH_FLOW1("CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Delete",
@@ -449,6 +445,7 @@ class CacheStorageDispatcherHost::CacheStorageImpl final
void Has(const base::string16& cache_name,
int64_t trace_id,
blink::mojom::CacheStorage::HasCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::string utf8_cache_name = base::UTF16ToUTF8(cache_name);
TRACE_EVENT_WITH_FLOW1("CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Has",
@@ -489,6 +486,7 @@ class CacheStorageDispatcherHost::CacheStorageImpl final
blink::mojom::MultiCacheQueryOptionsPtr match_options,
int64_t trace_id,
blink::mojom::CacheStorage::MatchCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
TRACE_EVENT_WITH_FLOW2("CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Match",
TRACE_ID_GLOBAL(trace_id),
@@ -555,6 +553,7 @@ class CacheStorageDispatcherHost::CacheStorageImpl final
void Open(const base::string16& cache_name,
int64_t trace_id,
blink::mojom::CacheStorage::OpenCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::string utf8_cache_name = base::UTF16ToUTF8(cache_name);
TRACE_EVENT_WITH_FLOW1("CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Open",
@@ -616,6 +615,7 @@ class CacheStorageDispatcherHost::CacheStorageImpl final
// automatically. This automatic open is necessary to re-attach to the
// backend after the browser storage has been wiped.
content::CacheStorage* GetOrCreateCacheStorage() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(owner_);
if (!cache_storage_handle_.value())
cache_storage_handle_ = owner_->OpenCacheStorage(origin_);
@@ -628,32 +628,26 @@ class CacheStorageDispatcherHost::CacheStorageImpl final
const url::Origin origin_;
CacheStorageHandle cache_storage_handle_;
+ SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<CacheStorageImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CacheStorageImpl);
};
CacheStorageDispatcherHost::CacheStorageDispatcherHost() = default;
-CacheStorageDispatcherHost::~CacheStorageDispatcherHost() = default;
-
-void CacheStorageDispatcherHost::Init(CacheStorageContextImpl* context) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&CacheStorageDispatcherHost::CreateCacheListener,
- base::RetainedRef(this), base::RetainedRef(context)));
+CacheStorageDispatcherHost::~CacheStorageDispatcherHost() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
-void CacheStorageDispatcherHost::CreateCacheListener(
- CacheStorageContextImpl* context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+void CacheStorageDispatcherHost::Init(CacheStorageContextImpl* context) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
context_ = context;
}
void CacheStorageDispatcherHost::AddBinding(
blink::mojom::CacheStorageRequest request,
const url::Origin& origin) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto impl = std::make_unique<CacheStorageImpl>(this, origin);
bindings_.AddBinding(std::move(impl), std::move(request));
}
@@ -661,12 +655,13 @@ void CacheStorageDispatcherHost::AddBinding(
void CacheStorageDispatcherHost::AddCacheBinding(
std::unique_ptr<CacheImpl> cache_impl,
blink::mojom::CacheStorageCacheAssociatedRequest request) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
cache_bindings_.AddBinding(std::move(cache_impl), std::move(request));
}
CacheStorageHandle CacheStorageDispatcherHost::OpenCacheStorage(
const url::Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!context_ || !context_->cache_manager() ||
!OriginCanAccessCacheStorage(origin))
return CacheStorageHandle();
diff --git a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
index 47e14601a81..e6b1ace714a 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
@@ -7,19 +7,10 @@
#include <stdint.h>
-#include <list>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "content/browser/cache_storage/cache_storage.h"
-#include "content/browser/cache_storage/cache_storage_index.h"
-#include "content/public/browser/browser_thread.h"
+#include "content/browser/cache_storage/cache_storage_handle.h"
#include "mojo/public/cpp/bindings/strong_associated_binding_set.h"
#include "mojo/public/cpp/bindings/strong_binding_set.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
+#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h"
namespace url {
class Origin;
@@ -30,18 +21,18 @@ namespace content {
class CacheStorageContextImpl;
// Handles Cache Storage related messages sent to the browser process from
-// child processes. One host instance exists per child process. All
-// messages are processed on the IO thread.
-class CONTENT_EXPORT CacheStorageDispatcherHost
- : public base::RefCountedThreadSafe<CacheStorageDispatcherHost,
- BrowserThread::DeleteOnIOThread> {
+// child processes. One host instance exists per child process. Each host
+// is bound to the cache_storage scheduler sequence and may not be accessed
+// from other sequences.
+class CacheStorageDispatcherHost {
public:
CacheStorageDispatcherHost();
+ ~CacheStorageDispatcherHost();
- // Runs on UI thread.
+ // Must be called before AddBinding().
void Init(CacheStorageContextImpl* context);
- // Binds Mojo request to this instance, must be called on IO thread.
+ // Binds the CacheStorage Mojo request to this instance.
// NOTE: The same CacheStorageDispatcherHost instance may be bound to
// different clients on different origins. Each context is kept on
// BindingSet's context. This guarantees that the browser process uses the
@@ -51,10 +42,6 @@ class CONTENT_EXPORT CacheStorageDispatcherHost
const url::Origin& origin);
private:
- // Friends to allow BrowserThread::DeleteOnIOThread delegation.
- friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
- friend class base::DeleteHelper<CacheStorageDispatcherHost>;
-
class CacheStorageImpl;
class CacheImpl;
friend class CacheImpl;
@@ -62,20 +49,15 @@ class CONTENT_EXPORT CacheStorageDispatcherHost
void AddCacheBinding(
std::unique_ptr<CacheImpl> cache_impl,
blink::mojom::CacheStorageCacheAssociatedRequest request);
-
CacheStorageHandle OpenCacheStorage(const url::Origin& origin);
- ~CacheStorageDispatcherHost();
-
- // Called by Init() on IO thread.
- void CreateCacheListener(CacheStorageContextImpl* context);
-
scoped_refptr<CacheStorageContextImpl> context_;
mojo::StrongBindingSet<blink::mojom::CacheStorage> bindings_;
mojo::StrongAssociatedBindingSet<blink::mojom::CacheStorageCache>
cache_bindings_;
+ SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(CacheStorageDispatcherHost);
};
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.cc b/chromium/content/browser/cache_storage/cache_storage_manager.cc
index eab6ea022fb..5d8127fcbfb 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.cc
@@ -4,256 +4,10 @@
#include "content/browser/cache_storage/cache_storage_manager.h"
-#include <stdint.h>
-
-#include <map>
-#include <numeric>
-#include <set>
-#include <utility>
-
-#include "base/barrier_closure.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/containers/id_map.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_util.h"
-#include "base/hash/sha1.h"
-#include "base/memory/ptr_util.h"
-#include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "content/browser/cache_storage/cache_storage.h"
-#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 "net/base/url_util.h"
-#include "storage/browser/quota/quota_manager_proxy.h"
-#include "storage/common/database/database_identifier.h"
-#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
-#include "url/gurl.h"
#include "url/origin.h"
namespace content {
-namespace {
-
-bool DeleteDir(const base::FilePath& path) {
- return base::DeleteFile(path, true /* recursive */);
-}
-
-void DeleteOriginDidDeleteDir(storage::QuotaClient::DeletionCallback callback,
- bool rv) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(callback),
- rv ? blink::mojom::QuotaStatusCode::kOk
- : blink::mojom::QuotaStatusCode::kErrorAbort));
-}
-
-// Calculate the sum of all cache sizes in this store, but only if all sizes are
-// known. If one or more sizes are not known then return kSizeUnknown.
-int64_t GetCacheStorageSize(const proto::CacheStorageIndex& index) {
- int64_t storage_size = 0;
- for (int i = 0, max = index.cache_size(); i < max; ++i) {
- const proto::CacheStorageIndex::Cache& cache = index.cache(i);
- if (!cache.has_size() || cache.size() == CacheStorage::kSizeUnknown)
- return CacheStorage::kSizeUnknown;
- storage_size += cache.size();
- }
- return storage_size;
-}
-
-// Open the various cache directories' index files and extract their origins,
-// sizes (if current), and last modified times.
-void ListOriginsAndLastModifiedOnTaskRunner(
- std::vector<StorageUsageInfo>* usages,
- base::FilePath root_path,
- CacheStorageOwner owner) {
- base::FileEnumerator file_enum(root_path, false /* recursive */,
- base::FileEnumerator::DIRECTORIES);
-
- base::FilePath path;
- while (!(path = file_enum.Next()).empty()) {
- base::FilePath index_path =
- path.AppendASCII(LegacyCacheStorage::kIndexFileName);
- base::File::Info file_info;
- base::Time index_last_modified;
- if (GetFileInfo(index_path, &file_info))
- index_last_modified = file_info.last_modified;
- std::string protobuf;
- base::ReadFileToString(path.AppendASCII(LegacyCacheStorage::kIndexFileName),
- &protobuf);
- proto::CacheStorageIndex index;
- if (index.ParseFromString(protobuf)) {
- if (index.has_origin()) {
- if (path ==
- CacheStorageManager::ConstructOriginPath(
- root_path, url::Origin::Create(GURL(index.origin())), owner)) {
- if (base::GetFileInfo(path, &file_info)) {
- int64_t storage_size = CacheStorage::kSizeUnknown;
- if (file_info.last_modified < index_last_modified)
- storage_size = GetCacheStorageSize(index);
- usages->push_back(
- StorageUsageInfo(url::Origin::Create(GURL(index.origin())),
- storage_size, file_info.last_modified));
- }
- }
- }
- }
- }
-}
-
-std::set<url::Origin> ListOriginsOnTaskRunner(base::FilePath root_path,
- CacheStorageOwner owner) {
- std::vector<StorageUsageInfo> usages;
- ListOriginsAndLastModifiedOnTaskRunner(&usages, root_path, owner);
-
- std::set<url::Origin> out_origins;
- for (const StorageUsageInfo& usage : usages)
- out_origins.insert(usage.origin);
-
- return out_origins;
-}
-
-void GetOriginsForHostDidListOrigins(
- const std::string& host,
- storage::QuotaClient::GetOriginsCallback callback,
- const std::set<url::Origin>& origins) {
- std::set<url::Origin> out_origins;
- for (const url::Origin& origin : origins) {
- if (host == net::GetHostOrSpecFromURL(origin.GetURL()))
- out_origins.insert(origin);
- }
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), out_origins));
-}
-
-void AllOriginSizesReported(
- std::unique_ptr<std::vector<StorageUsageInfo>> usages,
- CacheStorageContext::GetUsageInfoCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), *usages));
-}
-
-void OneOriginSizeReported(base::OnceClosure callback,
- StorageUsageInfo* usage,
- int64_t size) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- DCHECK_NE(size, CacheStorage::kSizeUnknown);
- usage->total_size_bytes = size;
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
-}
-
-} // namespace
-
-// static
-scoped_refptr<CacheStorageManager> CacheStorageManager::Create(
- const base::FilePath& path,
- scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
- scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) {
- base::FilePath root_path = path;
- if (!path.empty()) {
- root_path = path.Append(ServiceWorkerContextCore::kServiceWorkerDirectory)
- .AppendASCII("CacheStorage");
- }
-
- return base::WrapRefCounted(new CacheStorageManager(
- root_path, std::move(cache_task_runner), std::move(quota_manager_proxy)));
-}
-
-// static
-scoped_refptr<CacheStorageManager> CacheStorageManager::Create(
- CacheStorageManager* old_manager) {
- 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
- // the dispatcher host per usual.
- manager->SetBlobParametersForCache(old_manager->blob_storage_context());
- return manager;
-}
-
-CacheStorageManager::~CacheStorageManager() = default;
-
-CacheStorageHandle CacheStorageManager::OpenCacheStorage(
- const url::Origin& origin,
- CacheStorageOwner owner) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Wait to create the MemoryPressureListener until the first CacheStorage
- // object is needed. This ensures we create the listener on the correct
- // thread.
- if (!memory_pressure_listener_) {
- memory_pressure_listener_ =
- std::make_unique<base::MemoryPressureListener>(base::BindRepeating(
- &CacheStorageManager::OnMemoryPressure, base::Unretained(this)));
- }
-
- CacheStorageMap::const_iterator it = cache_storage_map_.find({origin, owner});
- if (it == cache_storage_map_.end()) {
- LegacyCacheStorage* cache_storage = new LegacyCacheStorage(
- ConstructOriginPath(root_path_, origin, owner), IsMemoryBacked(),
- cache_task_runner_.get(), quota_manager_proxy_, blob_context_, this,
- origin, owner);
- cache_storage_map_[{origin, owner}] = base::WrapUnique(cache_storage);
- return cache_storage->CreateHandle();
- }
- return it->second.get()->CreateHandle();
-}
-
-void CacheStorageManager::SetBlobParametersForCache(
- base::WeakPtr<storage::BlobStorageContext> blob_storage_context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(cache_storage_map_.empty());
- DCHECK(!blob_context_ || blob_context_.get() == blob_storage_context.get());
- blob_context_ = blob_storage_context;
-}
-
-void CacheStorageManager::AddObserver(
- CacheStorageContextImpl::Observer* observer) {
- DCHECK(!observers_.HasObserver(observer));
- observers_.AddObserver(observer);
-}
-
-void CacheStorageManager::RemoveObserver(
- CacheStorageContextImpl::Observer* observer) {
- observers_.RemoveObserver(observer);
-}
-
-void CacheStorageManager::NotifyCacheListChanged(const url::Origin& origin) {
- for (auto& observer : observers_)
- observer.OnCacheListChanged(origin);
-}
-
-void CacheStorageManager::NotifyCacheContentChanged(const url::Origin& origin,
- const std::string& name) {
- for (auto& observer : observers_)
- observer.OnCacheContentChanged(origin, name);
-}
-
-void CacheStorageManager::CacheStorageUnreferenced(
- LegacyCacheStorage* cache_storage,
- const url::Origin& origin,
- CacheStorageOwner owner) {
- DCHECK(cache_storage);
- cache_storage->AssertUnreferenced();
- auto it = cache_storage_map_.find({origin, owner});
- DCHECK(it != cache_storage_map_.end());
- DCHECK(it->second.get() == cache_storage);
-
- // Currently we don't do anything when a CacheStorage instance becomes
- // unreferenced. In the future we will deallocate some or all of the
- // CacheStorage's state.
-}
-
// static
bool CacheStorageManager::IsValidQuotaOrigin(const url::Origin& origin) {
// Disallow opaque origins at the quota boundary because we DCHECK that we
@@ -261,225 +15,4 @@ bool CacheStorageManager::IsValidQuotaOrigin(const url::Origin& origin) {
return !origin.opaque();
}
-void CacheStorageManager::GetAllOriginsUsage(
- CacheStorageOwner owner,
- CacheStorageContext::GetUsageInfoCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- auto usages = std::make_unique<std::vector<StorageUsageInfo>>();
-
- if (IsMemoryBacked()) {
- for (const auto& origin_details : cache_storage_map_) {
- if (origin_details.first.second != owner)
- continue;
- usages->emplace_back(origin_details.first.first,
- /*total_size_bytes=*/0,
- /*last_modified=*/base::Time());
- }
- GetAllOriginsUsageGetSizes(std::move(usages), std::move(callback));
- return;
- }
-
- std::vector<StorageUsageInfo>* usages_ptr = usages.get();
- cache_task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(&ListOriginsAndLastModifiedOnTaskRunner, usages_ptr,
- root_path_, owner),
- base::BindOnce(&CacheStorageManager::GetAllOriginsUsageGetSizes,
- weak_ptr_factory_.GetWeakPtr(), std::move(usages),
- std::move(callback)));
-}
-
-void CacheStorageManager::GetAllOriginsUsageGetSizes(
- std::unique_ptr<std::vector<StorageUsageInfo>> usages,
- CacheStorageContext::GetUsageInfoCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(usages);
-
- // The origin GURL and last modified times are set in |usages| but not the
- // size in bytes. Call each CacheStorage's Size() function to fill that out.
- std::vector<StorageUsageInfo>* usages_ptr = usages.get();
-
- if (usages->empty()) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), *usages));
- return;
- }
-
- base::RepeatingClosure barrier_closure = base::BarrierClosure(
- usages_ptr->size(),
- base::BindOnce(&AllOriginSizesReported, std::move(usages),
- std::move(callback)));
-
- for (StorageUsageInfo& usage : *usages_ptr) {
- if (usage.total_size_bytes != CacheStorage::kSizeUnknown ||
- !IsValidQuotaOrigin(usage.origin)) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, barrier_closure);
- continue;
- }
- CacheStorageHandle cache_storage =
- OpenCacheStorage(usage.origin, CacheStorageOwner::kCacheAPI);
- LegacyCacheStorage::From(cache_storage)
- ->Size(base::BindOnce(&OneOriginSizeReported, barrier_closure, &usage));
- }
-}
-
-void CacheStorageManager::GetOriginUsage(
- const url::Origin& origin,
- CacheStorageOwner owner,
- storage::QuotaClient::GetUsageCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- CacheStorageHandle cache_storage = OpenCacheStorage(origin, owner);
- LegacyCacheStorage::From(cache_storage)->Size(std::move(callback));
-}
-
-void CacheStorageManager::GetOrigins(
- CacheStorageOwner owner,
- storage::QuotaClient::GetOriginsCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (IsMemoryBacked()) {
- std::set<url::Origin> origins;
- for (const auto& key_value : cache_storage_map_)
- if (key_value.first.second == owner)
- origins.insert(key_value.first.first);
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), origins));
- return;
- }
-
- PostTaskAndReplyWithResult(
- cache_task_runner_.get(), FROM_HERE,
- base::BindOnce(&ListOriginsOnTaskRunner, root_path_, owner),
- std::move(callback));
-}
-
-void CacheStorageManager::GetOriginsForHost(
- const std::string& host,
- CacheStorageOwner owner,
- storage::QuotaClient::GetOriginsCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (IsMemoryBacked()) {
- std::set<url::Origin> origins;
- for (const auto& key_value : cache_storage_map_) {
- if (key_value.first.second != owner)
- continue;
- if (host == net::GetHostOrSpecFromURL(key_value.first.first.GetURL()))
- origins.insert(key_value.first.first);
- }
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), origins));
- return;
- }
-
- PostTaskAndReplyWithResult(
- cache_task_runner_.get(), FROM_HERE,
- base::BindOnce(&ListOriginsOnTaskRunner, root_path_, owner),
- base::BindOnce(&GetOriginsForHostDidListOrigins, host,
- std::move(callback)));
-}
-
-void CacheStorageManager::DeleteOriginData(
- const url::Origin& origin,
- CacheStorageOwner owner,
- storage::QuotaClient::DeletionCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Create the CacheStorage for the origin if it hasn't been loaded yet.
- CacheStorageHandle handle = OpenCacheStorage(origin, owner);
-
- auto it = cache_storage_map_.find({origin, owner});
- DCHECK(it != cache_storage_map_.end());
-
- LegacyCacheStorage* cache_storage = it->second.release();
- cache_storage->ResetManager();
- cache_storage_map_.erase({origin, owner});
- cache_storage->GetSizeThenCloseAllCaches(
- base::BindOnce(&CacheStorageManager::DeleteOriginDidClose,
- weak_ptr_factory_.GetWeakPtr(), origin, owner,
- std::move(callback), base::WrapUnique(cache_storage)));
-}
-
-void CacheStorageManager::DeleteOriginData(const url::Origin& origin,
- CacheStorageOwner owner) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DeleteOriginData(origin, owner, base::DoNothing());
-}
-
-void CacheStorageManager::DeleteOriginDidClose(
- const url::Origin& origin,
- CacheStorageOwner owner,
- storage::QuotaClient::DeletionCallback callback,
- std::unique_ptr<LegacyCacheStorage> cache_storage,
- int64_t origin_size) {
- // TODO(jkarlin): Deleting the storage leaves any unfinished operations
- // hanging, resulting in unresolved promises. Fix this by returning early from
- // CacheStorage operations posted after GetSizeThenCloseAllCaches is called.
- cache_storage.reset();
-
- quota_manager_proxy_->NotifyStorageModified(
- CacheStorageQuotaClient::GetIDFromOwner(owner), origin,
- blink::mojom::StorageType::kTemporary, -1 * origin_size);
-
- if (owner == CacheStorageOwner::kCacheAPI)
- NotifyCacheListChanged(origin);
-
- if (IsMemoryBacked()) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback),
- blink::mojom::QuotaStatusCode::kOk));
- return;
- }
-
- PostTaskAndReplyWithResult(
- cache_task_runner_.get(), FROM_HERE,
- base::BindOnce(&DeleteDir,
- ConstructOriginPath(root_path_, origin, owner)),
- base::BindOnce(&DeleteOriginDidDeleteDir, std::move(callback)));
-}
-
-CacheStorageManager::CacheStorageManager(
- const base::FilePath& path,
- scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
- scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy)
- : root_path_(path),
- cache_task_runner_(std::move(cache_task_runner)),
- quota_manager_proxy_(std::move(quota_manager_proxy)),
- weak_ptr_factory_(this) {
- if (quota_manager_proxy_.get()) {
- quota_manager_proxy_->RegisterClient(new CacheStorageQuotaClient(
- weak_ptr_factory_.GetWeakPtr(), CacheStorageOwner::kCacheAPI));
- quota_manager_proxy_->RegisterClient(new CacheStorageQuotaClient(
- weak_ptr_factory_.GetWeakPtr(), CacheStorageOwner::kBackgroundFetch));
- }
-}
-
-// static
-base::FilePath CacheStorageManager::ConstructOriginPath(
- const base::FilePath& root_path,
- const url::Origin& origin,
- CacheStorageOwner owner) {
- std::string identifier = storage::GetIdentifierFromOrigin(origin);
- if (owner != CacheStorageOwner::kCacheAPI) {
- identifier += "-" + std::to_string(static_cast<int>(owner));
- }
- const std::string origin_hash = base::SHA1HashString(identifier);
- const std::string origin_hash_hex = base::ToLowerASCII(
- base::HexEncode(origin_hash.c_str(), origin_hash.length()));
- return root_path.AppendASCII(origin_hash_hex);
-}
-
-void CacheStorageManager::OnMemoryPressure(
- base::MemoryPressureListener::MemoryPressureLevel level) {
- if (level != base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL)
- return;
-
- for (auto& entry : cache_storage_map_) {
- entry.second->ReleaseUnreferencedCaches();
- }
-}
-
} // namespace content
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.h b/chromium/content/browser/cache_storage/cache_storage_manager.h
index c8ab8e63461..d5241d309c5 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.h
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.h
@@ -5,42 +5,27 @@
#ifndef CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_MANAGER_H_
#define CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_MANAGER_H_
-#include <map>
-#include <memory>
#include <string>
-#include <vector>
-#include "base/files/file_path.h"
#include "base/macros.h"
-#include "base/memory/memory_pressure_listener.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_refptr.h"
-#include "content/browser/cache_storage/cache_storage_context_impl.h"
-#include "content/browser/cache_storage/legacy/legacy_cache_storage.h"
+#include "content/browser/cache_storage/cache_storage_handle.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/storage_usage_info.h"
#include "storage/browser/quota/quota_client.h"
-#include "url/origin.h"
-
-namespace base {
-class SequencedTaskRunner;
-}
namespace storage {
class BlobStorageContext;
-class QuotaManagerProxy;
}
-namespace content {
-
-class CacheStorageQuotaClient;
-
-namespace cache_storage_manager_unittest {
-class CacheStorageManagerTest;
+namespace url {
+class Origin;
}
+namespace content {
+
enum class CacheStorageOwner {
kMinValue,
@@ -61,125 +46,45 @@ class CONTENT_EXPORT CacheStorageManager
: public base::RefCountedThreadSafe<CacheStorageManager,
BrowserThread::DeleteOnIOThread> {
public:
- static scoped_refptr<CacheStorageManager> Create(
- const base::FilePath& path,
- scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
- scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
-
- static scoped_refptr<CacheStorageManager> Create(
- CacheStorageManager* old_manager);
-
- // Map a database identifier (computed from an origin) to the path.
- static base::FilePath ConstructOriginPath(const base::FilePath& root_path,
- const url::Origin& origin,
- CacheStorageOwner owner);
-
// Open the CacheStorage for the given origin and owner. A reference counting
// handle is returned which can be stored and used similar to a weak pointer.
- CacheStorageHandle OpenCacheStorage(const url::Origin& origin,
- CacheStorageOwner owner);
-
- // This must be called before creating any of the public *Cache functions
- // above.
- void SetBlobParametersForCache(
- base::WeakPtr<storage::BlobStorageContext> blob_storage_context);
-
- void AddObserver(CacheStorageContextImpl::Observer* observer);
- void RemoveObserver(CacheStorageContextImpl::Observer* observer);
-
- void NotifyCacheListChanged(const url::Origin& origin);
- void NotifyCacheContentChanged(const url::Origin& origin,
- const std::string& name);
-
- base::WeakPtr<CacheStorageManager> AsWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
-
- base::FilePath root_path() const { return root_path_; }
-
- // This method is called when the last CacheStorageHandle for a particular
- // instance is destroyed and its reference count drops to zero.
- void CacheStorageUnreferenced(LegacyCacheStorage* cache_storage,
- const url::Origin& origin,
- CacheStorageOwner owner);
+ virtual CacheStorageHandle OpenCacheStorage(const url::Origin& origin,
+ CacheStorageOwner owner) = 0;
+
+ // QuotaClient and Browsing Data Deletion support.
+ virtual void GetAllOriginsUsage(
+ CacheStorageOwner owner,
+ CacheStorageContext::GetUsageInfoCallback callback) = 0;
+ virtual void GetOriginUsage(
+ const url::Origin& origin_url,
+ CacheStorageOwner owner,
+ storage::QuotaClient::GetUsageCallback callback) = 0;
+ virtual void GetOrigins(
+ CacheStorageOwner owner,
+ storage::QuotaClient::GetOriginsCallback callback) = 0;
+ virtual void GetOriginsForHost(
+ const std::string& host,
+ CacheStorageOwner owner,
+ storage::QuotaClient::GetOriginsCallback callback) = 0;
+ virtual void DeleteOriginData(
+ const url::Origin& origin,
+ CacheStorageOwner owner,
+ storage::QuotaClient::DeletionCallback callback) = 0;
+ virtual void DeleteOriginData(const url::Origin& origin,
+ CacheStorageOwner owner) = 0;
+
+ // This must be called before any of the public Cache functions above.
+ virtual void SetBlobParametersForCache(
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context) = 0;
static bool IsValidQuotaOrigin(const url::Origin& origin);
- private:
+ protected:
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<LegacyCacheStorage>>
- CacheStorageMap;
-
- CacheStorageManager(
- const base::FilePath& path,
- scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
- scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
-
- virtual ~CacheStorageManager();
-
- // QuotaClient and Browsing Data Deletion support
- void GetAllOriginsUsage(CacheStorageOwner owner,
- CacheStorageContext::GetUsageInfoCallback callback);
- void GetAllOriginsUsageGetSizes(
- std::unique_ptr<std::vector<StorageUsageInfo>> usage_info,
- CacheStorageContext::GetUsageInfoCallback callback);
-
- void GetOriginUsage(const url::Origin& origin_url,
- CacheStorageOwner owner,
- storage::QuotaClient::GetUsageCallback callback);
- void GetOrigins(CacheStorageOwner owner,
- storage::QuotaClient::GetOriginsCallback callback);
- void GetOriginsForHost(const std::string& host,
- CacheStorageOwner owner,
- storage::QuotaClient::GetOriginsCallback callback);
- void DeleteOriginData(const url::Origin& origin,
- CacheStorageOwner owner,
- storage::QuotaClient::DeletionCallback callback);
- void DeleteOriginData(const url::Origin& origin, CacheStorageOwner owner);
- void DeleteOriginDidClose(const url::Origin& origin,
- CacheStorageOwner owner,
- storage::QuotaClient::DeletionCallback callback,
- std::unique_ptr<LegacyCacheStorage> cache_storage,
- int64_t origin_size);
-
- base::WeakPtr<storage::BlobStorageContext> blob_storage_context() const {
- return blob_context_;
- }
-
- scoped_refptr<base::SequencedTaskRunner> cache_task_runner() const {
- return cache_task_runner_;
- }
-
- bool IsMemoryBacked() const { return root_path_.empty(); }
-
- // MemoryPressureListener callback
- void OnMemoryPressure(
- base::MemoryPressureListener::MemoryPressureLevel level);
-
- base::FilePath root_path_;
- scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
-
- scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
-
- // The map owns the CacheStorages and the CacheStorages are only accessed on
- // |cache_task_runner_|.
- CacheStorageMap cache_storage_map_;
-
- base::ObserverList<CacheStorageContextImpl::Observer>::Unchecked observers_;
-
- base::WeakPtr<storage::BlobStorageContext> blob_context_;
-
- std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
-
- base::WeakPtrFactory<CacheStorageManager> weak_ptr_factory_;
- DISALLOW_COPY_AND_ASSIGN(CacheStorageManager);
+ virtual ~CacheStorageManager() = default;
};
} // namespace content
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 26d6aaba339..427e4b93936 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/cache_storage/cache_storage_manager.h"
-
#include <stddef.h>
#include <stdint.h>
@@ -26,12 +24,15 @@
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/browser/cache_storage/cache_storage.h"
#include "content/browser/cache_storage/cache_storage.pb.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_quota_client.h"
+#include "content/browser/cache_storage/cache_storage_scheduler.h"
+#include "content/browser/cache_storage/legacy/legacy_cache_storage.h"
+#include "content/browser/cache_storage/legacy/legacy_cache_storage_manager.h"
#include "content/common/background_fetch/background_fetch_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
@@ -41,9 +42,6 @@
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "net/disk_cache/disk_cache.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_job_factory_impl.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_data_handle.h"
@@ -123,6 +121,32 @@ class DelayedBlob : public storage::FakeBlob {
bool paused_ = true;
};
+// Scheduler implementation that will invoke a callback after the
+// next operation has been started.
+class CallbackScheduler : public CacheStorageScheduler {
+ public:
+ explicit CallbackScheduler(base::OnceClosure callback)
+ : CacheStorageScheduler(CacheStorageSchedulerClient::kCache,
+ base::ThreadTaskRunnerHandle::Get()),
+ callback_(std::move(callback)) {}
+
+ protected:
+ void DispatchOperationTask(base::OnceClosure task) override {
+ auto wrapped = base::BindOnce(&CallbackScheduler::ExecuteTask,
+ base::Unretained(this), std::move(task));
+ CacheStorageScheduler::DispatchOperationTask(std::move(wrapped));
+ }
+
+ private:
+ void ExecuteTask(base::OnceClosure task) {
+ std::move(task).Run();
+ if (callback_)
+ std::move(callback_).Run();
+ }
+
+ base::OnceClosure callback_;
+};
+
class MockCacheStorageQuotaManagerProxy : public MockQuotaManagerProxy {
public:
MockCacheStorageQuotaManagerProxy(MockQuotaManager* quota_manager,
@@ -171,32 +195,38 @@ bool IsIndexFileCurrent(const base::FilePath& cache_dir) {
class TestCacheStorageObserver : public CacheStorageContextImpl::Observer {
public:
+ TestCacheStorageObserver() : loop_(std::make_unique<base::RunLoop>()) {}
+
void OnCacheListChanged(const url::Origin& origin) override {
++notify_list_changed_count;
+ loop_->Quit();
}
void OnCacheContentChanged(const url::Origin& origin,
const std::string& cache_name) override {
++notify_content_changed_count;
+ loop_->Quit();
}
+ void Wait() {
+ loop_->Run();
+ loop_ = std::make_unique<base::RunLoop>();
+ }
+
+ base::OnceClosure callback;
int notify_list_changed_count = 0;
int notify_content_changed_count = 0;
-};
-// Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
-// the memory.
-std::unique_ptr<storage::BlobProtocolHandler> CreateMockBlobProtocolHandler(
- storage::BlobStorageContext* blob_storage_context) {
- return base::WrapUnique(
- new storage::BlobProtocolHandler(blob_storage_context));
-}
+ std::unique_ptr<base::RunLoop> loop_;
+};
class CacheStorageManagerTest : public testing::Test {
public:
CacheStorageManagerTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
blob_storage_context_(nullptr),
+ observers_(
+ base::MakeRefCounted<CacheStorageContextImpl::ObserverList>()),
callback_bool_(false),
callback_error_(CacheStorageError::kSuccess),
origin1_(url::Origin::Create(GURL("http://example1.com"))),
@@ -275,6 +305,13 @@ class CacheStorageManagerTest : public testing::Test {
run_loop->Quit();
}
+ void CacheMatchAllCallback(base::RunLoop* run_loop,
+ CacheStorageError error,
+ std::vector<blink::mojom::FetchAPIResponsePtr>) {
+ callback_error_ = error;
+ run_loop->Quit();
+ }
+
void CreateStorageManager() {
ChromeBlobStorageContext* blob_storage_context(
ChromeBlobStorageContext::GetFor(&browser_context_));
@@ -283,16 +320,6 @@ class CacheStorageManagerTest : public testing::Test {
blob_storage_context_ = blob_storage_context->context();
- url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
- url_request_job_factory_->SetProtocolHandler(
- "blob", CreateMockBlobProtocolHandler(blob_storage_context->context()));
-
- net::URLRequestContext* url_request_context =
- BrowserContext::GetDefaultStoragePartition(&browser_context_)->
- GetURLRequestContext()->GetURLRequestContext();
-
- url_request_context->set_job_factory(url_request_job_factory_.get());
-
base::FilePath temp_dir_path;
if (!MemoryOnly())
temp_dir_path = temp_dir_.GetPath();
@@ -309,9 +336,9 @@ class CacheStorageManagerTest : public testing::Test {
quota_manager_proxy_ = new MockCacheStorageQuotaManagerProxy(
mock_quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
- cache_manager_ = CacheStorageManager::Create(
+ cache_manager_ = LegacyCacheStorageManager::Create(
temp_dir_path, base::ThreadTaskRunnerHandle::Get(),
- quota_manager_proxy_);
+ base::ThreadTaskRunnerHandle::Get(), quota_manager_proxy_, observers_);
cache_manager_->SetBlobParametersForCache(
blob_storage_context->context()->AsWeakPtr());
@@ -342,7 +369,6 @@ class CacheStorageManagerTest : public testing::Test {
base::RunLoop().RunUntilIdle();
quota_manager_proxy_ = nullptr;
- url_request_job_factory_.reset();
blob_storage_context_ = nullptr;
quota_policy_ = nullptr;
@@ -715,13 +741,13 @@ class CacheStorageManagerTest : public testing::Test {
TestBrowserThreadBundle browser_thread_bundle_;
TestBrowserContext browser_context_;
- std::unique_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
storage::BlobStorageContext* blob_storage_context_;
scoped_refptr<MockSpecialStoragePolicy> quota_policy_;
scoped_refptr<MockQuotaManager> mock_quota_manager_;
scoped_refptr<MockCacheStorageQuotaManagerProxy> quota_manager_proxy_;
- scoped_refptr<CacheStorageManager> cache_manager_;
+ scoped_refptr<CacheStorageContextImpl::ObserverList> observers_;
+ scoped_refptr<LegacyCacheStorageManager> cache_manager_;
CacheStorageCacheHandle callback_cache_handle_;
int callback_bool_;
@@ -1058,7 +1084,8 @@ TEST_F(CacheStorageManagerTest, DataPersists) {
EXPECT_TRUE(Open(origin2_, "raz"));
EXPECT_TRUE(Delete(origin1_, "bar"));
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
- cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
+ cache_manager_ =
+ LegacyCacheStorageManager::CreateForTesting(cache_manager_.get());
EXPECT_EQ(2u, Keys(origin1_));
std::vector<std::string> expected_keys;
expected_keys.push_back("foo");
@@ -1070,7 +1097,8 @@ TEST_F(CacheStorageManagerMemoryOnlyTest, DataLostWhenMemoryOnly) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Open(origin2_, "baz"));
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
- cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
+ cache_manager_ =
+ LegacyCacheStorageManager::CreateForTesting(cache_manager_.get());
EXPECT_EQ(0u, Keys(origin1_));
}
@@ -1179,6 +1207,40 @@ TEST_F(CacheStorageManagerTest, DropReferenceAndMemoryPressure) {
<< "unreferenced cache not destroyed on critical memory pressure";
}
+TEST_F(CacheStorageManagerTest, DropReferenceDuringQuery) {
+ // Setup the cache and execute an operation to make sure all initialization
+ // is complete.
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ base::WeakPtr<LegacyCacheStorageCache> cache =
+ LegacyCacheStorageCache::From(callback_cache_handle_)->AsWeakPtr();
+ EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(),
+ GURL("http://example.com/foo")));
+
+ // Override the cache scheduler so that we can take an action below
+ // after the query operation begins.
+ base::RunLoop scheduler_loop;
+ auto scheduler =
+ std::make_unique<CallbackScheduler>(scheduler_loop.QuitClosure());
+ cache->SetSchedulerForTesting(std::move(scheduler));
+
+ // Perform a MatchAll() operation to trigger a full query of the cache
+ // that does not hit the fast path optimization.
+ base::RunLoop match_loop;
+ cache->MatchAll(
+ nullptr, nullptr, /* trace_id = */ 0,
+ base::BindOnce(&CacheStorageManagerTest::CacheMatchAllCallback,
+ base::Unretained(this), base::Unretained(&match_loop)));
+
+ // Wait for the MatchAll operation to begin.
+ scheduler_loop.Run();
+
+ // Clear the external cache handle.
+ callback_cache_handle_ = CacheStorageCacheHandle();
+
+ // Wait for the MatchAll operation to complete as expected.
+ match_loop.Run();
+ EXPECT_EQ(CacheStorageError::kSuccess, callback_error_);
+}
// A cache continues to work so long as there is a handle to it. Only after the
// last cache handle is deleted can the cache be freed.
TEST_P(CacheStorageManagerTestP, CacheWorksAfterDelete) {
@@ -1337,7 +1399,8 @@ TEST_F(CacheStorageManagerTest, CacheSizePaddedAfterReopen) {
// Create a new CacheStorageManager that hasn't yet loaded the origin.
CreateStorageManager();
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
- cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
+ cache_manager_ =
+ LegacyCacheStorageManager::CreateForTesting(cache_manager_.get());
EXPECT_TRUE(Open(origin1_, kCacheName));
base::RunLoop().RunUntilIdle();
@@ -1409,7 +1472,8 @@ TEST_F(CacheStorageManagerTest, PersistedCacheKeyUsed) {
// Create a new CacheStorageManager that hasn't yet loaded the origin.
CreateStorageManager();
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
- cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
+ cache_manager_ =
+ LegacyCacheStorageManager::CreateForTesting(cache_manager_.get());
// Reopening the origin/cache creates a new CacheStorage instance with a new
// random key.
@@ -1569,7 +1633,13 @@ TEST_P(CacheStorageManagerTestP, GetAllOriginsUsageDifferentOwners) {
}
}
-TEST_F(CacheStorageManagerTest, GetAllOriginsUsageWithOldIndex) {
+// TODO(crbug.com/760687): Flaky on Fuchsia.
+#if defined(OS_FUCHSIA)
+#define MAYBE_GetAllOriginsUsageWithOldIndex DISABLED_GetAllOriginsUsageWithOldIndex
+#else
+#define MAYBE_GetAllOriginsUsageWithOldIndex GetAllOriginsUsageWithOldIndex
+#endif
+TEST_F(CacheStorageManagerTest, MAYBE_GetAllOriginsUsageWithOldIndex) {
// Write a single value (V1) to the cache.
const GURL kFooURL = origin1_.GetURL().Resolve("foo");
const std::string kCacheName = "foo";
@@ -1597,7 +1667,8 @@ TEST_F(CacheStorageManagerTest, GetAllOriginsUsageWithOldIndex) {
// Create a new CacheStorageManager that hasn't yet loaded the origin.
CreateStorageManager();
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
- cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
+ cache_manager_ =
+ LegacyCacheStorageManager::CreateForTesting(cache_manager_.get());
// Create a second value (V2) in the cache.
EXPECT_TRUE(Open(origin1_, kCacheName));
@@ -1631,7 +1702,13 @@ TEST_F(CacheStorageManagerTest, GetAllOriginsUsageWithOldIndex) {
EXPECT_FALSE(usage[0].last_modified.is_null());
}
-TEST_F(CacheStorageManagerTest, GetOriginSizeWithOldIndex) {
+// TODO(crbug.com/760687): Flaky on Fuchsia.
+#if defined(OS_FUCHSIA)
+#define MAYBE_GetOriginSizeWithOldIndex DISABLED_GetOriginSizeWithOldIndex
+#else
+#define MAYBE_GetOriginSizeWithOldIndex GetOriginSizeWithOldIndex
+#endif
+TEST_F(CacheStorageManagerTest, MAYBE_GetOriginSizeWithOldIndex) {
// Write a single value (V1) to the cache.
const GURL kFooURL = origin1_.GetURL().Resolve("foo");
const std::string kCacheName = "foo";
@@ -1659,7 +1736,8 @@ TEST_F(CacheStorageManagerTest, GetOriginSizeWithOldIndex) {
// Create a new CacheStorageManager that hasn't yet loaded the origin.
CreateStorageManager();
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
- cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
+ cache_manager_ =
+ LegacyCacheStorageManager::CreateForTesting(cache_manager_.get());
// Reopen the cache and write a second value (V2).
EXPECT_TRUE(Open(origin1_, kCacheName));
@@ -1752,7 +1830,7 @@ TEST_F(CacheStorageManagerTest, DeleteUnreferencedCacheDirectories) {
CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
// Create an unreferenced directory next to the referenced one.
- base::FilePath origin_path = CacheStorageManager::ConstructOriginPath(
+ base::FilePath origin_path = LegacyCacheStorageManager::ConstructOriginPath(
cache_manager_->root_path(), origin1_, CacheStorageOwner::kCacheAPI);
base::FilePath unreferenced_path = origin_path.AppendASCII("bar");
EXPECT_TRUE(CreateDirectory(unreferenced_path));
@@ -1761,7 +1839,8 @@ TEST_F(CacheStorageManagerTest, DeleteUnreferencedCacheDirectories) {
// Create a new StorageManager so that the next time the cache is opened
// the unreferenced directory can be deleted.
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
- cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
+ cache_manager_ =
+ LegacyCacheStorageManager::CreateForTesting(cache_manager_.get());
// Verify that the referenced cache still works.
EXPECT_TRUE(Open(origin1_, "foo"));
@@ -1824,97 +1903,121 @@ TEST_P(CacheStorageManagerTestP, SizeThenCloseStorageAccessed) {
TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_Created) {
TestCacheStorageObserver observer;
- cache_manager_->AddObserver(&observer);
+ observers_->AddObserver(&observer);
EXPECT_EQ(0, observer.notify_list_changed_count);
EXPECT_TRUE(Open(origin1_, "foo"));
+ observer.Wait();
EXPECT_EQ(1, observer.notify_list_changed_count);
EXPECT_TRUE(
CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
+ observer.Wait();
EXPECT_EQ(1, observer.notify_list_changed_count);
}
TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_Deleted) {
TestCacheStorageObserver observer;
- cache_manager_->AddObserver(&observer);
+ observers_->AddObserver(&observer);
EXPECT_EQ(0, observer.notify_list_changed_count);
EXPECT_FALSE(Delete(origin1_, "foo"));
+ // Give any unexpected observer tasks a chance to run.
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, observer.notify_list_changed_count);
EXPECT_TRUE(Open(origin1_, "foo"));
+ observer.Wait();
EXPECT_EQ(1, observer.notify_list_changed_count);
EXPECT_TRUE(Delete(origin1_, "foo"));
+ observer.Wait();
EXPECT_EQ(2, observer.notify_list_changed_count);
}
TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_DeletedThenCreated) {
TestCacheStorageObserver observer;
- cache_manager_->AddObserver(&observer);
+ observers_->AddObserver(&observer);
EXPECT_EQ(0, observer.notify_list_changed_count);
EXPECT_TRUE(Open(origin1_, "foo"));
+ observer.Wait();
EXPECT_EQ(1, observer.notify_list_changed_count);
EXPECT_TRUE(Delete(origin1_, "foo"));
+ observer.Wait();
EXPECT_EQ(2, observer.notify_list_changed_count);
EXPECT_TRUE(Open(origin2_, "foo2"));
+ observer.Wait();
EXPECT_EQ(3, observer.notify_list_changed_count);
}
TEST_P(CacheStorageManagerTestP, NotifyCacheContentChanged_PutEntry) {
TestCacheStorageObserver observer;
- cache_manager_->AddObserver(&observer);
+ observers_->AddObserver(&observer);
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_TRUE(Open(origin1_, "foo"));
+ observer.Wait();
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_TRUE(
CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
+ observer.Wait();
EXPECT_EQ(1, observer.notify_content_changed_count);
EXPECT_TRUE(CachePut(callback_cache_handle_.value(),
GURL("http://example.com/foo1")));
+ observer.Wait();
EXPECT_TRUE(CachePut(callback_cache_handle_.value(),
GURL("http://example.com/foo2")));
+ observer.Wait();
EXPECT_EQ(3, observer.notify_content_changed_count);
}
TEST_P(CacheStorageManagerTestP, NotifyCacheContentChanged_DeleteEntry) {
TestCacheStorageObserver observer;
- cache_manager_->AddObserver(&observer);
+ observers_->AddObserver(&observer);
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_FALSE(Delete(origin1_, "foo"));
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_TRUE(Open(origin1_, "foo"));
+ observer.Wait();
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_TRUE(
CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
+ observer.Wait();
EXPECT_EQ(1, observer.notify_content_changed_count);
EXPECT_TRUE(CacheDelete(callback_cache_handle_.value(),
GURL("http://example.com/foo")));
+ observer.Wait();
EXPECT_EQ(2, observer.notify_content_changed_count);
EXPECT_FALSE(CacheDelete(callback_cache_handle_.value(),
GURL("http://example.com/foo")));
+ // Give any unexpected observer tasks a chance to run.
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, observer.notify_content_changed_count);
}
TEST_P(CacheStorageManagerTestP, NotifyCacheContentChanged_DeleteThenPutEntry) {
TestCacheStorageObserver observer;
- cache_manager_->AddObserver(&observer);
+ observers_->AddObserver(&observer);
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_TRUE(Open(origin1_, "foo"));
+ observer.Wait();
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_TRUE(
CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
+ observer.Wait();
EXPECT_EQ(1, observer.notify_content_changed_count);
EXPECT_TRUE(CacheDelete(callback_cache_handle_.value(),
GURL("http://example.com/foo")));
+ observer.Wait();
EXPECT_EQ(2, observer.notify_content_changed_count);
EXPECT_TRUE(
CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
+ observer.Wait();
EXPECT_EQ(3, observer.notify_content_changed_count);
EXPECT_TRUE(CacheDelete(callback_cache_handle_.value(),
GURL("http://example.com/foo")));
+ observer.Wait();
EXPECT_EQ(4, observer.notify_content_changed_count);
}
@@ -2327,7 +2430,8 @@ TEST_F(CacheStorageQuotaClientDiskOnlyTest, QuotaDeleteUnloadedOriginData) {
// Create a new CacheStorageManager that hasn't yet loaded the origin.
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
- cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
+ cache_manager_ =
+ LegacyCacheStorageManager::CreateForTesting(cache_manager_.get());
quota_client_.reset(new CacheStorageQuotaClient(
cache_manager_->AsWeakPtr(), CacheStorageOwner::kCacheAPI));
diff --git a/chromium/content/browser/cache_storage/cache_storage_operation.cc b/chromium/content/browser/cache_storage/cache_storage_operation.cc
index 98362a748aa..01bde84af52 100644
--- a/chromium/content/browser/cache_storage/cache_storage_operation.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_operation.cc
@@ -16,7 +16,7 @@ CacheStorageOperation::CacheStorageOperation(
base::OnceClosure closure,
CacheStorageSchedulerClient client_type,
CacheStorageSchedulerOp op_type,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
: closure_(std::move(closure)),
creation_ticks_(base::TimeTicks::Now()),
client_type_(client_type),
diff --git a/chromium/content/browser/cache_storage/cache_storage_operation.h b/chromium/content/browser/cache_storage/cache_storage_operation.h
index 0c893251902..cf101328812 100644
--- a/chromium/content/browser/cache_storage/cache_storage_operation.h
+++ b/chromium/content/browser/cache_storage/cache_storage_operation.h
@@ -9,7 +9,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
+#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
#include "content/browser/cache_storage/cache_storage_scheduler_types.h"
#include "content/common/content_export.h"
@@ -20,11 +20,10 @@ namespace content {
// to run plus a bunch of metrics data.
class CONTENT_EXPORT CacheStorageOperation {
public:
- CacheStorageOperation(
- base::OnceClosure closure,
- CacheStorageSchedulerClient client_type,
- CacheStorageSchedulerOp op_type,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ CacheStorageOperation(base::OnceClosure closure,
+ CacheStorageSchedulerClient client_type,
+ CacheStorageSchedulerOp op_type,
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
~CacheStorageOperation();
@@ -54,7 +53,7 @@ class CONTENT_EXPORT CacheStorageOperation {
const CacheStorageSchedulerClient client_type_;
const CacheStorageSchedulerOp op_type_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
base::WeakPtrFactory<CacheStorageOperation> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CacheStorageOperation);
diff --git a/chromium/content/browser/cache_storage/cache_storage_scheduler.cc b/chromium/content/browser/cache_storage/cache_storage_scheduler.cc
index c6486756144..0a0f31d4e64 100644
--- a/chromium/content/browser/cache_storage/cache_storage_scheduler.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_scheduler.cc
@@ -10,16 +10,18 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/sequenced_task_runner.h"
#include "content/browser/cache_storage/cache_storage_histogram_utils.h"
#include "content/browser/cache_storage/cache_storage_operation.h"
namespace content {
CacheStorageScheduler::CacheStorageScheduler(
- CacheStorageSchedulerClient client_type)
- : client_type_(client_type), weak_ptr_factory_(this) {}
+ CacheStorageSchedulerClient client_type,
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : task_runner_(std::move(task_runner)),
+ client_type_(client_type),
+ weak_ptr_factory_(this) {}
CacheStorageScheduler::~CacheStorageScheduler() {}
@@ -30,8 +32,7 @@ void CacheStorageScheduler::ScheduleOperation(CacheStorageSchedulerOp op_type,
pending_operations_.size());
pending_operations_.push_back(std::make_unique<CacheStorageOperation>(
- std::move(closure), client_type_, op_type,
- base::ThreadTaskRunnerHandle::Get()));
+ std::move(closure), client_type_, op_type, task_runner_));
RunOperationIfIdle();
}
@@ -46,6 +47,10 @@ bool CacheStorageScheduler::ScheduledOperations() const {
return running_operation_ || !pending_operations_.empty();
}
+void CacheStorageScheduler::DispatchOperationTask(base::OnceClosure task) {
+ task_runner_->PostTask(FROM_HERE, std::move(task));
+}
+
void CacheStorageScheduler::RunOperationIfIdle() {
if (!running_operation_ && !pending_operations_.empty()) {
// TODO(jkarlin): Run multiple operations in parallel where allowed.
@@ -57,9 +62,8 @@ void CacheStorageScheduler::RunOperationIfIdle() {
running_operation_->op_type(),
base::TimeTicks::Now() - running_operation_->creation_ticks());
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&CacheStorageOperation::Run,
- running_operation_->AsWeakPtr()));
+ DispatchOperationTask(base::BindOnce(&CacheStorageOperation::Run,
+ running_operation_->AsWeakPtr()));
}
}
diff --git a/chromium/content/browser/cache_storage/cache_storage_scheduler.h b/chromium/content/browser/cache_storage/cache_storage_scheduler.h
index 416d160cda5..3f0fbf73834 100644
--- a/chromium/content/browser/cache_storage/cache_storage_scheduler.h
+++ b/chromium/content/browser/cache_storage/cache_storage_scheduler.h
@@ -29,7 +29,8 @@ class CacheStorageOperation;
// the next operation.
class CONTENT_EXPORT CacheStorageScheduler {
public:
- explicit CacheStorageScheduler(CacheStorageSchedulerClient client_type);
+ CacheStorageScheduler(CacheStorageSchedulerClient client_type,
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
virtual ~CacheStorageScheduler();
// Adds the operation to the tail of the queue and starts it if the scheduler
@@ -52,6 +53,10 @@ class CONTENT_EXPORT CacheStorageScheduler {
weak_ptr_factory_.GetWeakPtr(), std::move(callback));
}
+ protected:
+ // virtual for testing
+ virtual void DispatchOperationTask(base::OnceClosure task);
+
private:
void RunOperationIfIdle();
@@ -68,9 +73,10 @@ class CONTENT_EXPORT CacheStorageScheduler {
CompleteOperationAndRunNext();
}
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::list<std::unique_ptr<CacheStorageOperation>> pending_operations_;
std::unique_ptr<CacheStorageOperation> running_operation_;
- CacheStorageSchedulerClient client_type_;
+ const CacheStorageSchedulerClient client_type_;
base::WeakPtrFactory<CacheStorageScheduler> weak_ptr_factory_;
diff --git a/chromium/content/browser/cache_storage/cache_storage_scheduler_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_scheduler_unittest.cc
index 50918cfbd07..3afaf4c99fc 100644
--- a/chromium/content/browser/cache_storage/cache_storage_scheduler_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_scheduler_unittest.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/run_loop.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -32,7 +33,8 @@ class CacheStorageSchedulerTest : public testing::Test {
protected:
CacheStorageSchedulerTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
- scheduler_(CacheStorageSchedulerClient::kStorage),
+ scheduler_(CacheStorageSchedulerClient::kStorage,
+ base::ThreadTaskRunnerHandle::Get()),
task1_(TestTask(&scheduler_)),
task2_(TestTask(&scheduler_)) {}
diff --git a/chromium/content/browser/cache_storage/legacy/legacy_cache_storage.cc b/chromium/content/browser/cache_storage/legacy/legacy_cache_storage.cc
index 75ba7c3f163..f91df0d1bc5 100644
--- a/chromium/content/browser/cache_storage/legacy/legacy_cache_storage.cc
+++ b/chromium/content/browser/cache_storage/legacy/legacy_cache_storage.cc
@@ -35,10 +35,10 @@
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_histogram_utils.h"
#include "content/browser/cache_storage/cache_storage_index.h"
-#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/cache_storage/cache_storage_quota_client.h"
#include "content/browser/cache_storage/cache_storage_scheduler.h"
#include "content/browser/cache_storage/cache_storage_trace_utils.h"
+#include "content/browser/cache_storage/legacy/legacy_cache_storage_manager.h"
#include "content/common/background_fetch/background_fetch_types.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/symmetric_key.h"
@@ -93,12 +93,14 @@ class LegacyCacheStorage::CacheLoader {
base::OnceCallback<void(std::unique_ptr<CacheStorageIndex>)>;
CacheLoader(base::SequencedTaskRunner* cache_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
LegacyCacheStorage* cache_storage,
const url::Origin& origin,
CacheStorageOwner owner)
: cache_task_runner_(cache_task_runner),
+ scheduler_task_runner_(std::move(scheduler_task_runner)),
quota_manager_proxy_(quota_manager_proxy),
blob_context_(blob_context),
cache_storage_(cache_storage),
@@ -142,7 +144,8 @@ class LegacyCacheStorage::CacheLoader {
virtual void NotifyCacheDoomed(CacheStorageCacheHandle cache_handle) {}
protected:
- scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
+ const scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
+ const scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner_;
// Owned by CacheStorage which owns this.
storage::QuotaManagerProxy* quota_manager_proxy_;
@@ -164,12 +167,14 @@ class LegacyCacheStorage::MemoryLoader
: public LegacyCacheStorage::CacheLoader {
public:
MemoryLoader(base::SequencedTaskRunner* cache_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
LegacyCacheStorage* cache_storage,
const url::Origin& origin,
CacheStorageOwner owner)
: CacheLoader(cache_task_runner,
+ std::move(scheduler_task_runner),
quota_manager_proxy,
blob_context,
cache_storage,
@@ -182,8 +187,8 @@ class LegacyCacheStorage::MemoryLoader
int64_t cache_padding,
std::unique_ptr<SymmetricKey> cache_padding_key) override {
return LegacyCacheStorageCache::CreateMemoryCache(
- origin_, owner_, cache_name, cache_storage_, quota_manager_proxy_,
- blob_context_, storage::CopyDefaultPaddingKey());
+ origin_, owner_, cache_name, cache_storage_, scheduler_task_runner_,
+ quota_manager_proxy_, blob_context_, storage::CopyDefaultPaddingKey());
}
void PrepareNewCacheDestination(const std::string& cache_name,
@@ -230,14 +235,17 @@ class LegacyCacheStorage::MemoryLoader
class LegacyCacheStorage::SimpleCacheLoader
: public LegacyCacheStorage::CacheLoader {
public:
- SimpleCacheLoader(const base::FilePath& origin_path,
- base::SequencedTaskRunner* cache_task_runner,
- storage::QuotaManagerProxy* quota_manager_proxy,
- base::WeakPtr<storage::BlobStorageContext> blob_context,
- LegacyCacheStorage* cache_storage,
- const url::Origin& origin,
- CacheStorageOwner owner)
+ SimpleCacheLoader(
+ const base::FilePath& origin_path,
+ base::SequencedTaskRunner* cache_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context,
+ LegacyCacheStorage* cache_storage,
+ const url::Origin& origin,
+ CacheStorageOwner owner)
: CacheLoader(cache_task_runner,
+ std::move(scheduler_task_runner),
quota_manager_proxy,
blob_context,
cache_storage,
@@ -258,8 +266,8 @@ class LegacyCacheStorage::SimpleCacheLoader
base::FilePath cache_path = origin_path_.AppendASCII(cache_dir);
return LegacyCacheStorageCache::CreatePersistentCache(
origin_, owner_, cache_name, cache_storage_, cache_path,
- quota_manager_proxy_, blob_context_, cache_size, cache_padding,
- std::move(cache_padding_key));
+ scheduler_task_runner_, quota_manager_proxy_, blob_context_, cache_size,
+ cache_padding, std::move(cache_padding_key));
}
void PrepareNewCacheDestination(const std::string& cache_name,
@@ -548,9 +556,10 @@ LegacyCacheStorage::LegacyCacheStorage(
const base::FilePath& path,
bool memory_only,
base::SequencedTaskRunner* cache_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
- CacheStorageManager* cache_storage_manager,
+ LegacyCacheStorageManager* cache_storage_manager,
const url::Origin& origin,
CacheStorageOwner owner)
: CacheStorage(origin),
@@ -558,7 +567,8 @@ LegacyCacheStorage::LegacyCacheStorage(
initializing_(false),
memory_only_(memory_only),
scheduler_(
- new CacheStorageScheduler(CacheStorageSchedulerClient::kStorage)),
+ new CacheStorageScheduler(CacheStorageSchedulerClient::kStorage,
+ scheduler_task_runner)),
origin_path_(path),
cache_task_runner_(cache_task_runner),
quota_manager_proxy_(quota_manager_proxy),
@@ -566,12 +576,13 @@ LegacyCacheStorage::LegacyCacheStorage(
cache_storage_manager_(cache_storage_manager),
weak_factory_(this) {
if (memory_only)
- cache_loader_.reset(new MemoryLoader(cache_task_runner_.get(),
- quota_manager_proxy.get(),
- blob_context, this, origin, owner));
+ cache_loader_.reset(new MemoryLoader(
+ cache_task_runner_.get(), std::move(scheduler_task_runner),
+ quota_manager_proxy.get(), blob_context, this, origin, owner));
else
cache_loader_.reset(new SimpleCacheLoader(
- origin_path_, cache_task_runner_.get(), quota_manager_proxy.get(),
+ origin_path_, cache_task_runner_.get(),
+ std::move(scheduler_task_runner), quota_manager_proxy.get(),
blob_context, this, origin, owner));
}
diff --git a/chromium/content/browser/cache_storage/legacy/legacy_cache_storage.h b/chromium/content/browser/cache_storage/legacy/legacy_cache_storage.h
index fdb21f76518..09f3fa6864c 100644
--- a/chromium/content/browser/cache_storage/legacy/legacy_cache_storage.h
+++ b/chromium/content/browser/cache_storage/legacy/legacy_cache_storage.h
@@ -29,9 +29,9 @@ class BlobStorageContext;
namespace content {
class CacheStorageIndex;
-class CacheStorageManager;
class CacheStorageScheduler;
enum class CacheStorageOwner;
+class LegacyCacheStorageManager;
namespace cache_storage_manager_unittest {
class CacheStorageManagerTest;
@@ -54,9 +54,10 @@ class CONTENT_EXPORT LegacyCacheStorage : public CacheStorage,
const base::FilePath& origin_path,
bool memory_only,
base::SequencedTaskRunner* cache_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
- CacheStorageManager* cache_storage_manager,
+ LegacyCacheStorageManager* cache_storage_manager,
const url::Origin& origin,
CacheStorageOwner owner);
@@ -296,7 +297,7 @@ class CONTENT_EXPORT LegacyCacheStorage : public CacheStorage,
// The manager that owns this cache storage. Only set to null by
// RemoveManager() when this cache storage is being deleted.
- CacheStorageManager* cache_storage_manager_;
+ LegacyCacheStorageManager* cache_storage_manager_;
base::CancelableOnceClosure index_write_task_;
size_t handle_ref_count_ = 0;
diff --git a/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc b/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
index 14344681cb9..abd1706c9e2 100644
--- a/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
+++ b/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
@@ -39,6 +39,7 @@
#include "content/browser/cache_storage/cache_storage_quota_client.h"
#include "content/browser/cache_storage/cache_storage_scheduler.h"
#include "content/browser/cache_storage/cache_storage_trace_utils.h"
+#include "content/browser/cache_storage/legacy/legacy_cache_storage.h"
#include "content/common/background_fetch/background_fetch_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
@@ -457,13 +458,15 @@ LegacyCacheStorageCache::CreateMemoryCache(
CacheStorageOwner owner,
const std::string& cache_name,
LegacyCacheStorage* cache_storage,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
std::unique_ptr<crypto::SymmetricKey> cache_padding_key) {
LegacyCacheStorageCache* cache = new LegacyCacheStorageCache(
origin, owner, cache_name, base::FilePath(), cache_storage,
- std::move(quota_manager_proxy), blob_context, 0 /* cache_size */,
- 0 /* cache_padding */, std::move(cache_padding_key));
+ std::move(scheduler_task_runner), std::move(quota_manager_proxy),
+ blob_context, 0 /* cache_size */, 0 /* cache_padding */,
+ std::move(cache_padding_key));
cache->SetObserver(cache_storage);
cache->InitBackend();
return base::WrapUnique(cache);
@@ -477,6 +480,7 @@ LegacyCacheStorageCache::CreatePersistentCache(
const std::string& cache_name,
LegacyCacheStorage* cache_storage,
const base::FilePath& path,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
int64_t cache_size,
@@ -484,8 +488,8 @@ LegacyCacheStorageCache::CreatePersistentCache(
std::unique_ptr<crypto::SymmetricKey> cache_padding_key) {
LegacyCacheStorageCache* cache = new LegacyCacheStorageCache(
origin, owner, cache_name, path, cache_storage,
- std::move(quota_manager_proxy), blob_context, cache_size, cache_padding,
- std::move(cache_padding_key));
+ std::move(scheduler_task_runner), std::move(quota_manager_proxy),
+ blob_context, cache_size, cache_padding, std::move(cache_padding_key));
cache->SetObserver(cache_storage);
cache->InitBackend();
return base::WrapUnique(cache);
@@ -897,12 +901,19 @@ LegacyCacheStorageCache::~LegacyCacheStorageCache() {
quota_manager_proxy_->NotifyOriginNoLongerInUse(origin_);
}
+void LegacyCacheStorageCache::SetSchedulerForTesting(
+ std::unique_ptr<CacheStorageScheduler> scheduler) {
+ DCHECK(!scheduler_->ScheduledOperations());
+ scheduler_ = std::move(scheduler);
+}
+
LegacyCacheStorageCache::LegacyCacheStorageCache(
const url::Origin& origin,
CacheStorageOwner owner,
const std::string& cache_name,
const base::FilePath& path,
LegacyCacheStorage* cache_storage,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
int64_t cache_size,
@@ -915,8 +926,8 @@ LegacyCacheStorageCache::LegacyCacheStorageCache(
cache_storage_(cache_storage),
quota_manager_proxy_(std::move(quota_manager_proxy)),
blob_storage_context_(blob_context),
- scheduler_(
- new CacheStorageScheduler(CacheStorageSchedulerClient::kCache)),
+ scheduler_(new CacheStorageScheduler(CacheStorageSchedulerClient::kCache,
+ std::move(scheduler_task_runner))),
cache_size_(cache_size),
cache_padding_(cache_padding),
cache_padding_key_(std::move(cache_padding_key)),
@@ -1419,7 +1430,11 @@ void LegacyCacheStorageCache::WriteSideDataDidOpenEntry(
std::move(callback).Run(CacheStorageError::kErrorNotFound);
return;
}
- disk_cache::ScopedEntryPtr entry(*entry_ptr);
+
+ // Moving the entry into a ScopedWritableEntry which will doom the entry
+ // before closing unless we tell it that writing has successfully completed
+ // via WritingCompleted.
+ ScopedWritableEntry entry(*entry_ptr);
ReadMetadata(
*entry_ptr,
@@ -1435,7 +1450,7 @@ void LegacyCacheStorageCache::WriteSideDataDidReadMetaData(
int64_t trace_id,
scoped_refptr<net::IOBuffer> buffer,
int buf_len,
- disk_cache::ScopedEntryPtr entry,
+ ScopedWritableEntry entry,
std::unique_ptr<proto::CacheMetadata> headers) {
TRACE_EVENT_WITH_FLOW0(
"CacheStorage", "LegacyCacheStorageCache::WriteSideDataDidReadMetaData",
@@ -1443,7 +1458,8 @@ void LegacyCacheStorageCache::WriteSideDataDidReadMetaData(
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
if (!headers || headers->response().response_time() !=
expected_response_time.ToInternalValue()) {
- std::move(callback).Run(CacheStorageError::kErrorNotFound);
+ WriteSideDataComplete(std::move(callback), std::move(entry),
+ CacheStorageError::kErrorNotFound);
return;
}
// Get a temporary copy of the entry pointer before passing it in base::Bind.
@@ -1475,7 +1491,7 @@ void LegacyCacheStorageCache::WriteSideDataDidReadMetaData(
void LegacyCacheStorageCache::WriteSideDataDidWrite(
ErrorCallback callback,
- disk_cache::ScopedEntryPtr entry,
+ ScopedWritableEntry entry,
int expected_bytes,
std::unique_ptr<::content::proto::CacheResponse> response,
int side_data_size_before_write,
@@ -1485,9 +1501,8 @@ void LegacyCacheStorageCache::WriteSideDataDidWrite(
"LegacyCacheStorageCache::WriteSideDataDidWrite",
TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN);
if (rv != expected_bytes) {
- entry->Doom();
- UpdateCacheSize(
- base::BindOnce(std::move(callback), CacheStorageError::kErrorNotFound));
+ WriteSideDataComplete(std::move(callback), std::move(entry),
+ CacheStorageError::kErrorStorage);
return;
}
@@ -1502,8 +1517,31 @@ void LegacyCacheStorageCache::WriteSideDataDidWrite(
response.get(), cache_padding_key_.get(), rv);
}
- UpdateCacheSize(
- base::BindOnce(std::move(callback), CacheStorageError::kSuccess));
+ WriteSideDataComplete(std::move(callback), std::move(entry),
+ CacheStorageError::kSuccess);
+}
+
+void LegacyCacheStorageCache::WriteSideDataComplete(
+ ErrorCallback callback,
+ ScopedWritableEntry entry,
+ blink::mojom::CacheStorageError error) {
+ if (error != CacheStorageError::kSuccess) {
+ // If we found the entry, then we possibly wrote something and now we're
+ // dooming the entry, causing a change in size, so update the size before
+ // returning.
+ if (error != CacheStorageError::kErrorNotFound) {
+ UpdateCacheSize(base::BindOnce(std::move(callback), error));
+ return;
+ }
+
+ entry.get_deleter()
+ .WritingCompleted(); // Since we didn't change the entry.
+ std::move(callback).Run(error);
+ return;
+ }
+
+ entry.get_deleter().WritingCompleted(); // Since we didn't change the entry.
+ UpdateCacheSize(base::BindOnce(std::move(callback), error));
}
void LegacyCacheStorageCache::Put(blink::mojom::BatchOperationPtr operation,
@@ -1544,8 +1582,8 @@ void LegacyCacheStorageCache::PutImpl(std::unique_ptr<PutContext> put_context) {
CacheStorageTracedValue(put_context->request), "response",
CacheStorageTracedValue(put_context->response));
if (backend_state_ != BACKEND_OPEN) {
- std::move(put_context->callback)
- .Run(MakeErrorStorage(ErrorStorageType::kPutImplBackendClosed));
+ PutComplete(std::move(put_context),
+ MakeErrorStorage(ErrorStorageType::kPutImplBackendClosed));
return;
}
@@ -1584,15 +1622,15 @@ void LegacyCacheStorageCache::PutDidDeleteEntry(
TRACE_ID_GLOBAL(put_context->trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
if (backend_state_ != BACKEND_OPEN) {
- std::move(put_context->callback)
- .Run(MakeErrorStorage(
- ErrorStorageType::kPutDidDeleteEntryBackendClosed));
+ PutComplete(
+ std::move(put_context),
+ MakeErrorStorage(ErrorStorageType::kPutDidDeleteEntryBackendClosed));
return;
}
if (error != CacheStorageError::kSuccess &&
error != CacheStorageError::kErrorNotFound) {
- std::move(put_context->callback).Run(error);
+ PutComplete(std::move(put_context), error);
return;
}
@@ -1627,10 +1665,13 @@ void LegacyCacheStorageCache::PutDidCreateEntry(
TRACE_ID_GLOBAL(put_context->trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+ // Moving the entry into a ScopedWritableEntry which will doom the entry
+ // before closing unless we tell it that writing has successfully completed
+ // via WritingCompleted.
put_context->cache_entry.reset(*entry_ptr);
if (rv != net::OK) {
- std::move(put_context->callback).Run(CacheStorageError::kErrorExists);
+ PutComplete(std::move(put_context), CacheStorageError::kErrorExists);
return;
}
@@ -1669,8 +1710,9 @@ void LegacyCacheStorageCache::PutDidCreateEntry(
std::unique_ptr<std::string> serialized(new std::string());
if (!metadata.SerializeToString(serialized.get())) {
- std::move(put_context->callback)
- .Run(MakeErrorStorage(ErrorStorageType::kMetadataSerializationFailed));
+ PutComplete(
+ std::move(put_context),
+ MakeErrorStorage(ErrorStorageType::kMetadataSerializationFailed));
return;
}
@@ -1707,9 +1749,9 @@ void LegacyCacheStorageCache::PutDidWriteHeaders(
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
if (rv != expected_bytes) {
- put_context->cache_entry->Doom();
- std::move(put_context->callback)
- .Run(MakeErrorStorage(ErrorStorageType::kPutDidWriteHeadersWrongBytes));
+ PutComplete(
+ std::move(put_context),
+ MakeErrorStorage(ErrorStorageType::kPutDidWriteHeadersWrongBytes));
return;
}
@@ -1735,8 +1777,7 @@ void LegacyCacheStorageCache::PutDidWriteHeaders(
return;
}
- UpdateCacheSize(base::BindOnce(std::move(put_context->callback),
- CacheStorageError::kSuccess));
+ PutComplete(std::move(put_context), CacheStorageError::kSuccess);
}
void LegacyCacheStorageCache::PutWriteBlobToCache(
@@ -1750,17 +1791,28 @@ void LegacyCacheStorageCache::PutWriteBlobToCache(
TRACE_ID_GLOBAL(put_context->trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
- blink::mojom::BlobPtr blob = disk_cache_body_index == INDEX_RESPONSE_BODY
- ? std::move(put_context->blob)
- : std::move(put_context->side_data_blob);
- DCHECK(blob);
+ blink::mojom::BlobPtr blob;
+ int64_t blob_size = 0;
- int64_t blob_size = disk_cache_body_index == INDEX_RESPONSE_BODY
- ? put_context->blob_size
- : put_context->side_data_blob_size;
+ switch (disk_cache_body_index) {
+ case INDEX_RESPONSE_BODY: {
+ blob = std::move(put_context->blob);
+ put_context->blob.reset();
+ blob_size = put_context->blob_size;
+ break;
+ }
+ case INDEX_SIDE_DATA: {
+ blob = std::move(put_context->side_data_blob);
+ put_context->side_data_blob.reset();
+ blob_size = put_context->side_data_blob_size;
+ break;
+ }
+ case INDEX_HEADERS:
+ NOTREACHED();
+ }
+ DCHECK(blob);
- disk_cache::ScopedEntryPtr entry(std::move(put_context->cache_entry));
- put_context->cache_entry = nullptr;
+ ScopedWritableEntry entry(put_context->cache_entry.release());
auto blob_to_cache = std::make_unique<CacheStorageBlobToDiskCache>();
CacheStorageBlobToDiskCache* blob_to_cache_raw = blob_to_cache.get();
@@ -1777,7 +1829,7 @@ void LegacyCacheStorageCache::PutWriteBlobToCache(
void LegacyCacheStorageCache::PutDidWriteBlobToCache(
std::unique_ptr<PutContext> put_context,
BlobToDiskCacheIDMap::KeyType blob_to_cache_key,
- disk_cache::ScopedEntryPtr entry,
+ ScopedWritableEntry entry,
bool success) {
DCHECK(entry);
TRACE_EVENT_WITH_FLOW0("CacheStorage",
@@ -1790,9 +1842,9 @@ void LegacyCacheStorageCache::PutDidWriteBlobToCache(
active_blob_to_disk_cache_writers_.Remove(blob_to_cache_key);
if (!success) {
- put_context->cache_entry->Doom();
- std::move(put_context->callback)
- .Run(MakeErrorStorage(ErrorStorageType::kPutDidWriteBlobToCacheFailed));
+ PutComplete(
+ std::move(put_context),
+ MakeErrorStorage(ErrorStorageType::kPutDidWriteBlobToCacheFailed));
return;
}
@@ -1801,8 +1853,24 @@ void LegacyCacheStorageCache::PutDidWriteBlobToCache(
return;
}
- UpdateCacheSize(base::BindOnce(std::move(put_context->callback),
- CacheStorageError::kSuccess));
+ PutComplete(std::move(put_context), CacheStorageError::kSuccess);
+}
+
+void LegacyCacheStorageCache::PutComplete(
+ std::unique_ptr<PutContext> put_context,
+ blink::mojom::CacheStorageError error) {
+ if (error == CacheStorageError::kSuccess) {
+ // Make sure we've written everything.
+ DCHECK(put_context->cache_entry);
+ DCHECK(!put_context->blob);
+ DCHECK(!put_context->side_data_blob);
+
+ // Tell the WritableScopedEntry not to doom the entry since it was a
+ // successful operation.
+ put_context->cache_entry.get_deleter().WritingCompleted();
+ }
+
+ UpdateCacheSize(base::BindOnce(std::move(put_context->callback), error));
}
void LegacyCacheStorageCache::CalculateCacheSizePadding(
@@ -2141,8 +2209,8 @@ void LegacyCacheStorageCache::CreateBackend(ErrorCallback callback) {
// The maximum size of each cache. Ultimately, cache size
// is controlled per-origin by the QuotaManager.
- uint64_t max_bytes = memory_only_ ? std::numeric_limits<int>::max()
- : std::numeric_limits<int64_t>::max();
+ int64_t max_bytes = memory_only_ ? std::numeric_limits<int>::max()
+ : std::numeric_limits<int64_t>::max();
std::unique_ptr<ScopedBackendPtr> backend_ptr(new ScopedBackendPtr());
diff --git a/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h b/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h
index 2a245590d2e..3764aabd0eb 100644
--- a/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h
+++ b/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h
@@ -19,6 +19,7 @@
#include "base/optional.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
#include "content/browser/cache_storage/cache_storage_handle.h"
+#include "content/browser/cache_storage/scoped_writable_entry.h"
#include "content/common/service_worker/service_worker_types.h"
#include "net/base/completion_once_callback.h"
#include "net/base/io_buffer.h"
@@ -67,6 +68,7 @@ class CONTENT_EXPORT LegacyCacheStorageCache : public CacheStorageCache {
CacheStorageOwner owner,
const std::string& cache_name,
LegacyCacheStorage* cache_storage,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
std::unique_ptr<crypto::SymmetricKey> cache_padding_key);
@@ -76,6 +78,7 @@ class CONTENT_EXPORT LegacyCacheStorageCache : public CacheStorageCache {
const std::string& cache_name,
LegacyCacheStorage* cache_storage,
const base::FilePath& path,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
int64_t cache_size,
@@ -195,6 +198,10 @@ class CONTENT_EXPORT LegacyCacheStorageCache : public CacheStorageCache {
void DropHandleRef() override;
bool IsUnreferenced() const override;
+ // Override the default scheduler with a customized scheduler for testing.
+ // The current scheduler must be idle.
+ void SetSchedulerForTesting(std::unique_ptr<CacheStorageScheduler> scheduler);
+
static LegacyCacheStorageCache* From(const CacheStorageCacheHandle& handle) {
return static_cast<LegacyCacheStorageCache*>(handle.value());
}
@@ -239,6 +246,7 @@ class CONTENT_EXPORT LegacyCacheStorageCache : public CacheStorageCache {
const std::string& cache_name,
const base::FilePath& path,
LegacyCacheStorage* cache_storage,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
int64_t cache_size,
@@ -333,16 +341,19 @@ class CONTENT_EXPORT LegacyCacheStorageCache : public CacheStorageCache {
int64_t trace_id,
scoped_refptr<net::IOBuffer> buffer,
int buf_len,
- disk_cache::ScopedEntryPtr entry,
+ ScopedWritableEntry entry,
std::unique_ptr<proto::CacheMetadata> headers);
void WriteSideDataDidWrite(
ErrorCallback callback,
- disk_cache::ScopedEntryPtr entry,
+ ScopedWritableEntry entry,
int expected_bytes,
std::unique_ptr<content::proto::CacheResponse> response,
int side_data_size_before_write,
int64_t trace_id,
int rv);
+ void WriteSideDataComplete(ErrorCallback callback,
+ ScopedWritableEntry entry,
+ blink::mojom::CacheStorageError error);
// Puts the request and response object in the cache. The response body (if
// present) is stored in the cache, but not the request body. Returns OK on
@@ -367,8 +378,10 @@ class CONTENT_EXPORT LegacyCacheStorageCache : public CacheStorageCache {
int disk_cache_body_index);
void PutDidWriteBlobToCache(std::unique_ptr<PutContext> put_context,
BlobToDiskCacheIDMap::KeyType blob_to_cache_key,
- disk_cache::ScopedEntryPtr entry,
+ ScopedWritableEntry entry,
bool success);
+ void PutComplete(std::unique_ptr<PutContext> put_context,
+ blink::mojom::CacheStorageError error);
// Asynchronously calculates the current cache size, notifies the quota
// manager of any change from the last report, and sets cache_size_ to the new
diff --git a/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_manager.cc b/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_manager.cc
new file mode 100644
index 00000000000..84874592c2c
--- /dev/null
+++ b/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_manager.cc
@@ -0,0 +1,479 @@
+// 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/cache_storage/legacy/legacy_cache_storage_manager.h"
+
+#include <stdint.h>
+
+#include <map>
+#include <numeric>
+#include <set>
+#include <utility>
+
+#include "base/barrier_closure.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/containers/id_map.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
+#include "base/hash/sha1.h"
+#include "base/memory/ptr_util.h"
+#include "base/sequenced_task_runner.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "content/browser/cache_storage/cache_storage.h"
+#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 "net/base/url_util.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/common/database/database_identifier.h"
+#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+
+namespace {
+
+bool DeleteDir(const base::FilePath& path) {
+ return base::DeleteFile(path, true /* recursive */);
+}
+
+void DeleteOriginDidDeleteDir(storage::QuotaClient::DeletionCallback callback,
+ bool rv) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback),
+ rv ? blink::mojom::QuotaStatusCode::kOk
+ : blink::mojom::QuotaStatusCode::kErrorAbort));
+}
+
+// Calculate the sum of all cache sizes in this store, but only if all sizes are
+// known. If one or more sizes are not known then return kSizeUnknown.
+int64_t GetCacheStorageSize(const proto::CacheStorageIndex& index) {
+ int64_t storage_size = 0;
+ for (int i = 0, max = index.cache_size(); i < max; ++i) {
+ const proto::CacheStorageIndex::Cache& cache = index.cache(i);
+ if (!cache.has_size() || cache.size() == CacheStorage::kSizeUnknown)
+ return CacheStorage::kSizeUnknown;
+ storage_size += cache.size();
+ }
+ return storage_size;
+}
+
+// Open the various cache directories' index files and extract their origins,
+// sizes (if current), and last modified times.
+void ListOriginsAndLastModifiedOnTaskRunner(
+ std::vector<StorageUsageInfo>* usages,
+ base::FilePath root_path,
+ CacheStorageOwner owner) {
+ base::FileEnumerator file_enum(root_path, false /* recursive */,
+ base::FileEnumerator::DIRECTORIES);
+
+ base::FilePath path;
+ while (!(path = file_enum.Next()).empty()) {
+ base::FilePath index_path =
+ path.AppendASCII(LegacyCacheStorage::kIndexFileName);
+ base::File::Info file_info;
+ base::Time index_last_modified;
+ if (GetFileInfo(index_path, &file_info))
+ index_last_modified = file_info.last_modified;
+ std::string protobuf;
+ base::ReadFileToString(path.AppendASCII(LegacyCacheStorage::kIndexFileName),
+ &protobuf);
+ proto::CacheStorageIndex index;
+ if (index.ParseFromString(protobuf)) {
+ if (index.has_origin()) {
+ if (path ==
+ LegacyCacheStorageManager::ConstructOriginPath(
+ root_path, url::Origin::Create(GURL(index.origin())), owner)) {
+ if (base::GetFileInfo(path, &file_info)) {
+ int64_t storage_size = CacheStorage::kSizeUnknown;
+ if (file_info.last_modified < index_last_modified)
+ storage_size = GetCacheStorageSize(index);
+ usages->push_back(
+ StorageUsageInfo(url::Origin::Create(GURL(index.origin())),
+ storage_size, file_info.last_modified));
+ }
+ }
+ }
+ }
+ }
+}
+
+std::set<url::Origin> ListOriginsOnTaskRunner(base::FilePath root_path,
+ CacheStorageOwner owner) {
+ std::vector<StorageUsageInfo> usages;
+ ListOriginsAndLastModifiedOnTaskRunner(&usages, root_path, owner);
+
+ std::set<url::Origin> out_origins;
+ for (const StorageUsageInfo& usage : usages)
+ out_origins.insert(usage.origin);
+
+ return out_origins;
+}
+
+void GetOriginsForHostDidListOrigins(
+ const std::string& host,
+ storage::QuotaClient::GetOriginsCallback callback,
+ const std::set<url::Origin>& origins) {
+ std::set<url::Origin> out_origins;
+ for (const url::Origin& origin : origins) {
+ if (host == net::GetHostOrSpecFromURL(origin.GetURL()))
+ out_origins.insert(origin);
+ }
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), out_origins));
+}
+
+void AllOriginSizesReported(
+ std::unique_ptr<std::vector<StorageUsageInfo>> usages,
+ CacheStorageContext::GetUsageInfoCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), *usages));
+}
+
+void OneOriginSizeReported(base::OnceClosure callback,
+ StorageUsageInfo* usage,
+ int64_t size) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ DCHECK_NE(size, CacheStorage::kSizeUnknown);
+ usage->total_size_bytes = size;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
+}
+
+} // namespace
+
+// static
+scoped_refptr<LegacyCacheStorageManager> LegacyCacheStorageManager::Create(
+ const base::FilePath& path,
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
+ scoped_refptr<CacheStorageContextImpl::ObserverList> observers) {
+ base::FilePath root_path = path;
+ if (!path.empty()) {
+ root_path = path.Append(ServiceWorkerContextCore::kServiceWorkerDirectory)
+ .AppendASCII("CacheStorage");
+ }
+
+ return base::WrapRefCounted(new LegacyCacheStorageManager(
+ root_path, std::move(cache_task_runner), std::move(scheduler_task_runner),
+ std::move(quota_manager_proxy), std::move(observers)));
+}
+
+// static
+scoped_refptr<LegacyCacheStorageManager>
+LegacyCacheStorageManager::CreateForTesting(
+ LegacyCacheStorageManager* old_manager) {
+ scoped_refptr<LegacyCacheStorageManager> manager(
+ new LegacyCacheStorageManager(
+ old_manager->root_path(), old_manager->cache_task_runner(),
+ old_manager->scheduler_task_runner(),
+ old_manager->quota_manager_proxy_.get(), old_manager->observers_));
+ manager->SetBlobParametersForCache(old_manager->blob_storage_context());
+ return manager;
+}
+
+LegacyCacheStorageManager::~LegacyCacheStorageManager() = default;
+
+CacheStorageHandle LegacyCacheStorageManager::OpenCacheStorage(
+ const url::Origin& origin,
+ CacheStorageOwner owner) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // Wait to create the MemoryPressureListener until the first CacheStorage
+ // object is needed. This ensures we create the listener on the correct
+ // thread.
+ if (!memory_pressure_listener_) {
+ memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
+ base::BindRepeating(&LegacyCacheStorageManager::OnMemoryPressure,
+ base::Unretained(this)));
+ }
+
+ CacheStorageMap::const_iterator it = cache_storage_map_.find({origin, owner});
+ if (it == cache_storage_map_.end()) {
+ LegacyCacheStorage* cache_storage = new LegacyCacheStorage(
+ ConstructOriginPath(root_path_, origin, owner), IsMemoryBacked(),
+ cache_task_runner_.get(), scheduler_task_runner_, quota_manager_proxy_,
+ blob_context_, this, origin, owner);
+ cache_storage_map_[{origin, owner}] = base::WrapUnique(cache_storage);
+ return cache_storage->CreateHandle();
+ }
+ return it->second.get()->CreateHandle();
+}
+
+void LegacyCacheStorageManager::SetBlobParametersForCache(
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(cache_storage_map_.empty());
+ DCHECK(!blob_context_ || blob_context_.get() == blob_storage_context.get());
+ blob_context_ = blob_storage_context;
+}
+
+void LegacyCacheStorageManager::NotifyCacheListChanged(
+ const url::Origin& origin) {
+ observers_->Notify(FROM_HERE,
+ &CacheStorageContextImpl::Observer::OnCacheListChanged,
+ origin);
+}
+
+void LegacyCacheStorageManager::NotifyCacheContentChanged(
+ const url::Origin& origin,
+ const std::string& name) {
+ observers_->Notify(FROM_HERE,
+ &CacheStorageContextImpl::Observer::OnCacheContentChanged,
+ origin, name);
+}
+
+void LegacyCacheStorageManager::CacheStorageUnreferenced(
+ LegacyCacheStorage* cache_storage,
+ const url::Origin& origin,
+ CacheStorageOwner owner) {
+ DCHECK(cache_storage);
+ cache_storage->AssertUnreferenced();
+ auto it = cache_storage_map_.find({origin, owner});
+ DCHECK(it != cache_storage_map_.end());
+ DCHECK(it->second.get() == cache_storage);
+
+ // Currently we don't do anything when a CacheStorage instance becomes
+ // unreferenced. In the future we will deallocate some or all of the
+ // CacheStorage's state.
+}
+
+void LegacyCacheStorageManager::GetAllOriginsUsage(
+ CacheStorageOwner owner,
+ CacheStorageContext::GetUsageInfoCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ auto usages = std::make_unique<std::vector<StorageUsageInfo>>();
+
+ if (IsMemoryBacked()) {
+ for (const auto& origin_details : cache_storage_map_) {
+ if (origin_details.first.second != owner)
+ continue;
+ usages->emplace_back(origin_details.first.first,
+ /*total_size_bytes=*/0,
+ /*last_modified=*/base::Time());
+ }
+ GetAllOriginsUsageGetSizes(std::move(usages), std::move(callback));
+ return;
+ }
+
+ std::vector<StorageUsageInfo>* usages_ptr = usages.get();
+ cache_task_runner_->PostTaskAndReply(
+ FROM_HERE,
+ base::BindOnce(&ListOriginsAndLastModifiedOnTaskRunner, usages_ptr,
+ root_path_, owner),
+ base::BindOnce(&LegacyCacheStorageManager::GetAllOriginsUsageGetSizes,
+ weak_ptr_factory_.GetWeakPtr(), std::move(usages),
+ std::move(callback)));
+}
+
+void LegacyCacheStorageManager::GetAllOriginsUsageGetSizes(
+ std::unique_ptr<std::vector<StorageUsageInfo>> usages,
+ CacheStorageContext::GetUsageInfoCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(usages);
+
+ // The origin GURL and last modified times are set in |usages| but not the
+ // size in bytes. Call each CacheStorage's Size() function to fill that out.
+ std::vector<StorageUsageInfo>* usages_ptr = usages.get();
+
+ if (usages->empty()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), *usages));
+ return;
+ }
+
+ base::RepeatingClosure barrier_closure = base::BarrierClosure(
+ usages_ptr->size(),
+ base::BindOnce(&AllOriginSizesReported, std::move(usages),
+ std::move(callback)));
+
+ for (StorageUsageInfo& usage : *usages_ptr) {
+ if (usage.total_size_bytes != CacheStorage::kSizeUnknown ||
+ !IsValidQuotaOrigin(usage.origin)) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, barrier_closure);
+ continue;
+ }
+ CacheStorageHandle cache_storage =
+ OpenCacheStorage(usage.origin, CacheStorageOwner::kCacheAPI);
+ LegacyCacheStorage::From(cache_storage)
+ ->Size(base::BindOnce(&OneOriginSizeReported, barrier_closure, &usage));
+ }
+}
+
+void LegacyCacheStorageManager::GetOriginUsage(
+ const url::Origin& origin,
+ CacheStorageOwner owner,
+ storage::QuotaClient::GetUsageCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ CacheStorageHandle cache_storage = OpenCacheStorage(origin, owner);
+ LegacyCacheStorage::From(cache_storage)->Size(std::move(callback));
+}
+
+void LegacyCacheStorageManager::GetOrigins(
+ CacheStorageOwner owner,
+ storage::QuotaClient::GetOriginsCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (IsMemoryBacked()) {
+ std::set<url::Origin> origins;
+ for (const auto& key_value : cache_storage_map_)
+ if (key_value.first.second == owner)
+ origins.insert(key_value.first.first);
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), origins));
+ return;
+ }
+
+ PostTaskAndReplyWithResult(
+ cache_task_runner_.get(), FROM_HERE,
+ base::BindOnce(&ListOriginsOnTaskRunner, root_path_, owner),
+ std::move(callback));
+}
+
+void LegacyCacheStorageManager::GetOriginsForHost(
+ const std::string& host,
+ CacheStorageOwner owner,
+ storage::QuotaClient::GetOriginsCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (IsMemoryBacked()) {
+ std::set<url::Origin> origins;
+ for (const auto& key_value : cache_storage_map_) {
+ if (key_value.first.second != owner)
+ continue;
+ if (host == net::GetHostOrSpecFromURL(key_value.first.first.GetURL()))
+ origins.insert(key_value.first.first);
+ }
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), origins));
+ return;
+ }
+
+ PostTaskAndReplyWithResult(
+ cache_task_runner_.get(), FROM_HERE,
+ base::BindOnce(&ListOriginsOnTaskRunner, root_path_, owner),
+ base::BindOnce(&GetOriginsForHostDidListOrigins, host,
+ std::move(callback)));
+}
+
+void LegacyCacheStorageManager::DeleteOriginData(
+ const url::Origin& origin,
+ CacheStorageOwner owner,
+ storage::QuotaClient::DeletionCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // Create the CacheStorage for the origin if it hasn't been loaded yet.
+ CacheStorageHandle handle = OpenCacheStorage(origin, owner);
+
+ auto it = cache_storage_map_.find({origin, owner});
+ DCHECK(it != cache_storage_map_.end());
+
+ LegacyCacheStorage* cache_storage = it->second.release();
+ cache_storage->ResetManager();
+ cache_storage_map_.erase({origin, owner});
+ cache_storage->GetSizeThenCloseAllCaches(
+ base::BindOnce(&LegacyCacheStorageManager::DeleteOriginDidClose,
+ weak_ptr_factory_.GetWeakPtr(), origin, owner,
+ std::move(callback), base::WrapUnique(cache_storage)));
+}
+
+void LegacyCacheStorageManager::DeleteOriginData(const url::Origin& origin,
+ CacheStorageOwner owner) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DeleteOriginData(origin, owner, base::DoNothing());
+}
+
+void LegacyCacheStorageManager::DeleteOriginDidClose(
+ const url::Origin& origin,
+ CacheStorageOwner owner,
+ storage::QuotaClient::DeletionCallback callback,
+ std::unique_ptr<LegacyCacheStorage> cache_storage,
+ int64_t origin_size) {
+ // TODO(jkarlin): Deleting the storage leaves any unfinished operations
+ // hanging, resulting in unresolved promises. Fix this by returning early from
+ // CacheStorage operations posted after GetSizeThenCloseAllCaches is called.
+ cache_storage.reset();
+
+ quota_manager_proxy_->NotifyStorageModified(
+ CacheStorageQuotaClient::GetIDFromOwner(owner), origin,
+ blink::mojom::StorageType::kTemporary, -1 * origin_size);
+
+ if (owner == CacheStorageOwner::kCacheAPI)
+ NotifyCacheListChanged(origin);
+
+ if (IsMemoryBacked()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback),
+ blink::mojom::QuotaStatusCode::kOk));
+ return;
+ }
+
+ PostTaskAndReplyWithResult(
+ cache_task_runner_.get(), FROM_HERE,
+ base::BindOnce(&DeleteDir,
+ ConstructOriginPath(root_path_, origin, owner)),
+ base::BindOnce(&DeleteOriginDidDeleteDir, std::move(callback)));
+}
+
+LegacyCacheStorageManager::LegacyCacheStorageManager(
+ const base::FilePath& path,
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
+ scoped_refptr<CacheStorageContextImpl::ObserverList> observers)
+ : root_path_(path),
+ cache_task_runner_(std::move(cache_task_runner)),
+ scheduler_task_runner_(std::move(scheduler_task_runner)),
+ quota_manager_proxy_(std::move(quota_manager_proxy)),
+ observers_(std::move(observers)),
+ weak_ptr_factory_(this) {
+ if (quota_manager_proxy_.get()) {
+ quota_manager_proxy_->RegisterClient(new CacheStorageQuotaClient(
+ weak_ptr_factory_.GetWeakPtr(), CacheStorageOwner::kCacheAPI));
+ quota_manager_proxy_->RegisterClient(new CacheStorageQuotaClient(
+ weak_ptr_factory_.GetWeakPtr(), CacheStorageOwner::kBackgroundFetch));
+ }
+}
+
+// static
+base::FilePath LegacyCacheStorageManager::ConstructOriginPath(
+ const base::FilePath& root_path,
+ const url::Origin& origin,
+ CacheStorageOwner owner) {
+ std::string identifier = storage::GetIdentifierFromOrigin(origin);
+ if (owner != CacheStorageOwner::kCacheAPI) {
+ identifier += "-" + std::to_string(static_cast<int>(owner));
+ }
+ const std::string origin_hash = base::SHA1HashString(identifier);
+ const std::string origin_hash_hex = base::ToLowerASCII(
+ base::HexEncode(origin_hash.c_str(), origin_hash.length()));
+ return root_path.AppendASCII(origin_hash_hex);
+}
+
+void LegacyCacheStorageManager::OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel level) {
+ if (level != base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL)
+ return;
+
+ for (auto& entry : cache_storage_map_) {
+ entry.second->ReleaseUnreferencedCaches();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_manager.h b/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_manager.h
new file mode 100644
index 00000000000..35ddcba39f5
--- /dev/null
+++ b/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_manager.h
@@ -0,0 +1,170 @@
+// 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_CACHE_STORAGE_LEGACY_LEGACY_CACHE_STORAGE_MANAGER_H_
+#define CONTENT_BROWSER_CACHE_STORAGE_LEGACY_LEGACY_CACHE_STORAGE_MANAGER_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/memory_pressure_listener.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "content/browser/cache_storage/cache_storage_context_impl.h"
+#include "content/browser/cache_storage/cache_storage_manager.h"
+#include "content/browser/cache_storage/legacy/legacy_cache_storage.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/storage_usage_info.h"
+#include "storage/browser/quota/quota_client.h"
+#include "url/origin.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
+
+namespace content {
+
+namespace cache_storage_manager_unittest {
+class CacheStorageManagerTest;
+}
+
+// A concrete implementation of the CacheStorageManager interface using
+// the legacy disk_cache backend.
+class CONTENT_EXPORT LegacyCacheStorageManager : public CacheStorageManager {
+ public:
+ static scoped_refptr<LegacyCacheStorageManager> Create(
+ const base::FilePath& path,
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
+ scoped_refptr<CacheStorageContextImpl::ObserverList> observers);
+
+ // Create a new manager using the underlying configuration of the given
+ // manager, but with its own list of storage objects. This is only used
+ // for testing.
+ static scoped_refptr<LegacyCacheStorageManager> CreateForTesting(
+ LegacyCacheStorageManager* old_manager);
+
+ // Map a database identifier (computed from an origin) to the path.
+ static base::FilePath ConstructOriginPath(const base::FilePath& root_path,
+ const url::Origin& origin,
+ CacheStorageOwner owner);
+
+ // Open the CacheStorage for the given origin and owner. A reference counting
+ // handle is returned which can be stored and used similar to a weak pointer.
+ CacheStorageHandle OpenCacheStorage(const url::Origin& origin,
+ CacheStorageOwner owner) override;
+
+ void GetAllOriginsUsage(
+ CacheStorageOwner owner,
+ CacheStorageContext::GetUsageInfoCallback callback) override;
+ void GetOriginUsage(const url::Origin& origin_url,
+ CacheStorageOwner owner,
+ storage::QuotaClient::GetUsageCallback callback) override;
+ void GetOrigins(CacheStorageOwner owner,
+ storage::QuotaClient::GetOriginsCallback callback) override;
+ void GetOriginsForHost(
+ const std::string& host,
+ CacheStorageOwner owner,
+ storage::QuotaClient::GetOriginsCallback callback) override;
+ void DeleteOriginData(
+ const url::Origin& origin,
+ CacheStorageOwner owner,
+ storage::QuotaClient::DeletionCallback callback) override;
+ void DeleteOriginData(const url::Origin& origin,
+ CacheStorageOwner owner) override;
+
+ void SetBlobParametersForCache(
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context) override;
+
+ void NotifyCacheListChanged(const url::Origin& origin);
+ void NotifyCacheContentChanged(const url::Origin& origin,
+ const std::string& name);
+
+ base::WeakPtr<CacheStorageManager> AsWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
+
+ base::FilePath root_path() const { return root_path_; }
+
+ // This method is called when the last CacheStorageHandle for a particular
+ // instance is destroyed and its reference count drops to zero.
+ void CacheStorageUnreferenced(LegacyCacheStorage* cache_storage,
+ const url::Origin& origin,
+ CacheStorageOwner owner);
+
+ private:
+ friend class cache_storage_manager_unittest::CacheStorageManagerTest;
+ friend class CacheStorageContextImpl;
+
+ typedef std::map<std::pair<url::Origin, CacheStorageOwner>,
+ std::unique_ptr<LegacyCacheStorage>>
+ CacheStorageMap;
+
+ LegacyCacheStorageManager(
+ const base::FilePath& path,
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
+ scoped_refptr<CacheStorageContextImpl::ObserverList> observers);
+
+ ~LegacyCacheStorageManager() override;
+
+ void GetAllOriginsUsageGetSizes(
+ std::unique_ptr<std::vector<StorageUsageInfo>> usage_info,
+ CacheStorageContext::GetUsageInfoCallback callback);
+
+ void DeleteOriginDidClose(const url::Origin& origin,
+ CacheStorageOwner owner,
+ storage::QuotaClient::DeletionCallback callback,
+ std::unique_ptr<LegacyCacheStorage> cache_storage,
+ int64_t origin_size);
+
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context() const {
+ return blob_context_;
+ }
+
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner() const {
+ return cache_task_runner_;
+ }
+
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner() const {
+ return scheduler_task_runner_;
+ }
+
+ bool IsMemoryBacked() const { return root_path_.empty(); }
+
+ // MemoryPressureListener callback
+ void OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel level);
+
+ base::FilePath root_path_;
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
+ scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner_;
+
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
+
+ // The map owns the CacheStorages and the CacheStorages are only accessed on
+ // |cache_task_runner_|.
+ CacheStorageMap cache_storage_map_;
+
+ scoped_refptr<CacheStorageContextImpl::ObserverList> observers_;
+
+ base::WeakPtr<storage::BlobStorageContext> blob_context_;
+
+ std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
+
+ base::WeakPtrFactory<LegacyCacheStorageManager> weak_ptr_factory_;
+ DISALLOW_COPY_AND_ASSIGN(LegacyCacheStorageManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_CACHE_STORAGE_LEGACY_LEGACY_CACHE_STORAGE_MANAGER_H_
diff --git a/chromium/content/browser/cache_storage/scoped_writable_entry.h b/chromium/content/browser/cache_storage/scoped_writable_entry.h
new file mode 100644
index 00000000000..93f55159345
--- /dev/null
+++ b/chromium/content/browser/cache_storage/scoped_writable_entry.h
@@ -0,0 +1,49 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_CACHE_STORAGE_SCOPED_WRITABLE_ENTRY_H_
+#define CONTENT_BROWSER_CACHE_STORAGE_SCOPED_WRITABLE_ENTRY_H_
+
+#include <memory>
+
+#include "net/disk_cache/disk_cache.h"
+
+namespace content {
+
+// A custom deleter that closes the entry. But if WritingCompleted() hasn't been
+// called, it will doom the entry before closing it.
+class ScopedWritableDeleter {
+ public:
+ ScopedWritableDeleter() = default;
+ ScopedWritableDeleter(ScopedWritableDeleter&& other) = default;
+ ScopedWritableDeleter& operator=(ScopedWritableDeleter&& other) = default;
+
+ void operator()(disk_cache::Entry* entry) {
+ if (!completed_)
+ entry->Doom();
+
+ // |entry| is owned by the backend, we just need to close it as it's
+ // ref-counted.
+ entry->Close();
+ }
+
+ void WritingCompleted() { completed_ = true; }
+
+ private:
+ bool completed_ = false;
+};
+
+// Use this to manage disk_cache::Entry*'s that should be doomed before closing
+// unless told otherwise (via calling WritingCompleted on the deleter).
+//
+// Example:
+// ScopedWritableEntry entry(my_entry);
+// .. write some stuff ..
+// entry.get_deleter().WritingCompleted();
+typedef std::unique_ptr<disk_cache::Entry, ScopedWritableDeleter>
+ ScopedWritableEntry;
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_CACHE_STORAGE_SCOPED_WRITABLE_ENTRY_H_
diff --git a/chromium/content/browser/child_process_launcher.cc b/chromium/content/browser/child_process_launcher.cc
index e3086c33df2..84da2e4f52d 100644
--- a/chromium/content/browser/child_process_launcher.cc
+++ b/chromium/content/browser/child_process_launcher.cc
@@ -188,9 +188,7 @@ ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
bool ChildProcessLauncherPriority::is_background() const {
return !visible && !has_media_stream && !boost_for_pending_views &&
- !(has_foreground_service_worker &&
- base::FeatureList::IsEnabled(
- features::kServiceWorkerForegroundPriority));
+ !has_foreground_service_worker;
}
bool ChildProcessLauncherPriority::operator==(
diff --git a/chromium/content/browser/child_process_launcher_helper_android.cc b/chromium/content/browser/child_process_launcher_helper_android.cc
index 50f5ee16808..bed56cfd0d4 100644
--- a/chromium/content/browser/child_process_launcher_helper_android.cc
+++ b/chromium/content/browser/child_process_launcher_helper_android.cc
@@ -190,7 +190,8 @@ static void JNI_ChildProcessLauncherHelperImpl_SetTerminationInfo(
jboolean clean_exit,
jint remaining_process_with_strong_binding,
jint remaining_process_with_moderate_binding,
- jint remaining_process_with_waived_binding) {
+ jint remaining_process_with_waived_binding,
+ jint reverse_rank) {
ChildProcessTerminationInfo* info =
reinterpret_cast<ChildProcessTerminationInfo*>(termination_info_ptr);
info->binding_state =
@@ -203,6 +204,7 @@ static void JNI_ChildProcessLauncherHelperImpl_SetTerminationInfo(
remaining_process_with_moderate_binding;
info->remaining_process_with_waived_binding =
remaining_process_with_waived_binding;
+ info->best_effort_reverse_rank = reverse_rank;
}
// static
diff --git a/chromium/content/browser/child_process_launcher_helper_mac.cc b/chromium/content/browser/child_process_launcher_helper_mac.cc
index 59390c523fa..8a46b5859d5 100644
--- a/chromium/content/browser/child_process_launcher_helper_mac.cc
+++ b/chromium/content/browser/child_process_launcher_helper_mac.cc
@@ -24,16 +24,7 @@
#include "mojo/public/cpp/platform/features.h"
#include "sandbox/mac/seatbelt_exec.h"
#include "services/service_manager/embedder/result_codes.h"
-#include "services/service_manager/sandbox/mac/audio.sb.h"
-#include "services/service_manager/sandbox/mac/cdm.sb.h"
-#include "services/service_manager/sandbox/mac/common.sb.h"
-#include "services/service_manager/sandbox/mac/gpu_v2.sb.h"
-#include "services/service_manager/sandbox/mac/nacl_loader.sb.h"
-#include "services/service_manager/sandbox/mac/network.sb.h"
-#include "services/service_manager/sandbox/mac/pdf_compositor.sb.h"
-#include "services/service_manager/sandbox/mac/ppapi.sb.h"
-#include "services/service_manager/sandbox/mac/renderer.sb.h"
-#include "services/service_manager/sandbox/mac/utility.sb.h"
+#include "services/service_manager/sandbox/mac/sandbox_mac.h"
#include "services/service_manager/sandbox/sandbox.h"
#include "services/service_manager/sandbox/sandbox_type.h"
#include "services/service_manager/sandbox/switches.h"
@@ -92,43 +83,7 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
if (use_v2 && !no_sandbox) {
// Generate the profile string.
std::string profile =
- std::string(service_manager::kSeatbeltPolicyString_common);
-
- switch (sandbox_type) {
- case service_manager::SANDBOX_TYPE_CDM:
- profile += service_manager::kSeatbeltPolicyString_cdm;
- break;
- case service_manager::SANDBOX_TYPE_GPU:
- profile += service_manager::kSeatbeltPolicyString_gpu_v2;
- break;
- case service_manager::SANDBOX_TYPE_NACL_LOADER:
- profile += service_manager::kSeatbeltPolicyString_nacl_loader;
- break;
- case service_manager::SANDBOX_TYPE_PPAPI:
- profile += service_manager::kSeatbeltPolicyString_ppapi;
- break;
- case service_manager::SANDBOX_TYPE_RENDERER:
- profile += service_manager::kSeatbeltPolicyString_renderer;
- break;
- case service_manager::SANDBOX_TYPE_PDF_COMPOSITOR:
- profile += service_manager::kSeatbeltPolicyString_pdf_compositor;
- break;
- case service_manager::SANDBOX_TYPE_AUDIO:
- profile += service_manager::kSeatbeltPolicyString_audio;
- break;
- case service_manager::SANDBOX_TYPE_NETWORK:
- profile += service_manager::kSeatbeltPolicyString_network;
- break;
- case service_manager::SANDBOX_TYPE_UTILITY:
- case service_manager::SANDBOX_TYPE_PROFILING:
- profile += service_manager::kSeatbeltPolicyString_utility;
- break;
- case service_manager::SANDBOX_TYPE_INVALID:
- case service_manager::SANDBOX_TYPE_FIRST_TYPE:
- case service_manager::SANDBOX_TYPE_AFTER_LAST_TYPE:
- CHECK(false);
- break;
- }
+ service_manager::SandboxMac::GetSandboxProfile(sandbox_type);
// Disable os logging to com.apple.diagnosticd which is a performance
// problem.
@@ -137,32 +92,8 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
seatbelt_exec_client_ = std::make_unique<sandbox::SeatbeltExecClient>();
seatbelt_exec_client_->SetProfile(profile);
- switch (sandbox_type) {
- case service_manager::SANDBOX_TYPE_CDM:
- SetupCDMSandboxParameters(seatbelt_exec_client_.get());
- break;
- case service_manager::SANDBOX_TYPE_GPU:
- case service_manager::SANDBOX_TYPE_NACL_LOADER:
- case service_manager::SANDBOX_TYPE_RENDERER:
- case service_manager::SANDBOX_TYPE_PDF_COMPOSITOR:
- case service_manager::SANDBOX_TYPE_AUDIO:
- SetupCommonSandboxParameters(seatbelt_exec_client_.get());
- break;
- case service_manager::SANDBOX_TYPE_NETWORK:
- SetupNetworkSandboxParameters(seatbelt_exec_client_.get());
- break;
- case service_manager::SANDBOX_TYPE_PPAPI:
- SetupPPAPISandboxParameters(seatbelt_exec_client_.get());
- break;
- case service_manager::SANDBOX_TYPE_UTILITY:
- case service_manager::SANDBOX_TYPE_PROFILING:
- SetupUtilitySandboxParameters(seatbelt_exec_client_.get(),
- *command_line_.get());
- break;
- default:
- CHECK(false) << "Unhandled parameters for sandbox_type "
- << sandbox_type;
- }
+ SetupSandboxParameters(sandbox_type, *command_line_.get(),
+ seatbelt_exec_client_.get());
int pipe = seatbelt_exec_client_->GetReadFD();
if (pipe < 0) {
diff --git a/chromium/content/browser/child_process_security_policy_unittest.cc b/chromium/content/browser/child_process_security_policy_unittest.cc
index 301cae01c8c..b29ae26950b 100644
--- a/chromium/content/browser/child_process_security_policy_unittest.cc
+++ b/chromium/content/browser/child_process_security_policy_unittest.cc
@@ -18,6 +18,7 @@
#include "content/public/common/url_constants.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"
#include "content/test/test_content_browser_client.h"
#include "storage/browser/fileapi/file_permission_policy.h"
#include "storage/browser/fileapi/file_system_url.h"
@@ -274,22 +275,20 @@ TEST_F(ChildProcessSecurityPolicyTest, StandardSchemesTest) {
// Dangerous to request, commit, or set as origin header.
EXPECT_FALSE(p->CanRequestURL(kRendererID,
GURL("file:///etc/passwd")));
- EXPECT_FALSE(p->CanRequestURL(kRendererID,
- GURL("chrome://foo/bar")));
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, GetWebUIURL("foo/bar")));
EXPECT_FALSE(p->CanRequestURL(kRendererID,
GURL("view-source:http://www.google.com/")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("file:///etc/passwd")));
- EXPECT_TRUE(p->CanRedirectToURL(GURL("chrome://foo/bar")));
+ EXPECT_TRUE(p->CanRedirectToURL(GetWebUIURL("foo/bar")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("view-source:http://www.google.com/")));
EXPECT_FALSE(p->CanCommitURL(kRendererID,
GURL("file:///etc/passwd")));
- EXPECT_FALSE(p->CanCommitURL(kRendererID,
- GURL("chrome://foo/bar")));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, GetWebUIURL("foo/bar")));
EXPECT_FALSE(
p->CanCommitURL(kRendererID, GURL("view-source:http://www.google.com/")));
EXPECT_FALSE(
p->CanSetAsOriginHeader(kRendererID, GURL("file:///etc/passwd")));
- EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, GURL("chrome://foo/bar")));
+ EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, GetWebUIURL("foo/bar")));
EXPECT_FALSE(p->CanSetAsOriginHeader(
kRendererID, GURL("view-source:http://www.google.com/")));
EXPECT_FALSE(p->CanRedirectToURL(GURL(kUnreachableWebDataURL)));
@@ -926,8 +925,8 @@ TEST_F(ChildProcessSecurityPolicyTest, CanServiceWebUIBindings) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
- const GURL url("chrome://thumb/http://www.google.com/");
- const GURL other_url("chrome://not-thumb/");
+ const GURL url(GetWebUIURL("thumb/http://www.google.com/"));
+ const GURL other_url(GetWebUIURL("not-thumb/"));
const url::Origin origin = url::Origin::Create(url);
{
p->Add(kRendererID, browser_context());
@@ -1244,9 +1243,9 @@ TEST_F(ChildProcessSecurityPolicyTest, OriginGranting) {
p->Add(kRendererID, browser_context());
- GURL url_foo1("chrome://foo/resource1");
- GURL url_foo2("chrome://foo/resource2");
- GURL url_bar("chrome://bar/resource3");
+ GURL url_foo1(GetWebUIURL("foo/resource1"));
+ GURL url_foo2(GetWebUIURL("foo/resource2"));
+ GURL url_bar(GetWebUIURL("bar/resource3"));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url_foo1));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url_foo2));
diff --git a/chromium/content/browser/code_cache/generated_code_cache.cc b/chromium/content/browser/code_cache/generated_code_cache.cc
index bef010a0b4e..e5bf3d6af19 100644
--- a/chromium/content/browser/code_cache/generated_code_cache.cc
+++ b/chromium/content/browser/code_cache/generated_code_cache.cc
@@ -209,7 +209,7 @@ void GeneratedCodeCache::GetBackend(GetBackendCallback callback) {
void GeneratedCodeCache::WriteData(const GURL& url,
const GURL& origin_lock,
const base::Time& response_time,
- const std::vector<uint8_t>& data) {
+ base::span<const uint8_t> data) {
// Silently ignore the requests.
if (backend_state_ == kFailed) {
CollectStatistics(CacheEntryStatus::kError);
@@ -225,8 +225,7 @@ void GeneratedCodeCache::WriteData(const GURL& url,
response_time.ToDeltaSinceWindowsEpoch().InMicroseconds();
memcpy(buffer->data(), &serialized_time, kResponseTimeSizeInBytes);
if (!data.empty())
- memcpy(buffer->data() + kResponseTimeSizeInBytes, &data.front(),
- data.size());
+ memcpy(buffer->data() + kResponseTimeSizeInBytes, data.data(), data.size());
std::string key = GetCacheKey(url, origin_lock);
// If there is an in progress operation corresponding to this key. Enqueue it
@@ -337,7 +336,6 @@ void GeneratedCodeCache::DidCreateBackend(
}
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_) {
diff --git a/chromium/content/browser/code_cache/generated_code_cache.h b/chromium/content/browser/code_cache/generated_code_cache.h
index 986bf031036..c9f481305b5 100644
--- a/chromium/content/browser/code_cache/generated_code_cache.h
+++ b/chromium/content/browser/code_cache/generated_code_cache.h
@@ -8,6 +8,7 @@
#include <queue>
#include "base/containers/queue.h"
+#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -90,7 +91,7 @@ class CONTENT_EXPORT GeneratedCodeCache {
void WriteData(const GURL& resource_url,
const GURL& origin_lock,
const base::Time& response_time,
- const std::vector<uint8_t>& data);
+ base::span<const uint8_t> data);
// Fetch entry corresponding to <resource_url, origin_lock> from the cache
// and return it using the ReadDataCallback.
diff --git a/chromium/content/browser/code_cache/generated_code_cache_unittest.cc b/chromium/content/browser/code_cache/generated_code_cache_unittest.cc
index 41cddee8bfb..04e0ad9c71c 100644
--- a/chromium/content/browser/code_cache/generated_code_cache_unittest.cc
+++ b/chromium/content/browser/code_cache/generated_code_cache_unittest.cc
@@ -367,4 +367,20 @@ TEST_F(GeneratedCodeCacheTest, WasmCache) {
ASSERT_TRUE(received_);
EXPECT_EQ(kInitialData, received_data_);
}
+
+TEST_F(GeneratedCodeCacheTest, TestFailedBackendOpening) {
+ GURL url(kInitialUrl);
+ GURL origin_lock = GURL(kInitialOrigin);
+
+ // Clear cache_path_ so the backend initialization fails.
+ cache_path_.clear();
+ InitializeCacheAndReOpen(GeneratedCodeCache::CodeCacheType::kJavaScript);
+ FetchFromCache(url, origin_lock);
+ scoped_task_environment_.RunUntilIdle();
+
+ // We should still receive a callback.
+ ASSERT_TRUE(received_);
+ // We shouldn't receive any data.
+ ASSERT_TRUE(received_null_);
+}
} // namespace content
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.cc b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
index 24cfe2fb6d7..79b2ae7b6fe 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
@@ -12,7 +12,7 @@
#include "base/strings/string_number_conversions.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/service/display/output_surface_client.h"
-#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
+#include "components/viz/service/display/overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.h"
#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
@@ -20,21 +20,14 @@ namespace content {
BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
scoped_refptr<viz::ContextProvider> context_provider,
- const viz::UpdateVSyncParametersCallback& update_vsync_parameters_callback,
- std::unique_ptr<viz::CompositorOverlayCandidateValidator>
- overlay_candidate_validator)
- : OutputSurface(std::move(context_provider)),
- update_vsync_parameters_callback_(update_vsync_parameters_callback),
- reflector_(nullptr) {
+ std::unique_ptr<viz::OverlayCandidateValidator> overlay_candidate_validator)
+ : OutputSurface(std::move(context_provider)) {
overlay_candidate_validator_ = std::move(overlay_candidate_validator);
}
BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
- std::unique_ptr<viz::SoftwareOutputDevice> software_device,
- const viz::UpdateVSyncParametersCallback& update_vsync_parameters_callback)
- : OutputSurface(std::move(software_device)),
- update_vsync_parameters_callback_(update_vsync_parameters_callback),
- reflector_(nullptr) {}
+ std::unique_ptr<viz::SoftwareOutputDevice> software_device)
+ : OutputSurface(std::move(software_device)) {}
BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() {
if (reflector_)
@@ -43,11 +36,6 @@ BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() {
}
void BrowserCompositorOutputSurface::SetReflector(ReflectorImpl* reflector) {
- // Software mirroring is done by doing a GL copy out of the framebuffer - if
- // we have overlays then that data will be missing.
- if (overlay_candidate_validator_) {
- overlay_candidate_validator_->SetSoftwareMirrorMode(reflector != nullptr);
- }
reflector_ = reflector;
OnReflectorChanged();
@@ -56,9 +44,9 @@ void BrowserCompositorOutputSurface::SetReflector(ReflectorImpl* reflector) {
void BrowserCompositorOutputSurface::OnReflectorChanged() {
}
-viz::OverlayCandidateValidator*
-BrowserCompositorOutputSurface::GetOverlayCandidateValidator() const {
- return overlay_candidate_validator_.get();
+std::unique_ptr<viz::OverlayCandidateValidator>
+BrowserCompositorOutputSurface::TakeOverlayCandidateValidator() {
+ return std::move(overlay_candidate_validator_);
}
bool BrowserCompositorOutputSurface::HasExternalStencilTest() const {
@@ -67,4 +55,13 @@ bool BrowserCompositorOutputSurface::HasExternalStencilTest() const {
void BrowserCompositorOutputSurface::ApplyExternalStencil() {}
+void BrowserCompositorOutputSurface::SetUpdateVSyncParametersCallback(
+ viz::UpdateVSyncParametersCallback callback) {
+ update_vsync_parameters_callback_ = std::move(callback);
+}
+
+gfx::OverlayTransform BrowserCompositorOutputSurface::GetDisplayTransform() {
+ return gfx::OVERLAY_TRANSFORM_NONE;
+}
+
} // namespace content
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.h b/chromium/content/browser/compositor/browser_compositor_output_surface.h
index dda4ac04b91..c91aedd1648 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.h
@@ -16,7 +16,7 @@ class SoftwareOutputDevice;
}
namespace viz {
-class CompositorOverlayCandidateValidator;
+class OverlayCandidateValidator;
}
namespace gfx {
@@ -32,9 +32,14 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
~BrowserCompositorOutputSurface() override;
// viz::OutputSurface implementation.
- viz::OverlayCandidateValidator* GetOverlayCandidateValidator() const override;
+ std::unique_ptr<viz::OverlayCandidateValidator>
+ TakeOverlayCandidateValidator() override;
bool HasExternalStencilTest() const override;
void ApplyExternalStencil() override;
+ void SetUpdateVSyncParametersCallback(
+ viz::UpdateVSyncParametersCallback callback) override;
+ void SetDisplayTransformHint(gfx::OverlayTransform transform) override {}
+ gfx::OverlayTransform GetDisplayTransform() override;
void SetReflector(ReflectorImpl* reflector);
@@ -43,25 +48,19 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
protected:
// Constructor used by the accelerated implementation.
- BrowserCompositorOutputSurface(
- scoped_refptr<viz::ContextProvider> context,
- const viz::UpdateVSyncParametersCallback&
- update_vsync_parameters_callback,
- std::unique_ptr<viz::CompositorOverlayCandidateValidator>
- overlay_candidate_validator);
+ BrowserCompositorOutputSurface(scoped_refptr<viz::ContextProvider> context,
+ std::unique_ptr<viz::OverlayCandidateValidator>
+ overlay_candidate_validator);
// Constructor used by the software implementation.
- BrowserCompositorOutputSurface(
- std::unique_ptr<viz::SoftwareOutputDevice> software_device,
- const viz::UpdateVSyncParametersCallback&
- update_vsync_parameters_callback);
+ explicit BrowserCompositorOutputSurface(
+ std::unique_ptr<viz::SoftwareOutputDevice> software_device);
- const viz::UpdateVSyncParametersCallback update_vsync_parameters_callback_;
- ReflectorImpl* reflector_;
+ viz::UpdateVSyncParametersCallback update_vsync_parameters_callback_;
+ ReflectorImpl* reflector_ = nullptr;
private:
- std::unique_ptr<viz::CompositorOverlayCandidateValidator>
- overlay_candidate_validator_;
+ std::unique_ptr<viz::OverlayCandidateValidator> overlay_candidate_validator_;
DISALLOW_COPY_AND_ASSIGN(BrowserCompositorOutputSurface);
};
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 b9838196165..05cf2f716d9 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -10,7 +10,7 @@
#include "build/build_config.h"
#include "components/viz/service/display/output_surface_client.h"
#include "components/viz/service/display/output_surface_frame.h"
-#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
+#include "components/viz/service/display/overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.h"
#include "content/browser/compositor/reflector_texture.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -26,11 +26,8 @@ namespace content {
GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface(
scoped_refptr<ws::ContextProviderCommandBuffer> context,
- const viz::UpdateVSyncParametersCallback& update_vsync_parameters_callback,
- std::unique_ptr<viz::CompositorOverlayCandidateValidator>
- overlay_candidate_validator)
+ std::unique_ptr<viz::OverlayCandidateValidator> overlay_candidate_validator)
: BrowserCompositorOutputSurface(std::move(context),
- update_vsync_parameters_callback,
std::move(overlay_candidate_validator)),
weak_ptr_factory_(this) {
if (capabilities_.uses_default_gl_framebuffer) {
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 8c728be50c5..8c068b856ab 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
@@ -14,7 +14,7 @@
#include "ui/latency/latency_tracker.h"
namespace viz {
-class CompositorOverlayCandidateValidator;
+class OverlayCandidateValidator;
}
namespace gfx {
@@ -41,9 +41,7 @@ class GpuBrowserCompositorOutputSurface
public:
GpuBrowserCompositorOutputSurface(
scoped_refptr<ws::ContextProviderCommandBuffer> context,
- const viz::UpdateVSyncParametersCallback&
- update_vsync_parameters_callback,
- std::unique_ptr<viz::CompositorOverlayCandidateValidator>
+ std::unique_ptr<viz::OverlayCandidateValidator>
overlay_candidate_validator);
~GpuBrowserCompositorOutputSurface() override;
diff --git a/chromium/content/browser/compositor/gpu_output_surface_mac.cc b/chromium/content/browser/compositor/gpu_output_surface_mac.cc
deleted file mode 100644
index 91ebbee3512..00000000000
--- a/chromium/content/browser/compositor/gpu_output_surface_mac.cc
+++ /dev/null
@@ -1,32 +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_output_surface_mac.h"
-
-#include "components/viz/service/display/output_surface_client.h"
-#include "components/viz/service/display/output_surface_frame.h"
-#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
-#include "gpu/GLES2/gl2extchromium.h"
-#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
-
-namespace content {
-
-GpuOutputSurfaceMac::GpuOutputSurfaceMac(
- scoped_refptr<ws::ContextProviderCommandBuffer> context,
- gpu::SurfaceHandle surface_handle,
- const viz::UpdateVSyncParametersCallback& update_vsync_parameters_callback,
- std::unique_ptr<viz::CompositorOverlayCandidateValidator>
- overlay_candidate_validator,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
- : GpuSurfacelessBrowserCompositorOutputSurface(
- std::move(context),
- surface_handle,
- update_vsync_parameters_callback,
- std::move(overlay_candidate_validator),
- gfx::BufferFormat::RGBA_8888,
- gpu_memory_buffer_manager) {}
-
-GpuOutputSurfaceMac::~GpuOutputSurfaceMac() {}
-
-} // namespace content
diff --git a/chromium/content/browser/compositor/gpu_output_surface_mac.h b/chromium/content/browser/compositor/gpu_output_surface_mac.h
deleted file mode 100644
index 573358ac2f5..00000000000
--- a/chromium/content/browser/compositor/gpu_output_surface_mac.h
+++ /dev/null
@@ -1,32 +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_OUTPUT_SURFACE_MAC_H_
-#define CONTENT_BROWSER_COMPOSITOR_GPU_OUTPUT_SURFACE_MAC_H_
-
-#include "content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h"
-
-#include "ui/gfx/native_widget_types.h"
-
-namespace content {
-
-class GpuOutputSurfaceMac
- : public GpuSurfacelessBrowserCompositorOutputSurface {
- public:
- GpuOutputSurfaceMac(scoped_refptr<ws::ContextProviderCommandBuffer> context,
- gpu::SurfaceHandle surface_handle,
- const viz::UpdateVSyncParametersCallback&
- update_vsync_parameters_callback,
- std::unique_ptr<viz::CompositorOverlayCandidateValidator>
- overlay_candidate_validator,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
- ~GpuOutputSurfaceMac() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GpuOutputSurfaceMac);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_COMPOSITOR_GPU_OUTPUT_SURFACE_MAC_H_
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.cc b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
index 99c703a1ba1..7e3574cb69f 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
@@ -33,9 +33,10 @@
#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/overlay_candidate_validator.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/server_shared_bitmap_manager.h"
+#include "components/viz/service/display_embedder/vsync_parameter_listener.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"
@@ -65,7 +66,6 @@
#include "gpu/vulkan/buildflags.h"
#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/khronos/GLES2/gl2.h"
-#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/host/external_begin_frame_controller_client_impl.h"
@@ -76,20 +76,8 @@
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
-#if defined(USE_AURA)
-#include "content/public/common/service_manager_connection.h"
-#include "ui/aura/env.h"
-#include "ui/aura/window_tree_host.h"
-#endif
-
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.h"
-#include "components/viz/service/display_embedder/output_device_backing.h"
-#include "components/viz/service/display_embedder/software_output_device_win.h"
-#include "ui/gfx/win/rendering_window_manager.h"
-#elif defined(USE_OZONE)
-#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.h"
+#if defined(USE_OZONE)
+#include "components/viz/service/display_embedder/overlay_candidate_validator_ozone.h"
#include "components/viz/service/display_embedder/software_output_device_ozone.h"
#include "ui/ozone/public/overlay_candidates_ozone.h"
#include "ui/ozone/public/overlay_manager_ozone.h"
@@ -100,12 +88,6 @@
#include "ui/ozone/public/surface_ozone_canvas.h"
#elif defined(USE_X11)
#include "components/viz/service/display_embedder/software_output_device_x11.h"
-#elif defined(OS_MACOSX)
-#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator_mac.h"
-#include "components/viz/service/display_embedder/software_output_device_mac.h"
-#include "content/browser/compositor/gpu_output_surface_mac.h"
-#include "ui/base/cocoa/remote_layer_api.h"
-#include "ui/base/ui_base_switches.h"
#endif
#if !defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW)
#include "gpu/ipc/common/gpu_surface_tracker.h"
@@ -131,11 +113,33 @@ constexpr char kIdentityUrl[] =
constexpr gpu::SchedulingPriority kStreamPriority =
content::kGpuStreamPriorityUI;
-#if defined(OS_MACOSX)
-bool IsCALayersDisabledFromCommandLine() {
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- return command_line->HasSwitch(switches::kDisableMacOverlays);
-}
+#if defined(USE_X11)
+class HostDisplayClient : public viz::HostDisplayClient {
+ public:
+ explicit HostDisplayClient(ui::Compositor* compositor)
+ : viz::HostDisplayClient(compositor->widget()), compositor_(compositor) {}
+ ~HostDisplayClient() override = default;
+
+ // viz::HostDisplayClient:
+ void DidCompleteSwapWithNewSize(const gfx::Size& size) override {
+ compositor_->OnCompleteSwapWithNewSize(size);
+ }
+
+ private:
+ ui::Compositor* const compositor_;
+
+ DISALLOW_COPY_AND_ASSIGN(HostDisplayClient);
+};
+#else
+class HostDisplayClient : public viz::HostDisplayClient {
+ public:
+ explicit HostDisplayClient(ui::Compositor* compositor)
+ : viz::HostDisplayClient(compositor->widget()) {}
+ ~HostDisplayClient() override = default;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HostDisplayClient);
+};
#endif
} // namespace
@@ -145,6 +149,12 @@ namespace content {
struct GpuProcessTransportFactory::PerCompositorData {
gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
BrowserCompositorOutputSurface* display_output_surface = nullptr;
+ // The |overlay_validator| pointer is used to pass settings for software
+ // mirror mode. The lifetime of the validator is the same as the
+ // |display_output_surface|.
+ // TODO(weiliangc): Remove this once software mirroring code path does not
+ // have to go though validator.
+ viz::OverlayCandidateValidator* overlay_validator = nullptr;
// 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;
@@ -156,6 +166,7 @@ struct GpuProcessTransportFactory::PerCompositorData {
std::unique_ptr<viz::Display> display;
std::unique_ptr<viz::mojom::DisplayClient> display_client;
bool output_is_secure = false;
+ std::unique_ptr<viz::VSyncParameterListener> vsync_listener;
};
GpuProcessTransportFactory::GpuProcessTransportFactory(
@@ -186,9 +197,6 @@ GpuProcessTransportFactory::GpuProcessTransportFactory(
task_graph_runner_->Start("CompositorTileWorker1",
base::SimpleThread::Options());
-#if defined(OS_WIN)
- software_backing_ = std::make_unique<viz::OutputDeviceBacking>();
-#endif
if (command_line->HasSwitch(switches::kDisableGpu) ||
command_line->HasSwitch(switches::kDisableGpuCompositing)) {
@@ -216,17 +224,8 @@ GpuProcessTransportFactory::CreateSoftwareOutputDevice(
if (command_line->HasSwitch(switches::kHeadless))
return base::WrapUnique(new viz::SoftwareOutputDevice);
-#if defined(USE_AURA)
- if (features::IsMultiProcessMash()) {
- NOTREACHED();
- return nullptr;
- }
-#endif
-
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-#if defined(OS_WIN)
- return CreateSoftwareOutputDeviceWinBrowser(widget, software_backing_.get());
-#elif defined(USE_OZONE)
+#if defined(USE_OZONE)
ui::SurfaceFactoryOzone* factory =
ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone();
std::unique_ptr<ui::PlatformWindowSurface> platform_window_surface =
@@ -238,23 +237,15 @@ GpuProcessTransportFactory::CreateSoftwareOutputDevice(
std::move(platform_window_surface), std::move(surface_ozone));
#elif defined(USE_X11)
return std::make_unique<viz::SoftwareOutputDeviceX11>(widget);
-#elif defined(OS_MACOSX)
- return std::make_unique<viz::SoftwareOutputDeviceMac>(std::move(task_runner));
#else
NOTREACHED();
return std::unique_ptr<viz::SoftwareOutputDevice>();
#endif
}
-std::unique_ptr<viz::CompositorOverlayCandidateValidator>
-CreateOverlayCandidateValidator(
-#if defined(OS_MACOSX)
- gfx::AcceleratedWidget widget,
- bool disable_overlay_ca_layers) {
-#else
+std::unique_ptr<viz::OverlayCandidateValidator> CreateOverlayCandidateValidator(
gfx::AcceleratedWidget widget) {
-#endif
- std::unique_ptr<viz::CompositorOverlayCandidateValidator> validator;
+ std::unique_ptr<viz::OverlayCandidateValidator> validator;
#if defined(USE_OZONE)
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -271,22 +262,10 @@ CreateOverlayCandidateValidator(
if (!enable_overlay_flag.empty()) {
std::unique_ptr<ui::OverlayCandidatesOzone> overlay_candidates =
ozone_platform->GetOverlayManager()->CreateOverlayCandidates(widget);
- validator.reset(new viz::CompositorOverlayCandidateValidatorOzone(
+ validator.reset(new viz::OverlayCandidateValidatorOzone(
std::move(overlay_candidates),
viz::ParseOverlayStategies(enable_overlay_flag)));
}
-#elif defined(OS_MACOSX)
- // Overlays are only supported through the remote layer API.
- if (ui::RemoteLayerAPISupported()) {
- static bool overlays_disabled_at_command_line =
- IsCALayersDisabledFromCommandLine();
- const bool ca_layers_disabled =
- overlays_disabled_at_command_line || disable_overlay_ca_layers;
- validator.reset(
- new viz::CompositorOverlayCandidateValidatorMac(ca_layers_disabled));
- }
-#elif defined(OS_WIN)
- validator = std::make_unique<viz::CompositorOverlayCandidateValidatorWin>();
#endif
return validator;
@@ -303,13 +282,9 @@ void GpuProcessTransportFactory::CreateLayerTreeFrameSink(
// |data->begin_frame_source| here when the compositor destroys its
// LayerTreeFrameSink before calling back here.
data->display_output_surface = nullptr;
+ data->overlay_validator = nullptr;
}
-#if defined(OS_WIN)
- gfx::RenderingWindowManager::GetInstance()->UnregisterParent(
- compositor->widget());
-#endif
-
const bool use_gpu_compositing =
!compositor->force_software_compositor() && !is_gpu_compositing_disabled_;
if (use_gpu_compositing) {
@@ -356,11 +331,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
support_stencil = true;
#endif
-#if defined(OS_WIN)
- gfx::RenderingWindowManager::GetInstance()->RegisterParent(
- compositor->widget());
-#endif
-
scoped_refptr<ws::ContextProviderCommandBuffer> context_provider;
if (!use_gpu_compositing) {
@@ -437,9 +407,8 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
}
}
- auto vsync_callback = base::BindRepeating(
- &ui::Compositor::SetDisplayVSyncParameters, compositor);
std::unique_ptr<BrowserCompositorOutputSurface> display_output_surface;
+ viz::OverlayCandidateValidator* overlay_validator = nullptr;
if (!use_gpu_compositing) {
if (!is_gpu_compositing_disabled_ &&
!compositor->force_software_compositor()) {
@@ -453,60 +422,47 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
display_output_surface =
std::make_unique<SoftwareBrowserCompositorOutputSurface>(
CreateSoftwareOutputDevice(compositor->widget(),
- compositor->task_runner()),
- std::move(vsync_callback));
+ compositor->task_runner()));
} else {
DCHECK(context_provider);
const auto& capabilities = context_provider->ContextCapabilities();
if (data->surface_handle == gpu::kNullSurfaceHandle) {
display_output_surface =
std::make_unique<OffscreenBrowserCompositorOutputSurface>(
- context_provider, std::move(vsync_callback),
- std::unique_ptr<viz::CompositorOverlayCandidateValidator>());
+ context_provider,
+ std::unique_ptr<viz::OverlayCandidateValidator>());
} else if (capabilities.surfaceless) {
-#if defined(OS_MACOSX)
- const auto& gpu_feature_info = context_provider->GetGpuFeatureInfo();
- bool disable_overlay_ca_layers =
- gpu_feature_info.IsWorkaroundEnabled(gpu::DISABLE_OVERLAY_CA_LAYERS);
- display_output_surface = std::make_unique<GpuOutputSurfaceMac>(
- context_provider, data->surface_handle, vsync_callback,
- CreateOverlayCandidateValidator(compositor->widget(),
- disable_overlay_ca_layers),
- GetGpuMemoryBufferManager());
-#else
DCHECK(capabilities.texture_format_bgra8888);
+ auto validator = CreateOverlayCandidateValidator(compositor->widget());
+ overlay_validator = validator.get();
auto gpu_output_surface =
std::make_unique<GpuSurfacelessBrowserCompositorOutputSurface>(
- context_provider, data->surface_handle, std::move(vsync_callback),
- CreateOverlayCandidateValidator(compositor->widget()),
+ context_provider, data->surface_handle, std::move(validator),
display::DisplaySnapshot::PrimaryFormat(),
GetGpuMemoryBufferManager());
display_output_surface = std::move(gpu_output_surface);
-#endif
} else {
- std::unique_ptr<viz::CompositorOverlayCandidateValidator> validator;
-#if defined(OS_WIN)
- const bool use_overlays_for_sw_protected_video =
- base::FeatureList::IsEnabled(
- features::kUseDCOverlaysForSoftwareProtectedVideo);
- if (capabilities.dc_layers && (capabilities.use_dc_overlays_for_video ||
- use_overlays_for_sw_protected_video))
- validator = CreateOverlayCandidateValidator(compositor->widget());
-#elif !defined(OS_MACOSX)
- // Overlays are only supported on surfaceless output surfaces on Mac.
- validator = CreateOverlayCandidateValidator(compositor->widget());
-#endif
+ std::unique_ptr<viz::OverlayCandidateValidator> validator =
+ CreateOverlayCandidateValidator(compositor->widget());
+ overlay_validator = validator.get();
auto gpu_output_surface =
std::make_unique<GpuBrowserCompositorOutputSurface>(
- context_provider, std::move(vsync_callback),
- std::move(validator));
+ context_provider, std::move(validator));
display_output_surface = std::move(gpu_output_surface);
}
}
+ data->overlay_validator = overlay_validator;
+
+ auto vsync_callback = base::BindRepeating(
+ &ui::Compositor::SetDisplayVSyncParameters, compositor);
+ display_output_surface->SetUpdateVSyncParametersCallback(vsync_callback);
+
data->display_output_surface = display_output_surface.get();
- if (data->reflector)
- data->reflector->OnSourceSurfaceReady(data->display_output_surface);
+ if (data->reflector) {
+ data->reflector->OnSourceSurfaceReady(data->display_output_surface,
+ data->overlay_validator);
+ }
std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_begin_frame_source;
std::unique_ptr<viz::ExternalBeginFrameSourceMojo>
@@ -563,8 +519,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
server_shared_bitmap_manager_, viz::CreateRendererSettings(),
compositor->frame_sink_id(), std::move(display_output_surface),
std::move(scheduler), compositor->task_runner());
- data->display_client =
- std::make_unique<viz::HostDisplayClient>(compositor->widget());
+ data->display_client = std::make_unique<HostDisplayClient>(compositor.get());
GetFrameSinkManager()->RegisterBeginFrameSource(begin_frame_source,
compositor->frame_sink_id());
// Note that we are careful not to destroy prior BeginFrameSource objects
@@ -651,8 +606,10 @@ std::unique_ptr<ui::Reflector> GpuProcessTransportFactory::CreateReflector(
std::unique_ptr<ReflectorImpl> reflector(
new ReflectorImpl(source_compositor, target_layer));
source_data->reflector = reflector.get();
- if (auto* source_surface = source_data->display_output_surface)
- reflector->OnSourceSurfaceReady(source_surface);
+ if (auto* source_surface = source_data->display_output_surface) {
+ reflector->OnSourceSurfaceReady(source_surface,
+ source_data->overlay_validator);
+ }
return std::move(reflector);
}
@@ -690,10 +647,6 @@ void GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
for (auto& observer : observer_list_)
observer.OnLostSharedContext();
}
-#if defined(OS_WIN)
- gfx::RenderingWindowManager::GetInstance()->UnregisterParent(
- compositor->widget());
-#endif
}
gpu::GpuMemoryBufferManager*
@@ -807,6 +760,8 @@ void GpuProcessTransportFactory::SetDisplayVSyncParameters(
if (data->synthetic_begin_frame_source) {
data->synthetic_begin_frame_source->OnUpdateVSyncParameters(timebase,
interval);
+ if (data->vsync_listener)
+ data->vsync_listener->OnVSyncParametersUpdated(timebase, interval);
}
}
@@ -834,6 +789,18 @@ void GpuProcessTransportFactory::SetOutputIsSecure(ui::Compositor* compositor,
data->display->SetOutputIsSecure(secure);
}
+void GpuProcessTransportFactory::AddVSyncParameterObserver(
+ ui::Compositor* compositor,
+ viz::mojom::VSyncParameterObserverPtr observer) {
+ auto it = per_compositor_data_.find(compositor);
+ if (it == per_compositor_data_.end())
+ return;
+ PerCompositorData* data = it->second.get();
+ DCHECK(data);
+ data->vsync_listener =
+ std::make_unique<viz::VSyncParameterListener>(std::move(observer));
+}
+
void GpuProcessTransportFactory::AddObserver(
ui::ContextFactoryObserver* observer) {
observer_list_.AddObserver(observer);
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.h b/chromium/content/browser/compositor/gpu_process_transport_factory.h
index 525fa0c06b3..4a78bdea7de 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.h
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.h
@@ -40,7 +40,6 @@ class GpuChannelEstablishFactory;
namespace viz {
class CompositingModeReporterImpl;
-class OutputDeviceBacking;
class RasterContextProvider;
class ServerSharedBitmapManager;
class SoftwareOutputDevice;
@@ -101,6 +100,9 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
void IssueExternalBeginFrame(ui::Compositor* compositor,
const viz::BeginFrameArgs& args) override;
void SetOutputIsSecure(ui::Compositor* compositor, bool secure) override;
+ void AddVSyncParameterObserver(
+ ui::Compositor* compositor,
+ viz::mojom::VSyncParameterObserverPtr observer) override;
// ImageTransportFactory implementation.
void DisableGpuCompositing() override;
@@ -143,11 +145,6 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
viz::FrameSinkIdAllocator frame_sink_id_allocator_;
-#if defined(OS_WIN)
- // Used by output surface, stored in PerCompositorData.
- std::unique_ptr<viz::OutputDeviceBacking> software_backing_;
-#endif
-
// Depends on SurfaceManager.
typedef std::map<ui::Compositor*, std::unique_ptr<PerCompositorData>>
PerCompositorDataMap;
diff --git a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
index 4d4f7136b09..eed5a25fcc2 100644
--- a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
@@ -8,8 +8,8 @@
#include "components/viz/service/display/output_surface_client.h"
#include "components/viz/service/display/output_surface_frame.h"
+#include "components/viz/service/display/overlay_candidate_validator.h"
#include "components/viz/service/display_embedder/buffer_queue.h"
-#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
@@ -22,14 +22,11 @@ GpuSurfacelessBrowserCompositorOutputSurface::
GpuSurfacelessBrowserCompositorOutputSurface(
scoped_refptr<ws::ContextProviderCommandBuffer> context,
gpu::SurfaceHandle surface_handle,
- const viz::UpdateVSyncParametersCallback&
- update_vsync_parameters_callback,
- std::unique_ptr<viz::CompositorOverlayCandidateValidator>
+ std::unique_ptr<viz::OverlayCandidateValidator>
overlay_candidate_validator,
gfx::BufferFormat format,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
: GpuBrowserCompositorOutputSurface(std::move(context),
- update_vsync_parameters_callback,
std::move(overlay_candidate_validator)),
use_gpu_fence_(
context_provider_->ContextCapabilities().chromium_gpu_fence &&
diff --git a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
index af364ef1362..238c2bcd86d 100644
--- a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
@@ -27,9 +27,7 @@ class GpuSurfacelessBrowserCompositorOutputSurface
GpuSurfacelessBrowserCompositorOutputSurface(
scoped_refptr<ws::ContextProviderCommandBuffer> context,
gpu::SurfaceHandle surface_handle,
- const viz::UpdateVSyncParametersCallback&
- update_vsync_parameters_callback,
- std::unique_ptr<viz::CompositorOverlayCandidateValidator>
+ std::unique_ptr<viz::OverlayCandidateValidator>
overlay_candidate_validator,
gfx::BufferFormat format,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
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 dfedf6a60eb..c38198dfe82 100644
--- a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
@@ -12,7 +12,7 @@
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/service/display/output_surface_client.h"
#include "components/viz/service/display/output_surface_frame.h"
-#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
+#include "components/viz/service/display/overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.h"
#include "content/browser/compositor/reflector_texture.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -32,12 +32,9 @@ static viz::ResourceFormat kFboTextureFormat = viz::RGBA_8888;
OffscreenBrowserCompositorOutputSurface::
OffscreenBrowserCompositorOutputSurface(
scoped_refptr<ws::ContextProviderCommandBuffer> context,
- const viz::UpdateVSyncParametersCallback&
- update_vsync_parameters_callback,
- std::unique_ptr<viz::CompositorOverlayCandidateValidator>
+ std::unique_ptr<viz::OverlayCandidateValidator>
overlay_candidate_validator)
: BrowserCompositorOutputSurface(std::move(context),
- update_vsync_parameters_callback,
std::move(overlay_candidate_validator)),
weak_ptr_factory_(this) {
capabilities_.uses_default_gl_framebuffer = false;
diff --git a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
index 9751f1e74d8..9756ca6f5bc 100644
--- a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
@@ -29,9 +29,7 @@ class OffscreenBrowserCompositorOutputSurface
public:
OffscreenBrowserCompositorOutputSurface(
scoped_refptr<ws::ContextProviderCommandBuffer> context,
- const viz::UpdateVSyncParametersCallback&
- update_vsync_parameters_callback,
- std::unique_ptr<viz::CompositorOverlayCandidateValidator>
+ std::unique_ptr<viz::OverlayCandidateValidator>
overlay_candidate_validator);
~OffscreenBrowserCompositorOutputSurface() override;
diff --git a/chromium/content/browser/compositor/reflector_impl.cc b/chromium/content/browser/compositor/reflector_impl.cc
index b41cb5b429a..a74a3d7be5a 100644
--- a/chromium/content/browser/compositor/reflector_impl.cc
+++ b/chromium/content/browser/compositor/reflector_impl.cc
@@ -6,6 +6,7 @@
#include "base/location.h"
#include "components/viz/common/resources/transferable_resource.h"
+#include "components/viz/service/display/overlay_candidate_validator.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "content/browser/compositor/owned_mailbox.h"
#include "third_party/khronos/GLES2/gl2.h"
@@ -24,6 +25,7 @@ ReflectorImpl::ReflectorImpl(ui::Compositor* mirrored_compositor,
ui::Layer* mirroring_layer)
: mirrored_compositor_(mirrored_compositor),
flip_texture_(false),
+ overlay_validator_(nullptr),
output_surface_(nullptr) {
if (mirroring_layer)
AddMirroringLayer(mirroring_layer);
@@ -41,15 +43,19 @@ void ReflectorImpl::Shutdown() {
void ReflectorImpl::DetachFromOutputSurface() {
DCHECK(output_surface_);
output_surface_->SetReflector(nullptr);
+ if (overlay_validator_)
+ overlay_validator_->SetSoftwareMirrorMode(false);
DCHECK(mailbox_);
mailbox_.reset();
output_surface_ = nullptr;
+ overlay_validator_ = nullptr;
for (const auto& layer_data : mirroring_layers_)
layer_data->layer->SetShowSolidColorContent();
}
void ReflectorImpl::OnSourceSurfaceReady(
- BrowserCompositorOutputSurface* output_surface) {
+ BrowserCompositorOutputSurface* output_surface,
+ viz::OverlayCandidateValidator* overlay_validator) {
if (mirroring_layers_.empty())
return; // Was already Shutdown().
if (output_surface == output_surface_)
@@ -58,10 +64,13 @@ void ReflectorImpl::OnSourceSurfaceReady(
DetachFromOutputSurface();
output_surface_ = output_surface;
+ overlay_validator_ = overlay_validator;
flip_texture_ = !output_surface->capabilities().flipped_output_surface;
output_surface_->SetReflector(this);
+ if (overlay_validator_)
+ overlay_validator_->SetSoftwareMirrorMode(true);
}
void ReflectorImpl::OnMirroringCompositorResized() {
@@ -151,9 +160,10 @@ void ReflectorImpl::UpdateTexture(ReflectorImpl::LayerData* layer_data,
const gfx::Rect& redraw_rect) {
if (layer_data->needs_set_mailbox) {
layer_data->layer->SetTransferableResource(
- viz::TransferableResource::MakeGL(mailbox_->holder().mailbox, GL_LINEAR,
- mailbox_->holder().texture_target,
- mailbox_->holder().sync_token),
+ viz::TransferableResource::MakeGL(
+ mailbox_->holder().mailbox, GL_LINEAR,
+ mailbox_->holder().texture_target, mailbox_->holder().sync_token,
+ source_size, false /* is_overlay_candidate */),
mailbox_->GetSingleReleaseCallback(), source_size);
layer_data->needs_set_mailbox = false;
} else {
diff --git a/chromium/content/browser/compositor/reflector_impl.h b/chromium/content/browser/compositor/reflector_impl.h
index a603b0757ae..4ba31e0f319 100644
--- a/chromium/content/browser/compositor/reflector_impl.h
+++ b/chromium/content/browser/compositor/reflector_impl.h
@@ -23,6 +23,10 @@ class Compositor;
class Layer;
}
+namespace viz {
+class OverlayCandidateValidator;
+}
+
namespace content {
class OwnedMailbox;
@@ -57,7 +61,8 @@ class CONTENT_EXPORT ReflectorImpl : public ui::Reflector {
const gfx::Size& surface_size);
// Called when the source surface is bound and available.
- void OnSourceSurfaceReady(BrowserCompositorOutputSurface* surface);
+ void OnSourceSurfaceReady(BrowserCompositorOutputSurface* surface,
+ viz::OverlayCandidateValidator* overlay_validator);
// Called when the mailbox which has the source surface's texture
// is updated.
@@ -77,6 +82,7 @@ class CONTENT_EXPORT ReflectorImpl : public ui::Reflector {
scoped_refptr<OwnedMailbox> mailbox_;
bool flip_texture_;
+ viz::OverlayCandidateValidator* overlay_validator_;
BrowserCompositorOutputSurface* output_surface_;
DISALLOW_COPY_AND_ASSIGN(ReflectorImpl);
diff --git a/chromium/content/browser/compositor/reflector_impl_unittest.cc b/chromium/content/browser/compositor/reflector_impl_unittest.cc
index d3fc3f8c0ef..0892cf1ad2f 100644
--- a/chromium/content/browser/compositor/reflector_impl_unittest.cc
+++ b/chromium/content/browser/compositor/reflector_impl_unittest.cc
@@ -14,7 +14,7 @@
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/frame_sinks/delay_based_time_source.h"
#include "components/viz/service/display/output_surface_frame.h"
-#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
+#include "components/viz/service/display/overlay_candidate_validator.h"
#include "components/viz/test/test_context_provider.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "content/browser/compositor/reflector_texture.h"
@@ -22,11 +22,11 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
-#include "ui/compositor/test/context_factories_for_test.h"
+#include "ui/compositor/test/test_context_factories.h"
#if defined(USE_OZONE)
#include "components/viz/service/display/overlay_candidate.h"
-#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.h"
+#include "components/viz/service/display_embedder/overlay_candidate_validator_ozone.h"
#include "ui/ozone/public/overlay_candidates_ozone.h"
#endif // defined(USE_OZONE)
@@ -64,12 +64,11 @@ class TestOverlayCandidatesOzone : public ui::OverlayCandidatesOzone {
};
#endif // defined(USE_OZONE)
-std::unique_ptr<viz::CompositorOverlayCandidateValidator>
-CreateTestValidatorOzone() {
+std::unique_ptr<viz::OverlayCandidateValidator> CreateTestValidatorOzone() {
#if defined(USE_OZONE)
std::vector<viz::OverlayStrategy> strategies = {
viz::OverlayStrategy::kSingleOnTop, viz::OverlayStrategy::kUnderlay};
- return std::make_unique<viz::CompositorOverlayCandidateValidatorOzone>(
+ return std::make_unique<viz::OverlayCandidateValidatorOzone>(
std::make_unique<TestOverlayCandidatesOzone>(), std::move(strategies));
#else
return nullptr;
@@ -79,9 +78,7 @@ CreateTestValidatorOzone() {
class TestOutputSurface : public BrowserCompositorOutputSurface {
public:
TestOutputSurface(scoped_refptr<viz::ContextProvider> context_provider)
- : BrowserCompositorOutputSurface(std::move(context_provider),
- viz::UpdateVSyncParametersCallback(),
- CreateTestValidatorOzone()) {}
+ : BrowserCompositorOutputSurface(std::move(context_provider), nullptr) {}
void SetFlip(bool flip) { capabilities_.flipped_output_surface = flip; }
@@ -126,12 +123,10 @@ const gfx::Size kSurfaceSize(256, 256);
class ReflectorImplTest : public testing::Test {
public:
void SetUp() override {
- bool enable_pixel_output = false;
- ui::ContextFactory* context_factory = nullptr;
- ui::ContextFactoryPrivate* context_factory_private = nullptr;
+ const bool enable_pixel_output = false;
+ context_factories_ =
+ std::make_unique<ui::TestContextFactories>(enable_pixel_output);
- ui::InitializeContextFactoryForTests(enable_pixel_output, &context_factory,
- &context_factory_private);
ImageTransportFactory::SetFactory(
std::make_unique<TestImageTransportFactory>());
task_runner_ = base::ThreadTaskRunnerHandle::Get();
@@ -140,16 +135,18 @@ class ReflectorImplTest : public testing::Test {
std::make_unique<viz::DelayBasedTimeSource>(
compositor_task_runner_.get()),
viz::BeginFrameSource::kNotRestartableId);
- compositor_.reset(new ui::Compositor(
- context_factory_private->AllocateFrameSinkId(), context_factory,
- context_factory_private, compositor_task_runner_.get(),
- false /* enable_pixel_canvas */));
+ compositor_ = std::make_unique<ui::Compositor>(
+ context_factories_->GetContextFactoryPrivate()->AllocateFrameSinkId(),
+ context_factories_->GetContextFactory(),
+ context_factories_->GetContextFactoryPrivate(),
+ compositor_task_runner_.get(), false /* enable_pixel_canvas */);
compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
auto context_provider = viz::TestContextProvider::Create();
context_provider->BindToCurrentThread();
output_surface_ =
std::make_unique<TestOutputSurface>(std::move(context_provider));
+ overlay_validator_ = CreateTestValidatorOzone();
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
compositor_->SetRootLayer(root_layer_.get());
@@ -163,7 +160,8 @@ class ReflectorImplTest : public testing::Test {
void SetUpReflector() {
reflector_ = std::make_unique<ReflectorImpl>(compositor_.get(),
mirroring_layer_.get());
- reflector_->OnSourceSurfaceReady(output_surface_.get());
+ reflector_->OnSourceSurfaceReady(output_surface_.get(),
+ overlay_validator_.get());
}
void TearDown() override {
@@ -176,7 +174,7 @@ class ReflectorImplTest : public testing::Test {
release->Run(gpu::SyncToken(), false);
}
compositor_.reset();
- ui::TerminateContextFactoryForTests();
+ context_factories_.reset();
ImageTransportFactory::Terminate();
}
@@ -184,7 +182,14 @@ class ReflectorImplTest : public testing::Test {
reflector_->OnSourcePostSubBuffer(kSubRect, kSurfaceSize);
}
+#if defined(USE_OZONE)
+ void CheckOverlaySupport(viz::OverlayCandidateList* surfaces) {
+ overlay_validator_->CheckOverlaySupport(surfaces);
+ }
+#endif // defined(USE_OZONE)
+
protected:
+ std::unique_ptr<ui::TestContextFactories> context_factories_;
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
std::unique_ptr<viz::SyntheticBeginFrameSource> begin_frame_source_;
base::test::ScopedTaskEnvironment task_environment_;
@@ -194,6 +199,7 @@ class ReflectorImplTest : public testing::Test {
std::unique_ptr<ui::Layer> mirroring_layer_;
std::unique_ptr<ReflectorImpl> reflector_;
std::unique_ptr<TestOutputSurface> output_surface_;
+ std::unique_ptr<viz::OverlayCandidateValidator> overlay_validator_;
};
namespace {
@@ -235,7 +241,7 @@ TEST_F(ReflectorImplTest, CheckOverlayNoReflector) {
plane_2.plane_z_order = 1;
list.push_back(plane_1);
list.push_back(plane_2);
- output_surface_->GetOverlayCandidateValidator()->CheckOverlaySupport(&list);
+ CheckOverlaySupport(&list);
EXPECT_TRUE(list[0].overlay_handled);
}
@@ -251,7 +257,7 @@ TEST_F(ReflectorImplTest, CheckOverlaySWMirroring) {
plane_2.plane_z_order = 1;
list.push_back(plane_1);
list.push_back(plane_2);
- output_surface_->GetOverlayCandidateValidator()->CheckOverlaySupport(&list);
+ CheckOverlaySupport(&list);
EXPECT_FALSE(list[0].overlay_handled);
}
#endif // defined(USE_OZONE)
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 0f13e98f516..d48e93fd685 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
@@ -21,10 +21,8 @@
namespace content {
SoftwareBrowserCompositorOutputSurface::SoftwareBrowserCompositorOutputSurface(
- std::unique_ptr<viz::SoftwareOutputDevice> software_device,
- const viz::UpdateVSyncParametersCallback& update_vsync_parameters_callback)
- : BrowserCompositorOutputSurface(std::move(software_device),
- update_vsync_parameters_callback),
+ std::unique_ptr<viz::SoftwareOutputDevice> software_device)
+ : BrowserCompositorOutputSurface(std::move(software_device)),
weak_factory_(this) {}
SoftwareBrowserCompositorOutputSurface::
@@ -87,9 +85,14 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
}
void SoftwareBrowserCompositorOutputSurface::SwapBuffersCallback(
- const std::vector<ui::LatencyInfo>& latency_info) {
+ const std::vector<ui::LatencyInfo>& latency_info,
+ const gfx::Size& pixel_size) {
latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
client_->DidReceiveSwapBuffersAck();
+#if defined(USE_X11)
+ if (needs_swap_size_notifications_)
+ client_->DidSwapWithSize(pixel_size);
+#endif
client_->DidReceivePresentationFeedback(
gfx::PresentationFeedback(base::TimeTicks::Now(), refresh_interval_, 0u));
}
@@ -98,7 +101,8 @@ void SoftwareBrowserCompositorOutputSurface::UpdateVSyncCallback(
const base::TimeTicks timebase,
const base::TimeDelta interval) {
refresh_interval_ = interval;
- update_vsync_parameters_callback_.Run(timebase, interval);
+ if (update_vsync_parameters_callback_)
+ update_vsync_parameters_callback_.Run(timebase, interval);
}
bool SoftwareBrowserCompositorOutputSurface::IsDisplayedAsOverlayPlane() const {
@@ -125,4 +129,11 @@ unsigned SoftwareBrowserCompositorOutputSurface::UpdateGpuFence() {
return 0;
}
+#if defined(USE_X11)
+void SoftwareBrowserCompositorOutputSurface::SetNeedsSwapSizeNotifications(
+ bool needs_swap_size_notifications) {
+ needs_swap_size_notifications_ = needs_swap_size_notifications;
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface.h b/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
index fa54dcb649e..9a838454c53 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
@@ -17,10 +17,8 @@ namespace content {
class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface
: public BrowserCompositorOutputSurface {
public:
- SoftwareBrowserCompositorOutputSurface(
- std::unique_ptr<viz::SoftwareOutputDevice> software_device,
- const viz::UpdateVSyncParametersCallback&
- update_vsync_parameters_callback);
+ explicit SoftwareBrowserCompositorOutputSurface(
+ std::unique_ptr<viz::SoftwareOutputDevice> software_device);
~SoftwareBrowserCompositorOutputSurface() override;
@@ -41,15 +39,25 @@ class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface
gfx::BufferFormat GetOverlayBufferFormat() const override;
uint32_t GetFramebufferCopyTextureFormat() override;
unsigned UpdateGpuFence() override;
+#if defined(USE_X11)
+ void SetNeedsSwapSizeNotifications(
+ bool needs_swap_size_notifications) override;
+#endif
private:
- void SwapBuffersCallback(const std::vector<ui::LatencyInfo>& latency_info);
+ void SwapBuffersCallback(const std::vector<ui::LatencyInfo>& latency_info,
+ const gfx::Size& pixel_size);
void UpdateVSyncCallback(const base::TimeTicks timebase,
const base::TimeDelta interval);
viz::OutputSurfaceClient* client_ = nullptr;
base::TimeDelta refresh_interval_;
ui::LatencyTracker latency_tracker_;
+
+#if defined(USE_X11)
+ bool needs_swap_size_notifications_ = false;
+#endif
+
base::WeakPtrFactory<SoftwareBrowserCompositorOutputSurface> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SoftwareBrowserCompositorOutputSurface);
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc b/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
deleted file mode 100644
index 5ac8128f4b7..00000000000
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
+++ /dev/null
@@ -1,168 +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/compositor/software_browser_compositor_output_surface.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/test/test_message_loop.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "cc/test/fake_output_surface_client.h"
-#include "components/viz/common/frame_sinks/begin_frame_source.h"
-#include "components/viz/common/frame_sinks/delay_based_time_source.h"
-#include "components/viz/service/display/output_surface_frame.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/compositor/compositor.h"
-#include "ui/compositor/test/context_factories_for_test.h"
-#include "ui/gfx/vsync_provider.h"
-
-namespace {
-
-class FakeVSyncProvider : public gfx::VSyncProvider {
- public:
- FakeVSyncProvider() : call_count_(0) {}
- ~FakeVSyncProvider() override {}
-
- void GetVSyncParameters(UpdateVSyncCallback callback) override {
- std::move(callback).Run(timebase_, interval_);
- call_count_++;
- }
-
- bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase,
- base::TimeDelta* interval) override {
- return false;
- }
-
- bool SupportGetVSyncParametersIfAvailable() const override { return false; }
- bool IsHWClock() const override { return false; }
-
- int call_count() const { return call_count_; }
-
- void set_timebase(base::TimeTicks timebase) { timebase_ = timebase; }
- void set_interval(base::TimeDelta interval) { interval_ = interval; }
-
- private:
- base::TimeTicks timebase_;
- base::TimeDelta interval_;
-
- int call_count_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeVSyncProvider);
-};
-
-class FakeSoftwareOutputDevice : public viz::SoftwareOutputDevice {
- public:
- FakeSoftwareOutputDevice() : vsync_provider_(new FakeVSyncProvider()) {}
- ~FakeSoftwareOutputDevice() override {}
-
- gfx::VSyncProvider* GetVSyncProvider() override {
- return vsync_provider_.get();
- }
-
- private:
- std::unique_ptr<gfx::VSyncProvider> vsync_provider_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeSoftwareOutputDevice);
-};
-
-} // namespace
-
-class SoftwareBrowserCompositorOutputSurfaceTest : public testing::Test {
- public:
- SoftwareBrowserCompositorOutputSurfaceTest()
- : begin_frame_source_(std::make_unique<viz::DelayBasedTimeSource>(
- message_loop_.task_runner().get()),
- viz::BeginFrameSource::kNotRestartableId) {}
- ~SoftwareBrowserCompositorOutputSurfaceTest() override = default;
-
- void SetUp() override;
- void TearDown() override;
-
- void UpdateVSyncParameters(base::TimeTicks timebase,
- base::TimeDelta interval);
-
- std::unique_ptr<content::BrowserCompositorOutputSurface> CreateSurface(
- std::unique_ptr<viz::SoftwareOutputDevice> device);
-
- protected:
- std::unique_ptr<content::BrowserCompositorOutputSurface> output_surface_;
-
- // TODO(crbug.com/616973): We shouldn't be using ThreadTaskRunnerHandle::Get()
- // inside the OutputSurface, so we shouldn't need a MessageLoop. The
- // OutputSurface should be using the TaskRunner given to the compositor.
- base::TestMessageLoop message_loop_;
- viz::DelayBasedBeginFrameSource begin_frame_source_;
- std::unique_ptr<ui::Compositor> compositor_;
- int update_vsync_parameters_call_count_ = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SoftwareBrowserCompositorOutputSurfaceTest);
-};
-
-void SoftwareBrowserCompositorOutputSurfaceTest::SetUp() {
- bool enable_pixel_output = false;
- ui::ContextFactory* context_factory = nullptr;
- ui::ContextFactoryPrivate* context_factory_private = nullptr;
-
- ui::InitializeContextFactoryForTests(enable_pixel_output, &context_factory,
- &context_factory_private);
-
- compositor_.reset(new ui::Compositor(
- context_factory_private->AllocateFrameSinkId(), context_factory,
- context_factory_private, message_loop_.task_runner().get(),
- false /* enable_pixel_canvas */));
- compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
-}
-
-void SoftwareBrowserCompositorOutputSurfaceTest::TearDown() {
- output_surface_.reset();
- compositor_.reset();
- ui::TerminateContextFactoryForTests();
-}
-
-std::unique_ptr<content::BrowserCompositorOutputSurface>
-SoftwareBrowserCompositorOutputSurfaceTest::CreateSurface(
- std::unique_ptr<viz::SoftwareOutputDevice> device) {
- return std::make_unique<content::SoftwareBrowserCompositorOutputSurface>(
- std::move(device),
- base::Bind(
- &SoftwareBrowserCompositorOutputSurfaceTest::UpdateVSyncParameters,
- base::Unretained(this)));
-}
-
-void SoftwareBrowserCompositorOutputSurfaceTest::UpdateVSyncParameters(
- base::TimeTicks timebase,
- base::TimeDelta interval) {
- update_vsync_parameters_call_count_++;
-}
-
-TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, NoVSyncProvider) {
- cc::FakeOutputSurfaceClient output_surface_client;
- std::unique_ptr<viz::SoftwareOutputDevice> software_device(
- new viz::SoftwareOutputDevice());
- output_surface_ = CreateSurface(std::move(software_device));
- output_surface_->BindToClient(&output_surface_client);
-
- output_surface_->SwapBuffers(viz::OutputSurfaceFrame());
- EXPECT_EQ(nullptr, output_surface_->software_device()->GetVSyncProvider());
- EXPECT_EQ(0, update_vsync_parameters_call_count_);
-}
-
-TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, VSyncProviderUpdates) {
- cc::FakeOutputSurfaceClient output_surface_client;
- std::unique_ptr<viz::SoftwareOutputDevice> software_device(
- new FakeSoftwareOutputDevice());
- output_surface_ = CreateSurface(std::move(software_device));
- output_surface_->BindToClient(&output_surface_client);
-
- FakeVSyncProvider* vsync_provider = static_cast<FakeVSyncProvider*>(
- output_surface_->software_device()->GetVSyncProvider());
- EXPECT_EQ(0, vsync_provider->call_count());
-
- output_surface_->SwapBuffers(viz::OutputSurfaceFrame());
- EXPECT_EQ(1, vsync_provider->call_count());
- EXPECT_EQ(1, update_vsync_parameters_call_count_);
-}
diff --git a/chromium/content/browser/compositor/viz_process_transport_factory.cc b/chromium/content/browser/compositor/viz_process_transport_factory.cc
index 0c91d65bcf0..dc46b51019d 100644
--- a/chromium/content/browser/compositor/viz_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/viz_process_transport_factory.cc
@@ -98,7 +98,7 @@ bool IsWorkerContextLost(viz::RasterContextProvider* context_provider) {
// Provided as a callback to crash the GPU process.
void ReceivedBadMessageFromGpuProcess() {
GpuProcessHost::CallOnIO(
- GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
+ GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
base::BindRepeating([](GpuProcessHost* host) {
// There should always be a GpuProcessHost instance, and GPU process,
// for running the compositor thread. The exception is during shutdown
@@ -313,6 +313,20 @@ void VizProcessTransportFactory::OnContextLost() {
void VizProcessTransportFactory::DisableGpuCompositing(
ui::Compositor* guilty_compositor) {
+#if defined(OS_CHROMEOS)
+ ALLOW_UNUSED_LOCAL(compositing_mode_reporter_);
+ // A fatal error has occurred and we can't fall back to software compositing
+ // on CrOS. These can be unrecoverable hardware errors, or bugs that should
+ // not happen. Crash the browser process to reset everything.
+ LOG(FATAL) << "Software compositing fallback is unavailable. Goodbye.";
+#else
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableSoftwareCompositingFallback)) {
+ // Some tests only want to run with a functional GPU Process. Fail out here
+ // rather than falling back to software compositing and silently passing.
+ LOG(FATAL) << "Software compositing fallback is unavailable. Goodbye.";
+ }
+
DLOG(ERROR) << "Switching to software compositing.";
// Change the result of IsGpuCompositingDisabled() before notifying anything.
@@ -354,6 +368,7 @@ void VizProcessTransportFactory::DisableGpuCompositing(
}
GpuDataManagerImpl::GetInstance()->NotifyGpuInfoUpdate();
+#endif
}
void VizProcessTransportFactory::OnGpuProcessLost() {
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 cffaec97cf7..37f5d43faee 100644
--- a/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc
+++ b/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc
@@ -17,6 +17,7 @@
#include "content/browser/storage_partition_impl.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "services/network/public/cpp/features.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_event_status.mojom.h"
@@ -260,11 +261,13 @@ class CookieStoreManagerTest
storage_partition_impl_ = base::WrapUnique(
new StoragePartitionImpl(worker_test_helper_->browser_context(),
user_data_directory_.GetPath(), nullptr));
- storage_partition_impl_->SetURLRequestContext(
- worker_test_helper_->browser_context()
- ->CreateRequestContextForStoragePartition(
- user_data_directory_.GetPath(), false, nullptr,
- URLRequestInterceptorScopedVector()));
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ storage_partition_impl_->SetURLRequestContext(
+ worker_test_helper_->browser_context()
+ ->CreateRequestContextForStoragePartition(
+ user_data_directory_.GetPath(), false, nullptr,
+ URLRequestInterceptorScopedVector()));
+ }
::network::mojom::NetworkContext* network_context =
storage_partition_impl_->GetNetworkContext();
cookie_store_context_->ListenToCookieChanges(
diff --git a/chromium/content/browser/device_sensors/device_sensor_browsertest.cc b/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
index 1242b41d6fa..f3d12aa78df 100644
--- a/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
+++ b/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
@@ -95,9 +95,8 @@ class DeviceSensorBrowserTest : public ContentBrowserTest {
shell()->GetJavaScriptDialogManager(shell()->web_contents()));
scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
- dialog_manager->set_dialog_request_callback(
- base::Bind(&DeviceSensorBrowserTest::DelayAndQuit,
- base::Unretained(this), delay));
+ dialog_manager->set_dialog_request_callback(base::BindOnce(
+ &DeviceSensorBrowserTest::DelayAndQuit, base::Unretained(this), delay));
runner->Run();
}
diff --git a/chromium/content/browser/devtools/BUILD.gn b/chromium/content/browser/devtools/BUILD.gn
index c06c3722f51..8d240625062 100644
--- a/chromium/content/browser/devtools/BUILD.gn
+++ b/chromium/content/browser/devtools/BUILD.gn
@@ -123,6 +123,8 @@ inspector_protocol_generate("protocol_sources") {
"protocol/tethering.h",
"protocol/tracing.cc",
"protocol/tracing.h",
+ "protocol/web_authn.cc",
+ "protocol/web_authn.h",
]
}
diff --git a/chromium/content/browser/devtools/OWNERS b/chromium/content/browser/devtools/OWNERS
index d8aa317eb98..6f34e236d0a 100644
--- a/chromium/content/browser/devtools/OWNERS
+++ b/chromium/content/browser/devtools/OWNERS
@@ -1,3 +1,6 @@
caseq@chromium.org
+alph@chromium.org
+
+per-file *background_service*=rayankans@chromium.org
# COMPONENT: Platform>DevTools
diff --git a/chromium/content/browser/devtools/browser_devtools_agent_host.cc b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
index 9cf49c0a0f3..b706247b81b 100644
--- a/chromium/content/browser/devtools/browser_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
@@ -89,8 +89,8 @@ bool BrowserDevToolsAgentHost::AttachSession(DevToolsSession* session) {
session->AddHandler(std::make_unique<protocol::TetheringHandler>(
socket_callback_, tethering_task_runner_));
}
- session->AddHandler(std::make_unique<protocol::TracingHandler>(
- nullptr, GetIOContext(), session->UsesBinaryProtocol()));
+ session->AddHandler(
+ std::make_unique<protocol::TracingHandler>(nullptr, GetIOContext()));
return true;
}
diff --git a/chromium/content/browser/devtools/devtools_background_services.proto b/chromium/content/browser/devtools/devtools_background_services.proto
index 022a17f8a52..8a80f14a7c9 100644
--- a/chromium/content/browser/devtools/devtools_background_services.proto
+++ b/chromium/content/browser/devtools/devtools_background_services.proto
@@ -10,11 +10,17 @@ package content.devtools.proto;
// The background service we are logging events for.
// Do not change the tags since these are persisted.
+// Add a corresponding entry in `enums.xml` if a new value is introduced.
enum BackgroundService {
UNKNOWN = 0;
TEST_BACKGROUND_SERVICE = 1;
BACKGROUND_FETCH = 2;
BACKGROUND_SYNC = 3;
+ PUSH_MESSAGING = 4;
+ NOTIFICATIONS = 5;
+
+ // Keep as last, must have the largest tag value.
+ COUNT = 6;
}
// A proto for storing the background service event with common metadata for
diff --git a/chromium/content/browser/devtools/devtools_background_services_context.cc b/chromium/content/browser/devtools/devtools_background_services_context_impl.cc
index d46e3d69e25..1c1331c4b43 100644
--- a/chromium/content/browser/devtools/devtools_background_services_context.cc
+++ b/chromium/content/browser/devtools/devtools_background_services_context_impl.cc
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/devtools/devtools_background_services_context.h"
+#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include <algorithm>
#include "base/guid.h"
+#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/post_task.h"
#include "base/time/time.h"
@@ -31,22 +32,35 @@ std::string CreateEntryKey(devtools::proto::BackgroundService service) {
void DidLogServiceEvent(blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // TODO(rayankans): Log errors to UMA.
+ UMA_HISTOGRAM_ENUMERATION("DevTools.BackgroundService.LogEvent", status);
}
void DidClearServiceEvents(blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // TODO(rayankans): Log errors to UMA.
+ UMA_HISTOGRAM_ENUMERATION("DevTools.BackgroundService.ClearEvents", status);
+}
+
+constexpr devtools::proto::BackgroundService ServiceToProtoEnum(
+ DevToolsBackgroundService service) {
+ switch (service) {
+ case DevToolsBackgroundService::kBackgroundFetch:
+ return devtools::proto::BACKGROUND_FETCH;
+ case DevToolsBackgroundService::kBackgroundSync:
+ return devtools::proto::BACKGROUND_SYNC;
+ case DevToolsBackgroundService::kPushMessaging:
+ return devtools::proto::PUSH_MESSAGING;
+ case DevToolsBackgroundService::kNotifications:
+ return devtools::proto::NOTIFICATIONS;
+ }
}
} // namespace
-DevToolsBackgroundServicesContext::DevToolsBackgroundServicesContext(
+DevToolsBackgroundServicesContextImpl::DevToolsBackgroundServicesContextImpl(
BrowserContext* browser_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
: browser_context_(browser_context),
- service_worker_context_(std::move(service_worker_context)),
- weak_ptr_factory_(this) {
+ service_worker_context_(std::move(service_worker_context)) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto expiration_times =
@@ -65,19 +79,20 @@ DevToolsBackgroundServicesContext::DevToolsBackgroundServicesContext(
}
}
-DevToolsBackgroundServicesContext::~DevToolsBackgroundServicesContext() =
- default;
+DevToolsBackgroundServicesContextImpl::
+ ~DevToolsBackgroundServicesContextImpl() = default;
-void DevToolsBackgroundServicesContext::AddObserver(EventObserver* observer) {
+void DevToolsBackgroundServicesContextImpl::AddObserver(
+ EventObserver* observer) {
observers_.AddObserver(observer);
}
-void DevToolsBackgroundServicesContext::RemoveObserver(
+void DevToolsBackgroundServicesContextImpl::RemoveObserver(
const EventObserver* observer) {
observers_.RemoveObserver(observer);
}
-void DevToolsBackgroundServicesContext::StartRecording(
+void DevToolsBackgroundServicesContextImpl::StartRecording(
devtools::proto::BackgroundService service) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -92,7 +107,7 @@ void DevToolsBackgroundServicesContext::StartRecording(
observer.OnRecordingStateChanged(/* should_record= */ true, service);
}
-void DevToolsBackgroundServicesContext::StopRecording(
+void DevToolsBackgroundServicesContextImpl::StopRecording(
devtools::proto::BackgroundService service) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -104,54 +119,61 @@ void DevToolsBackgroundServicesContext::StopRecording(
observer.OnRecordingStateChanged(/* should_record= */ false, service);
}
-bool DevToolsBackgroundServicesContext::IsRecording(
+bool DevToolsBackgroundServicesContextImpl::IsRecording(
+ DevToolsBackgroundService service) {
+ return IsRecording(ServiceToProtoEnum(service));
+}
+
+bool DevToolsBackgroundServicesContextImpl::IsRecording(
devtools::proto::BackgroundService service) {
// Returns whether |service| has been enabled. When the expiration time has
// been met it will be lazily updated to be null.
return !expiration_times_[service].is_null();
}
-bool DevToolsBackgroundServicesContext::IsRecordingExpired(
+bool DevToolsBackgroundServicesContextImpl::IsRecordingExpired(
devtools::proto::BackgroundService service) {
// Copy the expiration time to avoid data races.
const base::Time expiration_time = expiration_times_[service];
return !expiration_time.is_null() && expiration_time < base::Time::Now();
}
-void DevToolsBackgroundServicesContext::GetLoggedBackgroundServiceEvents(
+void DevToolsBackgroundServicesContextImpl::GetLoggedBackgroundServiceEvents(
devtools::proto::BackgroundService service,
GetLoggedBackgroundServiceEventsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&DevToolsBackgroundServicesContext::
+ base::BindOnce(&DevToolsBackgroundServicesContextImpl::
GetLoggedBackgroundServiceEventsOnIO,
- weak_ptr_factory_.GetWeakPtr(), service,
+ weak_ptr_factory_io_.GetWeakPtr(), service,
std::move(callback)));
}
-void DevToolsBackgroundServicesContext::GetLoggedBackgroundServiceEventsOnIO(
- devtools::proto::BackgroundService service,
- GetLoggedBackgroundServiceEventsCallback callback) {
+void DevToolsBackgroundServicesContextImpl::
+ GetLoggedBackgroundServiceEventsOnIO(
+ devtools::proto::BackgroundService service,
+ GetLoggedBackgroundServiceEventsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_worker_context_->GetUserDataForAllRegistrationsByKeyPrefix(
CreateEntryKeyPrefix(service),
- base::BindOnce(&DevToolsBackgroundServicesContext::DidGetUserData,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+ base::BindOnce(&DevToolsBackgroundServicesContextImpl::DidGetUserData,
+ weak_ptr_factory_io_.GetWeakPtr(), std::move(callback)));
}
-void DevToolsBackgroundServicesContext::DidGetUserData(
+void DevToolsBackgroundServicesContextImpl::DidGetUserData(
GetLoggedBackgroundServiceEventsCallback callback,
const std::vector<std::pair<int64_t, std::string>>& user_data,
blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ UMA_HISTOGRAM_ENUMERATION("DevTools.BackgroundService.GetEvents", status);
+
std::vector<devtools::proto::BackgroundServiceEvent> events;
if (status != blink::ServiceWorkerStatusCode::kOk) {
- // TODO(rayankans): Log errors to UMA.
std::move(callback).Run(events);
return;
}
@@ -178,29 +200,47 @@ void DevToolsBackgroundServicesContext::DidGetUserData(
base::BindOnce(std::move(callback), std::move(events)));
}
-void DevToolsBackgroundServicesContext::ClearLoggedBackgroundServiceEvents(
+void DevToolsBackgroundServicesContextImpl::ClearLoggedBackgroundServiceEvents(
devtools::proto::BackgroundService service) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&DevToolsBackgroundServicesContext::
+ base::BindOnce(&DevToolsBackgroundServicesContextImpl::
ClearLoggedBackgroundServiceEventsOnIO,
- weak_ptr_factory_.GetWeakPtr(), service));
+ weak_ptr_factory_io_.GetWeakPtr(), service));
}
-void DevToolsBackgroundServicesContext::ClearLoggedBackgroundServiceEventsOnIO(
- devtools::proto::BackgroundService service) {
+void DevToolsBackgroundServicesContextImpl::
+ ClearLoggedBackgroundServiceEventsOnIO(
+ devtools::proto::BackgroundService service) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_worker_context_->ClearUserDataForAllRegistrationsByKeyPrefix(
CreateEntryKeyPrefix(service), base::BindOnce(&DidClearServiceEvents));
}
-void DevToolsBackgroundServicesContext::LogBackgroundServiceEvent(
+void DevToolsBackgroundServicesContextImpl::LogBackgroundServiceEvent(
uint64_t service_worker_registration_id,
const url::Origin& origin,
- devtools::proto::BackgroundService service,
+ DevToolsBackgroundService service,
+ const std::string& event_name,
+ const std::string& instance_id,
+ const std::map<std::string, std::string>& event_metadata) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(
+ &DevToolsBackgroundServicesContextImpl::LogBackgroundServiceEventOnIO,
+ weak_ptr_factory_io_.GetWeakPtr(), service_worker_registration_id,
+ origin, service, event_name, instance_id, event_metadata));
+}
+
+void DevToolsBackgroundServicesContextImpl::LogBackgroundServiceEventOnIO(
+ uint64_t service_worker_registration_id,
+ const url::Origin& origin,
+ DevToolsBackgroundService service,
const std::string& event_name,
const std::string& instance_id,
const std::map<std::string, std::string>& event_metadata) {
@@ -209,14 +249,14 @@ void DevToolsBackgroundServicesContext::LogBackgroundServiceEvent(
if (!IsRecording(service))
return;
- if (IsRecordingExpired(service)) {
+ if (IsRecordingExpired(ServiceToProtoEnum(service))) {
// We should stop recording because of the expiration time. We should
// also inform the observers that we stopped recording.
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(
- &DevToolsBackgroundServicesContext::OnRecordingTimeExpired,
- weak_ptr_factory_.GetWeakPtr(), service));
+ &DevToolsBackgroundServicesContextImpl::OnRecordingTimeExpired,
+ weak_ptr_factory_ui_.GetWeakPtr(), ServiceToProtoEnum(service)));
return;
}
@@ -225,7 +265,7 @@ void DevToolsBackgroundServicesContext::LogBackgroundServiceEvent(
base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds());
event.set_origin(origin.GetURL().spec());
event.set_service_worker_registration_id(service_worker_registration_id);
- event.set_background_service(service);
+ event.set_background_service(ServiceToProtoEnum(service));
event.set_event_name(event_name);
event.set_instance_id(instance_id);
event.mutable_event_metadata()->insert(event_metadata.begin(),
@@ -238,11 +278,12 @@ void DevToolsBackgroundServicesContext::LogBackgroundServiceEvent(
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&DevToolsBackgroundServicesContext::NotifyEventObservers,
- weak_ptr_factory_.GetWeakPtr(), std::move(event)));
+ base::BindOnce(
+ &DevToolsBackgroundServicesContextImpl::NotifyEventObservers,
+ weak_ptr_factory_ui_.GetWeakPtr(), std::move(event)));
}
-void DevToolsBackgroundServicesContext::NotifyEventObservers(
+void DevToolsBackgroundServicesContextImpl::NotifyEventObservers(
const devtools::proto::BackgroundServiceEvent& event) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -250,7 +291,7 @@ void DevToolsBackgroundServicesContext::NotifyEventObservers(
observer.OnEventReceived(event);
}
-void DevToolsBackgroundServicesContext::OnRecordingTimeExpired(
+void DevToolsBackgroundServicesContextImpl::OnRecordingTimeExpired(
devtools::proto::BackgroundService service) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chromium/content/browser/devtools/devtools_background_services_context.h b/chromium/content/browser/devtools/devtools_background_services_context_impl.h
index a7d8d07e4f8..c378fb543bf 100644
--- a/chromium/content/browser/devtools/devtools_background_services_context.h
+++ b/chromium/content/browser/devtools/devtools_background_services_context_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_DEVTOOLS_DEVTOOLS_BACKGROUND_SERVICES_CONTEXT_H_
-#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_BACKGROUND_SERVICES_CONTEXT_H_
+#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_BACKGROUND_SERVICES_CONTEXT_IMPL_H_
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_BACKGROUND_SERVICES_CONTEXT_IMPL_H_
#include <array>
#include <map>
@@ -22,10 +22,7 @@
#include "content/browser/devtools/devtools_background_services.pb.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/content_export.h"
-
-namespace url {
-class Origin;
-} // namespace url
+#include "content/public/browser/devtools_background_services_context.h"
namespace content {
@@ -38,8 +35,9 @@ class ServiceWorkerContextWrapper;
// This class is also responsible for reading back the data to the DevTools
// client, as the protocol handler will have access to an instance of the
// context.
-class CONTENT_EXPORT DevToolsBackgroundServicesContext
- : public base::RefCountedThreadSafe<DevToolsBackgroundServicesContext> {
+class CONTENT_EXPORT DevToolsBackgroundServicesContextImpl
+ : public DevToolsBackgroundServicesContext,
+ public base::RefCountedThreadSafe<DevToolsBackgroundServicesContextImpl> {
public:
using GetLoggedBackgroundServiceEventsCallback = base::OnceCallback<void(
std::vector<devtools::proto::BackgroundServiceEvent>)>;
@@ -54,13 +52,33 @@ class CONTENT_EXPORT DevToolsBackgroundServicesContext
devtools::proto::BackgroundService service) = 0;
};
- DevToolsBackgroundServicesContext(
+ DevToolsBackgroundServicesContextImpl(
BrowserContext* browser_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
void AddObserver(EventObserver* observer);
void RemoveObserver(const EventObserver* observer);
+ // DevToolsBackgroundServicesContext overrides:
+ bool IsRecording(DevToolsBackgroundService service) override;
+ void LogBackgroundServiceEvent(
+ uint64_t service_worker_registration_id,
+ const url::Origin& origin,
+ DevToolsBackgroundService service,
+ const std::string& event_name,
+ const std::string& instance_id,
+ const std::map<std::string, std::string>& event_metadata) override;
+
+ // Helper functions for public overriden APIs. Can be used directly.
+ bool IsRecording(devtools::proto::BackgroundService service);
+ void LogBackgroundServiceEventOnIO(
+ uint64_t service_worker_registration_id,
+ const url::Origin& origin,
+ DevToolsBackgroundService service,
+ const std::string& event_name,
+ const std::string& instance_id,
+ const std::map<std::string, std::string>& event_metadata);
+
// Enables recording mode for |service|. This is capped at 3 days in case
// developers forget to switch it off.
void StartRecording(devtools::proto::BackgroundService service);
@@ -68,9 +86,6 @@ class CONTENT_EXPORT DevToolsBackgroundServicesContext
// Disables recording mode for |service|.
void StopRecording(devtools::proto::BackgroundService service);
- // Whether events related to |service| should be recorded.
- bool IsRecording(devtools::proto::BackgroundService service);
-
// Queries all logged events for |service| and returns them in sorted order
// (by timestamp). |callback| is called with an empty vector if there was an
// error. Must be called from the UI thread.
@@ -83,22 +98,11 @@ class CONTENT_EXPORT DevToolsBackgroundServicesContext
void ClearLoggedBackgroundServiceEvents(
devtools::proto::BackgroundService service);
- // Logs the event for |service|. |event_name| is a description of the event.
- // |instance_id| is for tracking events related to the same feature instance.
- // Any additional useful information relating to the feature can be sent via
- // |event_metadata|. Must be called on the IO thread.
- void LogBackgroundServiceEvent(
- uint64_t service_worker_registration_id,
- const url::Origin& origin,
- devtools::proto::BackgroundService service,
- const std::string& event_name,
- const std::string& instance_id,
- const std::map<std::string, std::string>& event_metadata);
-
private:
friend class DevToolsBackgroundServicesContextTest;
- friend class base::RefCountedThreadSafe<DevToolsBackgroundServicesContext>;
- ~DevToolsBackgroundServicesContext();
+ friend class base::RefCountedThreadSafe<
+ DevToolsBackgroundServicesContextImpl>;
+ ~DevToolsBackgroundServicesContextImpl() override;
// Whether |service| has an expiration time and it was exceeded.
bool IsRecordingExpired(devtools::proto::BackgroundService service);
@@ -127,16 +131,19 @@ class CONTENT_EXPORT DevToolsBackgroundServicesContext
// recorded. The BackgroundService enum is used as the index.
// This should only be updated on the UI thread, but is also
// accessed from the IO thread.
- std::array<base::Time, devtools::proto::BackgroundService_ARRAYSIZE>
+ std::array<base::Time, devtools::proto::BackgroundService::COUNT>
expiration_times_;
base::ObserverList<EventObserver> observers_;
- base::WeakPtrFactory<DevToolsBackgroundServicesContext> weak_ptr_factory_;
+ base::WeakPtrFactory<DevToolsBackgroundServicesContextImpl>
+ weak_ptr_factory_ui_{this};
+ base::WeakPtrFactory<DevToolsBackgroundServicesContextImpl>
+ weak_ptr_factory_io_{this};
- DISALLOW_COPY_AND_ASSIGN(DevToolsBackgroundServicesContext);
+ DISALLOW_COPY_AND_ASSIGN(DevToolsBackgroundServicesContextImpl);
};
} // namespace content
-#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_BACKGROUND_SERVICES_CONTEXT_H_
+#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_BACKGROUND_SERVICES_CONTEXT_IMPL_H_
diff --git a/chromium/content/browser/devtools/devtools_background_services_context_unittest.cc b/chromium/content/browser/devtools/devtools_background_services_context_impl_unittest.cc
index cc072b61074..b06c7bea32c 100644
--- a/chromium/content/browser/devtools/devtools_background_services_context_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_background_services_context_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/devtools/devtools_background_services_context.h"
+#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include <string>
#include <vector>
@@ -87,7 +87,7 @@ void DidGetLoggedBackgroundServiceEvents(
class DevToolsBackgroundServicesContextTest
: public ::testing::Test,
- DevToolsBackgroundServicesContext::EventObserver {
+ DevToolsBackgroundServicesContextImpl::EventObserver {
public:
DevToolsBackgroundServicesContextTest()
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
@@ -120,7 +120,7 @@ class DevToolsBackgroundServicesContextTest
if (context_)
context_->RemoveObserver(this);
// Create |context_|.
- context_ = base::MakeRefCounted<DevToolsBackgroundServicesContext>(
+ context_ = base::MakeRefCounted<DevToolsBackgroundServicesContextImpl>(
&browser_context_, embedded_worker_test_helper_.context_wrapper());
context_->AddObserver(this);
ASSERT_TRUE(context_);
@@ -129,18 +129,17 @@ class DevToolsBackgroundServicesContextTest
void SimulateOneWeekPassing() {
base::Time one_week_ago = base::Time::Now() - base::TimeDelta::FromDays(7);
context_->expiration_times_
- [devtools::proto::BackgroundService::TEST_BACKGROUND_SERVICE] =
- one_week_ago;
+ [devtools::proto::BackgroundService::BACKGROUND_FETCH] = one_week_ago;
}
bool IsRecording() {
return context_->IsRecording(
- devtools::proto::BackgroundService::TEST_BACKGROUND_SERVICE);
+ devtools::proto::BackgroundService::BACKGROUND_FETCH);
}
base::Time GetExpirationTime() {
return context_->expiration_times_
- [devtools::proto::BackgroundService::TEST_BACKGROUND_SERVICE];
+ [devtools::proto::BackgroundService::BACKGROUND_FETCH];
}
std::vector<devtools::proto::BackgroundServiceEvent>
@@ -149,7 +148,7 @@ class DevToolsBackgroundServicesContextTest
base::RunLoop run_loop;
context_->GetLoggedBackgroundServiceEvents(
- devtools::proto::BackgroundService::TEST_BACKGROUND_SERVICE,
+ devtools::proto::BackgroundService::BACKGROUND_FETCH,
base::BindOnce(&DidGetLoggedBackgroundServiceEvents,
run_loop.QuitClosure(), &feature_states));
run_loop.Run();
@@ -158,19 +157,18 @@ class DevToolsBackgroundServicesContextTest
}
void LogTestBackgroundServiceEvent(const std::string& log_message) {
- context_->LogBackgroundServiceEvent(
+ context_->LogBackgroundServiceEventOnIO(
service_worker_registration_id_, origin_,
- devtools::proto::BackgroundService::TEST_BACKGROUND_SERVICE, kEventName,
- kInstanceId, {{"key", log_message}});
+ DevToolsBackgroundService::kBackgroundFetch, kEventName, kInstanceId,
+ {{"key", log_message}});
}
void StartRecording() {
EXPECT_CALL(
- *this,
- OnRecordingStateChanged(
- true, devtools::proto::BackgroundService::TEST_BACKGROUND_SERVICE));
+ *this, OnRecordingStateChanged(
+ true, devtools::proto::BackgroundService::BACKGROUND_FETCH));
context_->StartRecording(
- devtools::proto::BackgroundService::TEST_BACKGROUND_SERVICE);
+ devtools::proto::BackgroundService::BACKGROUND_FETCH);
// Wait for the messages to propagate to the browser client.
thread_bundle_.RunUntilIdle();
@@ -180,10 +178,9 @@ class DevToolsBackgroundServicesContextTest
EXPECT_CALL(
*this,
OnRecordingStateChanged(
- false,
- devtools::proto::BackgroundService::TEST_BACKGROUND_SERVICE));
+ false, devtools::proto::BackgroundService::BACKGROUND_FETCH));
context_->StopRecording(
- devtools::proto::BackgroundService::TEST_BACKGROUND_SERVICE);
+ devtools::proto::BackgroundService::BACKGROUND_FETCH);
// Wait for the messages to propagate to the browser client.
thread_bundle_.RunUntilIdle();
@@ -191,7 +188,7 @@ class DevToolsBackgroundServicesContextTest
void ClearLoggedBackgroundServiceEvents() {
context_->ClearLoggedBackgroundServiceEvents(
- devtools::proto::BackgroundService::TEST_BACKGROUND_SERVICE);
+ devtools::proto::BackgroundService::BACKGROUND_FETCH);
}
TestBrowserThreadBundle thread_bundle_; // Must be first member.
@@ -247,7 +244,7 @@ class DevToolsBackgroundServicesContextTest
EmbeddedWorkerTestHelper embedded_worker_test_helper_;
TestBrowserContext browser_context_;
- scoped_refptr<DevToolsBackgroundServicesContext> context_;
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> context_;
scoped_refptr<ServiceWorkerRegistration> service_worker_registration_;
std::unique_ptr<ContentBrowserClient> browser_client_;
@@ -280,7 +277,7 @@ TEST_F(DevToolsBackgroundServicesContextTest, GetLoggedEvents) {
for (const auto& feature_event : feature_events) {
EXPECT_EQ(feature_event.background_service(),
- devtools::proto::BackgroundService::TEST_BACKGROUND_SERVICE);
+ devtools::proto::BackgroundService::BACKGROUND_FETCH);
EXPECT_EQ(feature_event.origin(), origin_.GetURL().spec());
EXPECT_EQ(feature_event.service_worker_registration_id(),
service_worker_registration_id_);
@@ -352,10 +349,9 @@ TEST_F(DevToolsBackgroundServicesContextTest, RecordingExpiration) {
LogTestBackgroundServiceEvent("f1");
// Observers should be informed that recording stopped.
- EXPECT_CALL(
- *this,
- OnRecordingStateChanged(
- false, devtools::proto::BackgroundService::TEST_BACKGROUND_SERVICE));
+ EXPECT_CALL(*this,
+ OnRecordingStateChanged(
+ false, devtools::proto::BackgroundService::BACKGROUND_FETCH));
thread_bundle_.RunUntilIdle();
diff --git a/chromium/content/browser/devtools/devtools_frame_metadata.cc b/chromium/content/browser/devtools/devtools_frame_metadata.cc
new file mode 100644
index 00000000000..b7ac2b0f4e6
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_frame_metadata.cc
@@ -0,0 +1,45 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/devtools_frame_metadata.h"
+
+#include "build/build_config.h"
+#include "cc/trees/render_frame_metadata.h"
+#include "components/viz/common/quads/compositor_frame_metadata.h"
+
+namespace content {
+
+#if defined(OS_ANDROID)
+DevToolsFrameMetadata::DevToolsFrameMetadata(
+ const cc::RenderFrameMetadata& metadata)
+ : device_scale_factor(metadata.device_scale_factor),
+ page_scale_factor(metadata.page_scale_factor),
+ root_scroll_offset(
+ metadata.root_scroll_offset.value_or(gfx::Vector2dF())),
+ top_controls_height(metadata.top_controls_height),
+ top_controls_shown_ratio(metadata.top_controls_shown_ratio),
+ scrollable_viewport_size(metadata.scrollable_viewport_size) {}
+
+DevToolsFrameMetadata::DevToolsFrameMetadata(
+ const viz::CompositorFrameMetadata& metadata)
+ : device_scale_factor(metadata.device_scale_factor),
+ page_scale_factor(metadata.page_scale_factor),
+ root_scroll_offset(metadata.root_scroll_offset),
+ top_controls_height(metadata.top_controls_height),
+ top_controls_shown_ratio(metadata.top_controls_shown_ratio),
+ scrollable_viewport_size(metadata.scrollable_viewport_size) {}
+#else
+// On non-Android, this class should never be created.
+DevToolsFrameMetadata::DevToolsFrameMetadata(
+ const cc::RenderFrameMetadata& metadata) {
+ NOTREACHED();
+}
+
+DevToolsFrameMetadata::DevToolsFrameMetadata(
+ const viz::CompositorFrameMetadata& metadata) {
+ NOTREACHED();
+}
+#endif // defined(OS_ANDROID)
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_frame_metadata.h b/chromium/content/browser/devtools/devtools_frame_metadata.h
new file mode 100644
index 00000000000..37201e37cb8
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_frame_metadata.h
@@ -0,0 +1,38 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRAME_METADATA_H_
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRAME_METADATA_H_
+
+#include "ui/gfx/geometry/size_f.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+
+namespace cc {
+class RenderFrameMetadata;
+}
+
+namespace viz {
+class CompositorFrameMetadata;
+}
+
+namespace content {
+
+// A subset of the information in Render/CompositorFrameMetadata used in
+// DevTools with Android WebView.
+struct DevToolsFrameMetadata {
+ public:
+ explicit DevToolsFrameMetadata(const cc::RenderFrameMetadata& metadata);
+ explicit DevToolsFrameMetadata(const viz::CompositorFrameMetadata& metadata);
+
+ float device_scale_factor;
+ float page_scale_factor;
+ gfx::Vector2dF root_scroll_offset;
+ float top_controls_height;
+ float top_controls_shown_ratio;
+ gfx::SizeF scrollable_viewport_size;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRAME_METADATA_H_
diff --git a/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc b/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc
index 4c8f6b249c3..3a9fca06bd3 100644
--- a/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc
+++ b/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc
@@ -13,7 +13,7 @@
#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/trace_event/trace_event_impl.h"
-#include "components/viz/common/quads/compositor_frame_metadata.h"
+#include "content/browser/devtools/devtools_frame_metadata.h"
#include "content/browser/devtools/devtools_traceable_screenshot.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
@@ -42,7 +42,7 @@ void FrameCaptured(base::TimeTicks timestamp, const SkBitmap& bitmap) {
}
void CaptureFrame(RenderFrameHostImpl* host,
- const viz::CompositorFrameMetadata& metadata) {
+ const DevToolsFrameMetadata& metadata) {
RenderWidgetHostViewBase* view =
static_cast<RenderWidgetHostViewBase*>(host->GetView());
if (!view)
@@ -82,18 +82,15 @@ DevToolsFrameTraceRecorder::~DevToolsFrameTraceRecorder() { }
void DevToolsFrameTraceRecorder::OnSynchronousSwapCompositorFrame(
RenderFrameHostImpl* host,
- const viz::CompositorFrameMetadata& frame_metadata) {
+ const DevToolsFrameMetadata& metadata) {
if (!host || !ScreenshotCategoryEnabled()) {
- last_metadata_.reset();
return;
}
bool is_new_trace;
TRACE_EVENT_IS_NEW_TRACE(&is_new_trace);
- if (!is_new_trace && last_metadata_)
- CaptureFrame(host, *last_metadata_);
- last_metadata_.reset(new viz::CompositorFrameMetadata);
- *last_metadata_ = frame_metadata.Clone();
+ if (!is_new_trace)
+ CaptureFrame(host, metadata);
}
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_frame_trace_recorder.h b/chromium/content/browser/devtools/devtools_frame_trace_recorder.h
index ed1d52f1152..0b43c995254 100644
--- a/chromium/content/browser/devtools/devtools_frame_trace_recorder.h
+++ b/chromium/content/browser/devtools/devtools_frame_trace_recorder.h
@@ -5,34 +5,27 @@
#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRAME_TRACE_RECORDER_H_
#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRAME_TRACE_RECORDER_H_
-#include <memory>
-
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-namespace viz {
-class CompositorFrameMetadata;
-}
-
namespace content {
class RenderFrameHostImpl;
+struct DevToolsFrameMetadata;
class DevToolsFrameTraceRecorder {
public:
DevToolsFrameTraceRecorder();
~DevToolsFrameTraceRecorder();
- void OnSynchronousSwapCompositorFrame(
- RenderFrameHostImpl* host,
- const viz::CompositorFrameMetadata& frame_metadata);
+ void OnSynchronousSwapCompositorFrame(RenderFrameHostImpl* host,
+ const DevToolsFrameMetadata& metadata);
static constexpr int kMaximumNumberOfScreenshots = 450;
private:
DISALLOW_COPY_AND_ASSIGN(DevToolsFrameTraceRecorder);
- std::unique_ptr<viz::CompositorFrameMetadata> last_metadata_;
};
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_frontend_host_impl.cc b/chromium/content/browser/devtools/devtools_frontend_host_impl.cc
index 2c5abd05aea..bf12208685b 100644
--- a/chromium/content/browser/devtools/devtools_frontend_host_impl.cc
+++ b/chromium/content/browser/devtools/devtools_frontend_host_impl.cc
@@ -25,7 +25,7 @@ namespace {
const char kCompatibilityScript[] = "devtools_compatibility.js";
const char kCompatibilityScriptSourceURL[] =
"\n//# "
- "sourceURL=chrome-devtools://devtools/bundled/devtools_compatibility.js";
+ "sourceURL=devtools://devtools/bundled/devtools_compatibility.js";
}
// static
diff --git a/chromium/content/browser/devtools/devtools_http_handler.cc b/chromium/content/browser/devtools/devtools_http_handler.cc
index 94892dd57d3..30b2a43959d 100644
--- a/chromium/content/browser/devtools/devtools_http_handler.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler.cc
@@ -604,9 +604,7 @@ void DevToolsHttpHandler::OnJsonRequest(
}
if (command == "new") {
- GURL url(net::UnescapeURLComponent(
- query, net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS |
- net::UnescapeRule::PATH_SEPARATORS));
+ GURL url(net::UnescapeBinaryURLComponent(query));
if (!url.is_valid())
url = GURL(url::kAboutBlankURL);
scoped_refptr<DevToolsAgentHost> agent_host = nullptr;
diff --git a/chromium/content/browser/devtools/devtools_instrumentation.cc b/chromium/content/browser/devtools/devtools_instrumentation.cc
index 27795d258b8..fd4f77bfc3f 100644
--- a/chromium/content/browser/devtools/devtools_instrumentation.cc
+++ b/chromium/content/browser/devtools/devtools_instrumentation.cc
@@ -15,6 +15,7 @@
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/navigation_request.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_package/signed_exchange_envelope.h"
#include "content/common/navigation_params.mojom.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -81,6 +82,19 @@ void OnNavigationRequestFailed(
protocol::Network::ResourceTypeEnum::Document, status);
}
+void WillBeginDownload(int render_process_id,
+ int render_frame_id,
+ const GURL& url) {
+ auto* rfh = static_cast<RenderFrameHostImpl*>(
+ RenderFrameHost::FromID(render_process_id, render_frame_id));
+ FrameTreeNode* ftn =
+ rfh ? FrameTreeNode::GloballyFindByID(rfh->GetFrameTreeNodeId())
+ : nullptr;
+ if (!ftn)
+ return;
+ DispatchToAgents(ftn, &protocol::PageHandler::DownloadWillBegin, ftn, url);
+}
+
void OnSignedExchangeReceived(
FrameTreeNode* frame_tree_node,
base::Optional<const base::UnguessableToken> devtools_navigation_token,
@@ -146,9 +160,18 @@ std::vector<std::unique_ptr<NavigationThrottle>> CreateNavigationThrottles(
result.push_back(std::move(throttle));
}
}
- if (!frame_tree_node->parent())
- return result;
- agent_host = RenderFrameDevToolsAgentHost::GetFor(frame_tree_node->parent());
+ FrameTreeNode* parent = frame_tree_node->parent();
+ if (!parent) {
+ if (WebContentsImpl::FromFrameTreeNode(frame_tree_node)->IsPortal()) {
+ parent = WebContentsImpl::FromFrameTreeNode(frame_tree_node)
+ ->GetOuterWebContents()
+ ->GetFrameTree()
+ ->root();
+ } else {
+ return result;
+ }
+ }
+ agent_host = RenderFrameDevToolsAgentHost::GetFor(parent);
if (agent_host) {
for (auto* target_handler :
protocol::TargetHandler::ForAgentHost(agent_host)) {
@@ -345,6 +368,21 @@ bool HandleCertificateError(WebContents* web_contents,
return !callback;
}
+void PortalAttached(RenderFrameHostImpl* render_frame_host_impl) {
+ DispatchToAgents(render_frame_host_impl->frame_tree_node(),
+ &protocol::TargetHandler::UpdatePortals);
+}
+
+void PortalDetached(RenderFrameHostImpl* render_frame_host_impl) {
+ DispatchToAgents(render_frame_host_impl->frame_tree_node(),
+ &protocol::TargetHandler::UpdatePortals);
+}
+
+void PortalActivated(RenderFrameHostImpl* render_frame_host_impl) {
+ DispatchToAgents(render_frame_host_impl->frame_tree_node(),
+ &protocol::TargetHandler::UpdatePortals);
+}
+
} // namespace devtools_instrumentation
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_instrumentation.h b/chromium/content/browser/devtools/devtools_instrumentation.h
index 605e388043a..0ef3544d94b 100644
--- a/chromium/content/browser/devtools/devtools_instrumentation.h
+++ b/chromium/content/browser/devtools/devtools_instrumentation.h
@@ -74,6 +74,10 @@ void OnNavigationRequestFailed(
const NavigationRequest& nav_request,
const network::URLLoaderCompletionStatus& status);
+void WillBeginDownload(int render_process_id,
+ int render_frame_id,
+ const GURL& url);
+
void OnSignedExchangeReceived(
FrameTreeNode* frame_tree_node,
base::Optional<const base::UnguessableToken> devtools_navigation_token,
@@ -112,6 +116,10 @@ bool HandleCertificateError(WebContents* web_contents,
const GURL& request_url,
CertErrorCallback callback);
+void PortalAttached(RenderFrameHostImpl* render_frame_host_impl);
+void PortalDetached(RenderFrameHostImpl* render_frame_host_impl);
+void PortalActivated(RenderFrameHostImpl* render_frame_host_impl);
+
} // namespace devtools_instrumentation
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding.cc b/chromium/content/browser/devtools/devtools_protocol_encoding.cc
new file mode 100644
index 00000000000..8ca4717da58
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding.cc
@@ -0,0 +1,48 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/devtools_protocol_encoding.h"
+
+#include "base/strings/string_number_conversions.h"
+
+namespace content {
+namespace {
+using ::inspector_protocol_encoding::span;
+using ::inspector_protocol_encoding::json::ConvertCBORToJSON;
+using ::inspector_protocol_encoding::json::ConvertJSONToCBOR;
+using IPEStatus = ::inspector_protocol_encoding::Status;
+
+// Platform allows us to inject the string<->double conversion
+// routines from base:: into the inspector_protocol JSON parser / serializer.
+class Platform : public ::inspector_protocol_encoding::json::Platform {
+ public:
+ bool StrToD(const char* str, double* result) const override {
+ return base::StringToDouble(str, result);
+ }
+
+ // Prints |value| in a format suitable for JSON.
+ std::unique_ptr<char[]> DToStr(double value) const override {
+ std::string str = base::NumberToString(value);
+ std::unique_ptr<char[]> result(new char[str.size() + 1]);
+ memcpy(result.get(), str.c_str(), str.size() + 1);
+ return result;
+ }
+};
+} // namespace
+
+IPEStatus ConvertCBORToJSON(span<uint8_t> cbor, std::string* json) {
+ Platform platform;
+ return ConvertCBORToJSON(platform, cbor, json);
+}
+
+IPEStatus ConvertJSONToCBOR(span<uint8_t> json, std::string* cbor) {
+ Platform platform;
+ return ConvertJSONToCBOR(platform, json, cbor);
+}
+
+IPEStatus ConvertJSONToCBOR(span<uint8_t> json, std::vector<uint8_t>* cbor) {
+ Platform platform;
+ return ConvertJSONToCBOR(platform, json, cbor);
+}
+} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding.h b/chromium/content/browser/devtools/devtools_protocol_encoding.h
new file mode 100644
index 00000000000..8faa144baeb
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding.h
@@ -0,0 +1,32 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_ENCODING_H_
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_ENCODING_H_
+
+#include <memory>
+#include "third_party/inspector_protocol/encoding/encoding.h"
+
+// Convenience adaptations of the conversion functions
+// ::inspector_protocol_encoding::json::ConvertCBORToJSON
+// ::inspector_protocol_encoding::json::ConvertJDONToCBOR.
+// These adaptations use an implementation of
+// ::inspector_protocol_encoding::json::Platform that
+// uses base/strings/string_number_conversions.h.
+namespace content {
+
+::inspector_protocol_encoding::Status ConvertCBORToJSON(
+ ::inspector_protocol_encoding::span<uint8_t> cbor,
+ std::string* json);
+
+::inspector_protocol_encoding::Status ConvertJSONToCBOR(
+ ::inspector_protocol_encoding::span<uint8_t> json,
+ std::string* cbor);
+
+::inspector_protocol_encoding::Status ConvertJSONToCBOR(
+ ::inspector_protocol_encoding::span<uint8_t> json,
+ std::vector<uint8_t>* cbor);
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_ENCODING_H_
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer.cc b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer.cc
new file mode 100644
index 00000000000..ad57032ef6b
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer.cc
@@ -0,0 +1,26 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/devtools_protocol_encoding.h"
+
+#include <string>
+#include "third_party/inspector_protocol/encoding/encoding.h"
+
+// A corpus for this fuzzer is located in
+// devtools_protocol_encoding_cbor_fuzzer_corpus.
+// The files contained therein were generated from JSON examples,
+// by running the transcode utility from
+// https://chromium.googlesource.com/deps/inspector_protocol/
+
+namespace content {
+namespace {
+using ::inspector_protocol_encoding::span;
+} // namespace
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::string cbor;
+ content::ConvertJSONToCBOR(span<uint8_t>(data, size), &cbor);
+ return 0;
+}
+} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor1 b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor1
new file mode 100644
index 00000000000..60cf1598b27
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor1
Binary files differ
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor10 b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor10
new file mode 100644
index 00000000000..e8a4aa1c115
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor10
Binary files differ
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor2 b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor2
new file mode 100644
index 00000000000..c6a596fd1bc
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor2
Binary files differ
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor3 b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor3
new file mode 100644
index 00000000000..471ac03ef32
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor3
Binary files differ
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor4 b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor4
new file mode 100644
index 00000000000..7337c061436
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor4
Binary files differ
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor5 b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor5
new file mode 100644
index 00000000000..19a68abaf10
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor5
Binary files differ
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor6 b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor6
new file mode 100644
index 00000000000..04bed6fe806
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor6
Binary files differ
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor7 b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor7
new file mode 100644
index 00000000000..f2ae80c2cc9
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor7
Binary files differ
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor8 b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor8
new file mode 100644
index 00000000000..e1c94ce22d8
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor8
Binary files differ
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor9 b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor9
new file mode 100644
index 00000000000..7bdf5d34b2b
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/cbor9
Binary files differ
diff --git a/chromium/content/browser/devtools/devtools_protocol_encoding_json_fuzzer.cc b/chromium/content/browser/devtools/devtools_protocol_encoding_json_fuzzer.cc
new file mode 100644
index 00000000000..b20782b682c
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_protocol_encoding_json_fuzzer.cc
@@ -0,0 +1,20 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/devtools_protocol_encoding.h"
+
+#include <string>
+#include "third_party/inspector_protocol/encoding/encoding.h"
+
+namespace content {
+namespace {
+using ::inspector_protocol_encoding::span;
+} // namespace
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::string json;
+ content::ConvertJSONToCBOR(span<uint8_t>(data, size), &json);
+ return 0;
+}
+} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_session.cc b/chromium/content/browser/devtools/devtools_session.cc
index 8fc303cb611..1c47409b16b 100644
--- a/chromium/content/browser/devtools/devtools_session.cc
+++ b/chromium/content/browser/devtools/devtools_session.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "content/browser/devtools/devtools_manager.h"
-#include "content/browser/devtools/devtools_session_encoding.h"
+#include "content/browser/devtools/devtools_protocol_encoding.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/protocol.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
@@ -17,20 +17,22 @@
#include "content/public/browser/devtools_manager_delegate.h"
#include "third_party/inspector_protocol/encoding/encoding.h"
-using inspector_protocol_encoding::SpanFrom;
-using inspector_protocol_encoding::cbor::IsCBORMessage;
-
namespace content {
-
namespace {
+using ::inspector_protocol_encoding::span;
+using ::inspector_protocol_encoding::SpanFrom;
+using ::inspector_protocol_encoding::cbor::AppendString8EntryToCBORMap;
+using ::inspector_protocol_encoding::cbor::IsCBORMessage;
+using IPEStatus = ::inspector_protocol_encoding::Status;
bool ShouldSendOnIO(const std::string& method) {
// Keep in sync with WebDevToolsAgent::ShouldInterruptForMethod.
- // TODO(dgozman): find a way to share this.
+ // TODO(einbinder): find a way to share this.
return method == "Debugger.pause" || method == "Debugger.setBreakpoint" ||
method == "Debugger.setBreakpointByUrl" ||
method == "Debugger.removeBreakpoint" ||
method == "Debugger.setBreakpointsActive" ||
+ method == "Debugger.getStackTrace" ||
method == "Performance.getMetrics" || method == "Page.crash" ||
method == "Runtime.terminateExecution" ||
method == "Emulation.setScriptExecutionDisabled";
@@ -77,11 +79,6 @@ DevToolsSession* DevToolsSession::GetRootSession() {
return root_session_ ? root_session_ : this;
}
-bool DevToolsSession::UsesBinaryProtocol() const {
- return client_->UsesBinaryProtocol() ||
- EnableInternalDevToolsBinaryProtocol();
-}
-
void DevToolsSession::AddHandler(
std::unique_ptr<protocol::DevToolsDomainHandler> handler) {
DCHECK(agent_host_);
@@ -151,8 +148,10 @@ bool DevToolsSession::DispatchProtocolMessage(const std::string& message) {
if (proxy_delegate_) {
if (client_->UsesBinaryProtocol()) {
DCHECK(IsCBORMessage(SpanFrom(message)));
- proxy_delegate_->SendMessageToBackend(
- this, ConvertCBORToJSON(SpanFrom(message)));
+ std::string json;
+ IPEStatus status = ConvertCBORToJSON(SpanFrom(message), &json);
+ LOG_IF(ERROR, !status.ok()) << status.ToASCIIString();
+ proxy_delegate_->SendMessageToBackend(this, json);
return true;
}
proxy_delegate_->SendMessageToBackend(this, message);
@@ -160,22 +159,19 @@ bool DevToolsSession::DispatchProtocolMessage(const std::string& message) {
}
std::string converted_cbor_message;
const std::string* message_to_send = &message;
- std::unique_ptr<protocol::DictionaryValue> value;
- if (!EnableInternalDevToolsBinaryProtocol()) {
- value = protocol::DictionaryValue::cast(protocol::StringUtil::parseMessage(
- message, client_->UsesBinaryProtocol()));
+ if (client_->UsesBinaryProtocol()) {
+ // If the client uses the binary protocol, then |message| is already
+ // CBOR (it comes from the client).
+ DCHECK(IsCBORMessage(SpanFrom(message)));
} else {
- if (client_->UsesBinaryProtocol()) {
- // If the client uses the binary protocol, then |message| is already
- // CBOR (it comes from the client).
- DCHECK(IsCBORMessage(SpanFrom(message)));
- } else {
- converted_cbor_message = ConvertJSONToCBOR(SpanFrom(message));
- message_to_send = &converted_cbor_message;
- }
- value = protocol::DictionaryValue::cast(
- protocol::StringUtil::parseMessage(*message_to_send, true));
+ IPEStatus status =
+ ConvertJSONToCBOR(SpanFrom(message), &converted_cbor_message);
+ LOG_IF(ERROR, !status.ok()) << status.ToASCIIString();
+ message_to_send = &converted_cbor_message;
}
+ std::unique_ptr<protocol::DictionaryValue> value =
+ protocol::DictionaryValue::cast(
+ protocol::StringUtil::parseMessage(*message_to_send, true));
std::string session_id;
if (!value || !value->getString(kSessionId, &session_id))
@@ -282,16 +278,16 @@ static void SendProtocolResponseOrNotification(
DevToolsAgentHostClient* client,
DevToolsAgentHostImpl* agent_host,
std::unique_ptr<protocol::Serializable> message) {
- if (!EnableInternalDevToolsBinaryProtocol()) {
- bool binary = client->UsesBinaryProtocol();
- client->DispatchProtocolMessage(agent_host, message->serialize(binary));
- return;
- }
std::string cbor = message->serialize(/*binary=*/true);
DCHECK(IsCBORMessage(SpanFrom(cbor)));
- client->DispatchProtocolMessage(
- agent_host,
- client->UsesBinaryProtocol() ? cbor : ConvertCBORToJSON(SpanFrom(cbor)));
+ if (client->UsesBinaryProtocol()) {
+ client->DispatchProtocolMessage(agent_host, cbor);
+ return;
+ }
+ std::string json;
+ IPEStatus status = ConvertCBORToJSON(SpanFrom(cbor), &json);
+ LOG_IF(ERROR, !status.ok()) << status.ToASCIIString();
+ client->DispatchProtocolMessage(agent_host, json);
}
void DevToolsSession::sendProtocolResponse(
@@ -316,23 +312,18 @@ static void DispatchProtocolResponseOrNotification(
DevToolsAgentHostClient* client,
DevToolsAgentHostImpl* agent_host,
blink::mojom::DevToolsMessagePtr message) {
- // TODO(johannes): When eliminating the
- // --enable-internal-devtools-binary-protocol flag, reconsider the similarity
- // with SendProtocolResponseOrNotification above and either merge the methods
- // or inline them again.
- if (!EnableInternalDevToolsBinaryProtocol()) {
- client->DispatchProtocolMessage(
- agent_host,
- std::string(reinterpret_cast<const char*>(message->data.data()),
- message->data.size()));
+ span<uint8_t> cbor(message->data.data(), message->data.size());
+ DCHECK(IsCBORMessage(cbor));
+ if (client->UsesBinaryProtocol()) {
+ client->DispatchProtocolMessage(agent_host,
+ std::string(cbor.begin(), cbor.end()));
return;
}
- std::string cbor(reinterpret_cast<const char*>(message->data.data()),
- message->data.size());
- DCHECK(IsCBORMessage(SpanFrom(cbor)));
- client->DispatchProtocolMessage(
- agent_host,
- client->UsesBinaryProtocol() ? cbor : ConvertCBORToJSON(SpanFrom(cbor)));
+ std::string json;
+ IPEStatus status = ConvertCBORToJSON(cbor, &json);
+ // TODO(johannes): Should we kill renderer if !status.ok() ?
+ LOG_IF(ERROR, !status.ok()) << status.ToASCIIString();
+ client->DispatchProtocolMessage(agent_host, json);
}
void DevToolsSession::DispatchProtocolResponse(
@@ -356,22 +347,21 @@ void DevToolsSession::DispatchProtocolNotification(
}
void DevToolsSession::DispatchOnClientHost(const std::string& message) {
- if (!EnableInternalDevToolsBinaryProtocol()) {
- client_->DispatchProtocolMessage(agent_host_, message);
- return;
- }
// |message| either comes from a web socket, in which case it's JSON.
// Or it comes from another devtools_session, in which case it may be CBOR
// already. We auto-detect and convert to what the client wants as needed.
inspector_protocol_encoding::span<uint8_t> bytes = SpanFrom(message);
bool is_cbor_message = IsCBORMessage(bytes);
- if (client_->UsesBinaryProtocol()) {
- client_->DispatchProtocolMessage(
- agent_host_, is_cbor_message ? message : ConvertJSONToCBOR(bytes));
- } else {
- client_->DispatchProtocolMessage(
- agent_host_, !is_cbor_message ? message : ConvertCBORToJSON(bytes));
+ if (client_->UsesBinaryProtocol() == is_cbor_message) {
+ client_->DispatchProtocolMessage(agent_host_, message);
+ return;
}
+ std::string converted;
+ IPEStatus status = client_->UsesBinaryProtocol()
+ ? ConvertJSONToCBOR(bytes, &converted)
+ : ConvertCBORToJSON(bytes, &converted);
+ LOG_IF(ERROR, !status.ok()) << status.ToASCIIString();
+ client_->DispatchProtocolMessage(agent_host_, converted);
// |this| may be deleted at this point.
}
@@ -391,7 +381,7 @@ void DevToolsSession::ApplySessionStateUpdates(
session_state_cookie_ = blink::mojom::DevToolsSessionState::New();
for (auto& entry : updates->entries) {
if (entry.second.has_value())
- session_state_cookie_->entries[entry.first] = std::move(entry.second);
+ session_state_cookie_->entries[entry.first] = std::move(*entry.second);
else
session_state_cookie_->entries.erase(entry.first);
}
@@ -421,32 +411,21 @@ void DevToolsSession::SendMessageFromChildSession(const std::string& session_id,
const std::string& message) {
if (child_sessions_.find(session_id) == child_sessions_.end())
return;
- if (!EnableInternalDevToolsBinaryProtocol()) {
- std::string patched;
- bool patched_ok;
- if (client_->UsesBinaryProtocol()) {
- patched_ok = protocol::AppendStringValueToMapBinary(message, kSessionId,
- session_id, &patched);
- } else {
- patched_ok = protocol::AppendStringValueToMapJSON(message, kSessionId,
- session_id, &patched);
- }
- if (!patched_ok)
- return;
+ DCHECK(IsCBORMessage(SpanFrom(message)));
+ std::string patched(message);
+ IPEStatus status = AppendString8EntryToCBORMap(
+ SpanFrom(kSessionId), SpanFrom(session_id), &patched);
+ LOG_IF(ERROR, !status.ok()) << status.ToASCIIString();
+ if (!status.ok())
+ return;
+ if (client_->UsesBinaryProtocol()) {
client_->DispatchProtocolMessage(agent_host_, patched);
- // |this| may be deleted at this point.
return;
}
- DCHECK(IsCBORMessage(SpanFrom(message)));
- std::string patched;
- bool patched_ok = protocol::AppendStringValueToMapBinary(
- message, kSessionId, session_id, &patched);
- if (!patched_ok)
- return;
- client_->DispatchProtocolMessage(agent_host_,
- client_->UsesBinaryProtocol()
- ? patched
- : ConvertCBORToJSON(SpanFrom(patched)));
+ std::string json;
+ status = ConvertCBORToJSON(SpanFrom(patched), &json);
+ LOG_IF(ERROR, !status.ok()) << status.ToASCIIString();
+ client_->DispatchProtocolMessage(agent_host_, json);
// |this| may be deleted at this point.
}
diff --git a/chromium/content/browser/devtools/devtools_session.h b/chromium/content/browser/devtools/devtools_session.h
index 619c96e2e71..413d75740b6 100644
--- a/chromium/content/browser/devtools/devtools_session.h
+++ b/chromium/content/browser/devtools/devtools_session.h
@@ -42,11 +42,6 @@ class DevToolsSession : public protocol::FrontendChannel,
DevToolsAgentHostClient* client() { return client_; }
DevToolsSession* GetRootSession();
- // Whether this session uses binary protocol. This is true if
- // |client()->UsesBinaryProtocol()| or if the
- // --enable-devtools-binary-protocol flag is set.
- bool UsesBinaryProtocol() const;
-
// Browser-only sessions do not talk to mojom::DevToolsAgent, but instead
// handle all protocol messages locally in the browser process.
void SetBrowserOnly(bool browser_only);
diff --git a/chromium/content/browser/devtools/devtools_session_encoding.cc b/chromium/content/browser/devtools/devtools_session_encoding.cc
deleted file mode 100644
index e80f003e251..00000000000
--- a/chromium/content/browser/devtools/devtools_session_encoding.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/devtools/devtools_session_encoding.h"
-
-#include <memory>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/strings/string_number_conversions.h"
-#include "content/public/common/content_switches.h"
-#include "third_party/inspector_protocol/encoding/encoding.h"
-
-using inspector_protocol_encoding::span;
-using inspector_protocol_encoding::json::ConvertCBORToJSON;
-using inspector_protocol_encoding::json::ConvertJSONToCBOR;
-using inspector_protocol_encoding::json::Platform;
-
-namespace content {
-namespace {
-// ContentShellPlatform allows us to inject the string<->double conversion
-// routines from base:: into the inspector_protocol JSON parser / serializer.
-class ContentShellPlatform : public Platform {
- public:
- bool StrToD(const char* str, double* result) const override {
- return base::StringToDouble(str, result);
- }
-
- // Prints |value| in a format suitable for JSON.
- std::unique_ptr<char[]> DToStr(double value) const override {
- std::string str = base::NumberToString(value);
- std::unique_ptr<char[]> result(new char[str.size() + 1]);
- memcpy(result.get(), str.c_str(), str.size() + 1);
- return result;
- }
-};
-} // namespace
-bool EnableInternalDevToolsBinaryProtocol() {
- return false;
-}
-
-// TODO(johannes): Push error handling to client code after devtools_session.cc
-// is simplified.
-std::string ConvertCBORToJSON(inspector_protocol_encoding::span<uint8_t> cbor) {
- ContentShellPlatform platform;
- std::string json_message;
- inspector_protocol_encoding::Status status =
- ConvertCBORToJSON(platform, cbor, &json_message);
- if (!status.ok()) {
- LOG(ERROR) << "ConvertCBORToJSON error "
- << static_cast<uint32_t>(status.error) << " position "
- << static_cast<uint32_t>(status.pos);
- return "";
- }
- return json_message;
-}
-
-std::string ConvertJSONToCBOR(inspector_protocol_encoding::span<uint8_t> json) {
- ContentShellPlatform platform;
- std::string cbor;
- inspector_protocol_encoding::Status status =
- ConvertJSONToCBOR(platform, json, &cbor);
- if (!status.ok()) {
- LOG(ERROR) << "ConvertJSONToCBOR error "
- << static_cast<uint32_t>(status.error) << " position "
- << static_cast<uint32_t>(status.pos);
- return "";
- }
- return cbor;
-}
-} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_session_encoding.h b/chromium/content/browser/devtools/devtools_session_encoding.h
deleted file mode 100644
index e85874f67a0..00000000000
--- a/chromium/content/browser/devtools/devtools_session_encoding.h
+++ /dev/null
@@ -1,25 +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_DEVTOOLS_DEVTOOLS_SESSION_ENCODING_H_
-#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_SESSION_ENCODING_H_
-
-#include <string>
-
-#include "third_party/inspector_protocol/encoding/encoding.h"
-
-namespace content {
-
-// Whether --enable-internal-devtools-binary-parotocol was passed on the command
-// line. If so, the DevtoolsSession will convert all outgoing traffic to agents
-// / handlers / etc. to the CBOR-based binary protocol.
-bool EnableInternalDevToolsBinaryProtocol();
-
-// Conversion routines between the inspector protocol binary wire format
-// (based on CBOR RFC 7049) and JSON.
-std::string ConvertCBORToJSON(inspector_protocol_encoding::span<uint8_t> cbor);
-std::string ConvertJSONToCBOR(inspector_protocol_encoding::span<uint8_t> json);
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_SESSION_ENCODING_H_
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 32cff2f921b..bebd340f911 100644
--- a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
+++ b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
@@ -58,6 +58,7 @@ class DevToolsURLInterceptorRequestJob::SubRequest
net::URLRequest* request,
net::SSLCertRequestInfo* cert_request_info) override;
void OnSSLCertificateError(net::URLRequest* request,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal) override;
void OnResponseStarted(net::URLRequest* request, int net_error) override;
@@ -201,9 +202,11 @@ void DevToolsURLInterceptorRequestJob::SubRequest::OnCertificateRequested(
void DevToolsURLInterceptorRequestJob::SubRequest::OnSSLCertificateError(
net::URLRequest* request,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal) {
- devtools_interceptor_request_job_->NotifySSLCertificateError(ssl_info, fatal);
+ devtools_interceptor_request_job_->NotifySSLCertificateError(net_error,
+ ssl_info, fatal);
}
void DevToolsURLInterceptorRequestJob::SubRequest::OnResponseStarted(
@@ -547,6 +550,8 @@ DevToolsURLInterceptorRequestJob::DevToolsURLInterceptorRequestJob(
: net::URLRequestJob(original_request, original_network_delegate),
interceptor_(interceptor),
request_details_(original_request->url(),
+ original_request->site_for_cookies(),
+ original_request->initiator(),
original_request->method(),
GetUploadData(original_request),
original_request->extra_request_headers(),
@@ -1026,6 +1031,11 @@ void DevToolsURLInterceptorRequestJob::ProcessInterceptionResponse(
// Set cookies in the network stack.
net::CookieOptions options;
options.set_include_httponly();
+ options.set_same_site_cookie_context(
+ net::cookie_util::ComputeSameSiteContextForResponse(
+ request_details_.url, request_details_.site_for_cookies,
+ request_details_.initiator));
+
base::Time response_date;
if (!mock_response_details_->response_headers()->GetDateValue(
&response_date)) {
@@ -1159,6 +1169,8 @@ void DevToolsURLInterceptorRequestJob::ContinueDespiteLastError() {
DevToolsURLInterceptorRequestJob::RequestDetails::RequestDetails(
const GURL& url,
+ const GURL& site_for_cookies,
+ base::Optional<url::Origin> initiator,
const std::string& method,
std::unique_ptr<net::UploadDataStream> post_data,
const net::HttpRequestHeaders& extra_request_headers,
@@ -1167,6 +1179,8 @@ DevToolsURLInterceptorRequestJob::RequestDetails::RequestDetails(
const net::RequestPriority& priority,
const net::URLRequestContext* url_request_context)
: url(url),
+ site_for_cookies(site_for_cookies),
+ initiator(std::move(initiator)),
method(method),
post_data(std::move(post_data)),
extra_request_headers(extra_request_headers),
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 7a22e70e1f8..08d163fd2c6 100644
--- a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h
+++ b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h
@@ -92,6 +92,8 @@ class DevToolsURLInterceptorRequestJob : public net::URLRequestJob {
// fields.
struct RequestDetails {
RequestDetails(const GURL& url,
+ const GURL& site_for_cookies,
+ base::Optional<url::Origin> initiator,
const std::string& method,
std::unique_ptr<net::UploadDataStream> post_data,
const net::HttpRequestHeaders& extra_request_headers,
@@ -102,6 +104,8 @@ class DevToolsURLInterceptorRequestJob : public net::URLRequestJob {
~RequestDetails();
GURL url;
+ GURL site_for_cookies;
+ base::Optional<url::Origin> initiator;
std::string method;
std::unique_ptr<net::UploadDataStream> post_data;
std::string cookie_line;
diff --git a/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc b/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
index 9a8614da82e..9783b88adf7 100644
--- a/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
+++ b/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -166,7 +166,7 @@ struct ResponseMetadata {
network::ResourceResponseHead head;
std::unique_ptr<net::RedirectInfo> redirect_info;
- std::vector<uint8_t> cached_metadata;
+ mojo_base::BigBuffer cached_metadata;
size_t encoded_length = 0;
size_t transfer_size = 0;
network::URLLoaderCompletionStatus status;
@@ -276,7 +276,7 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
@@ -1039,8 +1039,7 @@ Response InterceptionJob::ProcessResponseOverride(
void InterceptionJob::ProcessSetCookies(const net::HttpResponseHeaders& headers,
base::OnceClosure callback) {
- if (create_loader_params_->request.load_flags &
- net::LOAD_DO_NOT_SAVE_COOKIES) {
+ if (!create_loader_params_->request.SavesCookies()) {
std::move(callback).Run();
return;
}
@@ -1050,6 +1049,12 @@ void InterceptionJob::ProcessSetCookies(const net::HttpResponseHeaders& headers,
size_t iter = 0;
net::CookieOptions options;
options.set_include_httponly();
+ options.set_same_site_cookie_context(
+ net::cookie_util::ComputeSameSiteContextForResponse(
+ create_loader_params_->request.url,
+ create_loader_params_->request.site_for_cookies,
+ create_loader_params_->request.request_initiator));
+
std::vector<std::unique_ptr<net::CanonicalCookie>> cookies;
base::Time response_date;
if (headers.GetDateValue(&response_date))
@@ -1100,8 +1105,9 @@ void InterceptionJob::ProcessRedirectByClient(const GURL& redirect_url) {
void InterceptionJob::SendResponse(scoped_refptr<base::RefCountedMemory> body,
size_t offset) {
client_->OnReceiveResponse(response_metadata_->head);
- if (!response_metadata_->cached_metadata.empty())
- client_->OnReceiveCachedMetadata(response_metadata_->cached_metadata);
+ if (response_metadata_->cached_metadata.size() != 0)
+ client_->OnReceiveCachedMetadata(
+ std::move(response_metadata_->cached_metadata));
if (body) {
DCHECK_LE(offset, body->size());
@@ -1186,8 +1192,7 @@ std::unique_ptr<InterceptedRequestInfo> InterceptionJob::BuildRequestInfo(
void InterceptionJob::FetchCookies(
network::mojom::CookieManager::GetCookieListCallback callback) {
- if (create_loader_params_->request.load_flags &
- net::LOAD_DO_NOT_SEND_COOKIES) {
+ if (!create_loader_params_->request.SendsCookies()) {
std::move(callback).Run({}, {});
return;
}
@@ -1360,12 +1365,11 @@ void InterceptionJob::OnUploadProgress(int64_t current_position,
client_->OnUploadProgress(current_position, total_size, std::move(callback));
}
-void InterceptionJob::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
+void InterceptionJob::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
if (ShouldBypassForResponse())
- client_->OnReceiveCachedMetadata(data);
+ client_->OnReceiveCachedMetadata(std::move(data));
else
- response_metadata_->cached_metadata = data;
+ response_metadata_->cached_metadata = std::move(data);
}
void InterceptionJob::OnTransferSizeUpdated(int32_t transfer_size_diff) {
diff --git a/chromium/content/browser/devtools/devtools_video_consumer.cc b/chromium/content/browser/devtools/devtools_video_consumer.cc
index 8859f8f72a2..2bd1bbd848c 100644
--- a/chromium/content/browser/devtools/devtools_video_consumer.cc
+++ b/chromium/content/browser/devtools/devtools_video_consumer.cc
@@ -59,7 +59,7 @@ SkBitmap DevToolsVideoConsumer::GetSkBitmapFromFrame(
skbitmap.allocN32Pixels(frame->visible_rect().width(),
frame->visible_rect().height());
cc::SkiaPaintCanvas canvas(skbitmap);
- renderer.Copy(frame, &canvas, media::Context3D(), nullptr);
+ renderer.Copy(frame, &canvas, nullptr);
return skbitmap;
}
diff --git a/chromium/content/browser/devtools/inspector_fuzzer.cc b/chromium/content/browser/devtools/inspector_fuzzer.cc
new file mode 100644
index 00000000000..4c45d1e8499
--- /dev/null
+++ b/chromium/content/browser/devtools/inspector_fuzzer.cc
@@ -0,0 +1,33 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "third_party/inspector_protocol/encoding/encoding.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ using namespace inspector_protocol_encoding;
+
+ if (size > 64 * 1024) {
+ return 0;
+ }
+
+ span<uint8_t> fuzz{data, size};
+
+ // We need to handle whatever the parser parses. So, we handle the parsed
+ // stuff with another CBOR encoder, just because it's conveniently available.
+ std::vector<uint8_t> encoded;
+ Status status;
+ std::unique_ptr<StreamingParserHandler> encoder =
+ cbor::NewCBOREncoder(&encoded, &status);
+
+ cbor::ParseCBOR(fuzz, encoder.get());
+
+ return 0;
+}
diff --git a/chromium/content/browser/devtools/protocol/background_service_handler.cc b/chromium/content/browser/devtools/protocol/background_service_handler.cc
index dc2419a85cb..d5a174ab72a 100644
--- a/chromium/content/browser/devtools/protocol/background_service_handler.cc
+++ b/chromium/content/browser/devtools/protocol/background_service_handler.cc
@@ -4,6 +4,7 @@
#include "content/browser/devtools/protocol/background_service_handler.h"
+#include "base/metrics/histogram_functions.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/storage_partition_impl.h"
@@ -21,6 +22,12 @@ devtools::proto::BackgroundService ServiceNameToEnum(
} else if (service_name ==
BackgroundService::ServiceNameEnum::BackgroundSync) {
return devtools::proto::BackgroundService::BACKGROUND_SYNC;
+ } else if (service_name ==
+ BackgroundService::ServiceNameEnum::PushMessaging) {
+ return devtools::proto::BackgroundService::PUSH_MESSAGING;
+ } else if (service_name ==
+ BackgroundService::ServiceNameEnum::Notifications) {
+ return devtools::proto::BackgroundService::NOTIFICATIONS;
}
return devtools::proto::BackgroundService::UNKNOWN;
}
@@ -31,6 +38,10 @@ std::string ServiceEnumToName(devtools::proto::BackgroundService service_enum) {
return BackgroundService::ServiceNameEnum::BackgroundFetch;
case devtools::proto::BackgroundService::BACKGROUND_SYNC:
return BackgroundService::ServiceNameEnum::BackgroundSync;
+ case devtools::proto::BackgroundService::PUSH_MESSAGING:
+ return BackgroundService::ServiceNameEnum::PushMessaging;
+ case devtools::proto::BackgroundService::NOTIFICATIONS:
+ return BackgroundService::ServiceNameEnum::Notifications;
default:
NOTREACHED();
}
@@ -188,10 +199,13 @@ Response BackgroundServiceHandler::SetRecording(bool should_record,
if (service_enum == devtools::proto::BackgroundService::UNKNOWN)
return Response::InvalidParams("Invalid service name");
- if (should_record)
+ if (should_record) {
devtools_context_->StartRecording(service_enum);
- else
+ base::UmaHistogramEnumeration("DevTools.BackgroundService.StartRecording",
+ service_enum, devtools::proto::COUNT);
+ } else {
devtools_context_->StopRecording(service_enum);
+ }
return Response::OK();
}
diff --git a/chromium/content/browser/devtools/protocol/background_service_handler.h b/chromium/content/browser/devtools/protocol/background_service_handler.h
index 9b35cc48e89..5bd4a704573 100644
--- a/chromium/content/browser/devtools/protocol/background_service_handler.h
+++ b/chromium/content/browser/devtools/protocol/background_service_handler.h
@@ -13,7 +13,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/devtools/devtools_background_services.pb.h"
-#include "content/browser/devtools/devtools_background_services_context.h"
+#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include "content/browser/devtools/protocol/background_service.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
@@ -26,7 +26,7 @@ namespace protocol {
class BackgroundServiceHandler
: public DevToolsDomainHandler,
public BackgroundService::Backend,
- public DevToolsBackgroundServicesContext::EventObserver {
+ public DevToolsBackgroundServicesContextImpl::EventObserver {
public:
BackgroundServiceHandler();
~BackgroundServiceHandler() override;
@@ -59,7 +59,7 @@ class BackgroundServiceHandler
std::unique_ptr<BackgroundService::Frontend> frontend_;
// Owned by the storage partition.
- DevToolsBackgroundServicesContext* devtools_context_;
+ DevToolsBackgroundServicesContextImpl* devtools_context_;
base::flat_set<devtools::proto::BackgroundService> enabled_services_;
diff --git a/chromium/content/browser/devtools/protocol/browser_handler.cc b/chromium/content/browser/devtools/protocol/browser_handler.cc
index 17af5799ae2..91a1f18e641 100644
--- a/chromium/content/browser/devtools/protocol/browser_handler.cc
+++ b/chromium/content/browser/devtools/protocol/browser_handler.cc
@@ -144,6 +144,9 @@ Response FromProtocolPermissionType(
*out_type = PermissionType::BACKGROUND_FETCH;
} else if (type == protocol::Browser::PermissionTypeEnum::IdleDetection) {
*out_type = PermissionType::IDLE_DETECTION;
+ } else if (type ==
+ protocol::Browser::PermissionTypeEnum::PeriodicBackgroundSync) {
+ *out_type = PermissionType::PERIODIC_BACKGROUND_SYNC;
} else {
return Response::InvalidParams("Unknown permission type: " + type);
}
@@ -280,8 +283,7 @@ Response BrowserHandler::Crash() {
}
Response BrowserHandler::CrashGpuProcess() {
- GpuProcessHost::CallOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- false /* force_create */,
+ GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
base::BindOnce([](GpuProcessHost* host) {
if (host)
host->gpu_service()->Crash();
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 67abfa91c44..248c9702cd4 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -57,7 +57,6 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/layout.h"
-#include "ui/base/ui_base_features.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
@@ -503,9 +502,6 @@ class CaptureScreenshotTest : public DevToolsProtocolTest {
};
IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) {
- // TODO(crbug.com/877172): CopyOutputRequests not allowed.
- if (features::IsSingleProcessMash())
- return;
// This test fails consistently on low-end Android devices.
// See crbug.com/653637.
// TODO(eseckler): Reenable with error limit if necessary.
@@ -528,9 +524,6 @@ IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) {
}
IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshotJpeg) {
- // TODO(crbug.com/877172): CopyOutputRequests not allowed.
- if (features::IsSingleProcessMash())
- return;
// This test fails consistently on low-end Android devices.
// See crbug.com/653637.
// TODO(eseckler): Reenable with error limit if necessary.
@@ -582,9 +575,6 @@ IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
// of a page that does not specify one.
IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
SetDefaultBackgroundColorOverride) {
- // TODO(crbug.com/877172): CopyOutputRequests not allowed.
- if (features::IsSingleProcessMash())
- return;
if (base::SysInfo::IsLowEndDevice())
return;
@@ -625,9 +615,6 @@ IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
// and semi-transparent background, and that setDeviceMetricsOverride doesn't
// affect it.
IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, TransparentScreenshots) {
- // TODO(crbug.com/877172): CopyOutputRequests not allowed.
- if (features::IsSingleProcessMash())
- return;
if (base::SysInfo::IsLowEndDevice())
return;
@@ -2011,8 +1998,6 @@ class TestShellDownloadManagerDelegate : public ShellDownloadManagerDelegate {
return true;
}
- bool GenerateFileHash() override { return true; }
-
void SetDelayedOpen(bool delay) { delay_download_open_ = delay; }
void GetDelayedCallbacks(
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc
index f74ff055eac..a8c14fd0b75 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc
@@ -37,7 +37,7 @@ void DevToolsProtocolTest::SetUpOnMainThread() {
bool DevToolsProtocolTest::DidAddMessageToConsole(
WebContents* source,
- int32_t level,
+ blink::mojom::ConsoleMessageLevel log_level,
const base::string16& message,
int32_t line_no,
const base::string16& source_id) {
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h b/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h
index cb8a49967f9..23d51162072 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h
@@ -31,7 +31,7 @@ class DevToolsProtocolTest : public ContentBrowserTest,
protected:
// WebContentsDelegate methods:
bool DidAddMessageToConsole(WebContents* source,
- int32_t level,
+ blink::mojom::ConsoleMessageLevel log_level,
const base::string16& message,
int32_t line_no,
const base::string16& source_id) override;
diff --git a/chromium/content/browser/devtools/protocol/network_handler.cc b/chromium/content/browser/devtools/protocol/network_handler.cc
index d7545bfecdb..529de117c9e 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.cc
+++ b/chromium/content/browser/devtools/protocol/network_handler.cc
@@ -50,7 +50,7 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
-#include "content/public/common/content_switches.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/origin_util.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_endpoint.h"
@@ -130,17 +130,19 @@ std::unique_ptr<Network::Cookie> BuildCookie(
.SetSession(!cookie.IsPersistent())
.Build();
- // TODO(chlily): Add EXTENDED_MODE and UNSPECIFIED to devtools'
- // Network::CookieSameSiteEnum.
switch (cookie.SameSite()) {
case net::CookieSameSite::STRICT_MODE:
devtools_cookie->SetSameSite(Network::CookieSameSiteEnum::Strict);
break;
case net::CookieSameSite::LAX_MODE:
- case net::CookieSameSite::EXTENDED_MODE:
devtools_cookie->SetSameSite(Network::CookieSameSiteEnum::Lax);
break;
+ case net::CookieSameSite::EXTENDED_MODE:
+ devtools_cookie->SetSameSite(Network::CookieSameSiteEnum::Extended);
+ break;
case net::CookieSameSite::NO_RESTRICTION:
+ devtools_cookie->SetSameSite(Network::CookieSameSiteEnum::None);
+ break;
case net::CookieSameSite::UNSPECIFIED:
break;
}
@@ -444,11 +446,15 @@ std::unique_ptr<net::CanonicalCookie> MakeCookieFromProtocolValues(
expires ? base::Time::FromDoubleT(expires) : base::Time::UnixEpoch();
}
- net::CookieSameSite css = net::CookieSameSite::NO_RESTRICTION;
+ net::CookieSameSite css = net::CookieSameSite::UNSPECIFIED;
if (same_site == Network::CookieSameSiteEnum::Lax)
css = net::CookieSameSite::LAX_MODE;
if (same_site == Network::CookieSameSiteEnum::Strict)
css = net::CookieSameSite::STRICT_MODE;
+ if (same_site == Network::CookieSameSiteEnum::Extended)
+ css = net::CookieSameSite::EXTENDED_MODE;
+ if (same_site == Network::CookieSameSiteEnum::None)
+ css = net::CookieSameSite::NO_RESTRICTION;
return net::CanonicalCookie::CreateSanitizedCookie(
url, name, value, normalized_domain, path, base::Time(), expiration_date,
@@ -548,8 +554,7 @@ String referrerPolicy(network::mojom::ReferrerPolicy referrer_policy) {
case network::mojom::ReferrerPolicy::kAlways:
return Network::Request::ReferrerPolicyEnum::UnsafeUrl;
case network::mojom::ReferrerPolicy::kDefault:
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kReducedReferrerGranularity)) {
+ if (base::FeatureList::IsEnabled(features::kReducedReferrerGranularity)) {
return Network::Request::ReferrerPolicyEnum::
StrictOriginWhenCrossOrigin;
} else {
@@ -1606,6 +1611,7 @@ std::unique_ptr<Network::Response> BuildResponse(
info.load_timing.request_start_time)
.Build();
response->SetFromServiceWorker(info.was_fetched_via_service_worker);
+ response->SetFromPrefetchCache(info.was_in_prefetch_cache);
network::HttpRawRequestResponseInfo* raw_info =
info.raw_request_response_info.get();
if (raw_info) {
@@ -1979,8 +1985,8 @@ void NetworkHandler::ContinueInterceptedRequest(
LOG(WARNING) << "Can't find headers in raw response";
header_size = 0;
} else {
- raw_headers = net::HttpUtil::AssembleRawHeaders(
- reinterpret_cast<const char*>(raw.data()), header_size);
+ raw_headers = net::HttpUtil::AssembleRawHeaders(base::StringPiece(
+ reinterpret_cast<const char*>(raw.data()), header_size));
}
CHECK_LE(header_size, raw.size());
response_headers =
diff --git a/chromium/content/browser/devtools/protocol/page_handler.cc b/chromium/content/browser/devtools/protocol/page_handler.cc
index d0adc36d21e..a1898c01f49 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.cc
+++ b/chromium/content/browser/devtools/protocol/page_handler.cc
@@ -192,7 +192,6 @@ PageHandler::PageHandler(EmulationHandler* emulation_handler,
screencast_max_height_(-1),
capture_every_nth_frame_(1),
capture_retry_count_(0),
- has_compositor_frame_metadata_(false),
session_id_(0),
frame_counter_(0),
frames_in_flight_(0),
@@ -269,17 +268,10 @@ void PageHandler::Wire(UberDispatcher* dispatcher) {
}
void PageHandler::OnSynchronousSwapCompositorFrame(
- viz::CompositorFrameMetadata frame_metadata) {
- if (has_compositor_frame_metadata_) {
- last_compositor_frame_metadata_ =
- std::move(next_compositor_frame_metadata_);
- } else {
- last_compositor_frame_metadata_ = frame_metadata.Clone();
- }
- next_compositor_frame_metadata_ = std::move(frame_metadata);
-
- has_compositor_frame_metadata_ = true;
-
+ const DevToolsFrameMetadata& frame_metadata) {
+ // Cache |frame_metadata_| as InnerSwapCompositorFrame may also be called on
+ // screencast start.
+ frame_metadata_ = frame_metadata;
if (screencast_enabled_)
InnerSwapCompositorFrame();
}
@@ -521,6 +513,13 @@ void PageHandler::NavigationReset(NavigationRequest* navigation_request) {
navigate_callbacks_.erase(navigate_callback);
}
+void PageHandler::DownloadWillBegin(FrameTreeNode* ftn, const GURL& url) {
+ if (!enabled_)
+ return;
+ frontend_->DownloadWillBegin(ftn->devtools_frame_token().ToString(),
+ url.spec());
+}
+
static const char* TransitionTypeName(ui::PageTransition type) {
int32_t t = type & ~ui::PAGE_TRANSITION_QUALIFIER_MASK;
switch (t) {
@@ -822,7 +821,7 @@ Response PageHandler::StartScreencast(Maybe<std::string> format,
if (!visible)
return Response::FallThrough();
- if (has_compositor_frame_metadata_) {
+ if (frame_metadata_) {
InnerSwapCompositorFrame();
} else {
widget_host->Send(
@@ -975,17 +974,15 @@ void PageHandler::InnerSwapCompositorFrame() {
if (snapshot_size.IsEmpty())
return;
- double top_controls_height =
- last_compositor_frame_metadata_.top_controls_height;
- double top_controls_shown_ratio =
- last_compositor_frame_metadata_.top_controls_shown_ratio;
+ double top_controls_height = frame_metadata_->top_controls_height;
+ double top_controls_shown_ratio = frame_metadata_->top_controls_shown_ratio;
std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata =
BuildScreencastFrameMetadata(
- surface_size, last_compositor_frame_metadata_.device_scale_factor,
- last_compositor_frame_metadata_.page_scale_factor,
- last_compositor_frame_metadata_.root_scroll_offset,
- top_controls_height, top_controls_shown_ratio);
+ surface_size, frame_metadata_->device_scale_factor,
+ frame_metadata_->page_scale_factor,
+ frame_metadata_->root_scroll_offset, top_controls_height,
+ top_controls_shown_ratio);
if (!page_metadata)
return;
diff --git a/chromium/content/browser/devtools/protocol/page_handler.h b/chromium/content/browser/devtools/protocol/page_handler.h
index 4bee8baf7d6..8d22209f5a3 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.h
+++ b/chromium/content/browser/devtools/protocol/page_handler.h
@@ -18,7 +18,7 @@
#include "base/scoped_observer.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "components/viz/common/quads/compositor_frame_metadata.h"
+#include "content/browser/devtools/devtools_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"
@@ -46,6 +46,7 @@ struct WebDeviceEmulationParams;
namespace content {
class DevToolsAgentHostImpl;
+class FrameTreeNode;
class NavigationRequest;
class RenderFrameHostImpl;
class WebContentsImpl;
@@ -68,8 +69,9 @@ class PageHandler : public DevToolsDomainHandler,
void Wire(UberDispatcher* dispatcher) override;
void SetRenderer(int process_host_id,
RenderFrameHostImpl* frame_host) override;
+ // Instrumentation signals.
void OnSynchronousSwapCompositorFrame(
- viz::CompositorFrameMetadata frame_metadata);
+ const DevToolsFrameMetadata& frame_metadata);
void DidAttachInterstitialPage();
void DidDetachInterstitialPage();
bool screencast_enabled() const { return enabled_ && screencast_enabled_; }
@@ -86,6 +88,8 @@ class PageHandler : public DevToolsDomainHandler,
JavaScriptDialogCallback callback);
void DidCloseJavaScriptDialog(bool success, const base::string16& user_input);
void NavigationReset(NavigationRequest* navigation_request);
+ void DownloadWillBegin(FrameTreeNode* ftn, const GURL& url);
+
WebContentsImpl* GetWebContents();
Response Enable() override;
@@ -198,9 +202,7 @@ class PageHandler : public DevToolsDomainHandler,
int screencast_max_height_;
int capture_every_nth_frame_;
int capture_retry_count_;
- bool has_compositor_frame_metadata_;
- viz::CompositorFrameMetadata next_compositor_frame_metadata_;
- viz::CompositorFrameMetadata last_compositor_frame_metadata_;
+ base::Optional<DevToolsFrameMetadata> frame_metadata_;
int session_id_;
int frame_counter_;
int frames_in_flight_;
diff --git a/chromium/content/browser/devtools/protocol/service_worker_handler.cc b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
index 34381dc45e1..01b9511401a 100644
--- a/chromium/content/browser/devtools/protocol/service_worker_handler.cc
+++ b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
@@ -30,7 +30,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/push_messaging_status.mojom.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging_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_provider_type.mojom.h"
#include "url/gurl.h"
@@ -318,8 +318,9 @@ Response ServiceWorkerHandler::DeliverPushMessage(
if (data.size() > 0)
payload = data;
BrowserContext::DeliverPushMessage(
- browser_context_, GURL(origin), id, std::move(payload),
- base::BindRepeating([](mojom::PushDeliveryStatus status) {}));
+ browser_context_, GURL(origin), id, /* push_message_id= */ std::string(),
+ std::move(payload),
+ base::BindRepeating([](blink::mojom::PushDeliveryStatus status) {}));
return Response::OK();
}
diff --git a/chromium/content/browser/devtools/protocol/service_worker_handler.h b/chromium/content/browser/devtools/protocol/service_worker_handler.h
index ec9ab86d0ca..13f25337ba4 100644
--- a/chromium/content/browser/devtools/protocol/service_worker_handler.h
+++ b/chromium/content/browser/devtools/protocol/service_worker_handler.h
@@ -56,6 +56,7 @@ class ServiceWorkerHandler : public DevToolsDomainHandler,
const std::string& registration_id,
const std::string& tag,
bool last_chance) override;
+ // TODO(crbug.com/961238): Add DispatchPeriodicSyncEvent().
private:
void OnWorkerRegistrationUpdated(
diff --git a/chromium/content/browser/devtools/protocol/storage_handler.cc b/chromium/content/browser/devtools/protocol/storage_handler.cc
index 34e104f9988..a6586faec74 100644
--- a/chromium/content/browser/devtools/protocol/storage_handler.cc
+++ b/chromium/content/browser/devtools/protocol/storage_handler.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
@@ -109,55 +110,44 @@ class StorageHandler::CacheStorageObserver : CacheStorageContextImpl::Observer {
CacheStorageObserver(base::WeakPtr<StorageHandler> owner_storage_handler,
CacheStorageContextImpl* cache_storage_context)
: owner_(owner_storage_handler), context_(cache_storage_context) {
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&CacheStorageObserver::AddObserverOnIOThread,
- base::Unretained(this)));
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ context_->AddObserver(this);
}
~CacheStorageObserver() override {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
context_->RemoveObserver(this);
}
- void TrackOriginOnIOThread(const url::Origin& origin) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ void TrackOrigin(const url::Origin& origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (origins_.find(origin) != origins_.end())
return;
origins_.insert(origin);
}
- void UntrackOriginOnIOThread(const url::Origin& origin) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ void UntrackOrigin(const url::Origin& origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
origins_.erase(origin);
}
void OnCacheListChanged(const url::Origin& origin) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto found = origins_.find(origin);
if (found == origins_.end())
return;
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&StorageHandler::NotifyCacheStorageListChanged, owner_,
- origin.Serialize()));
+ owner_->NotifyCacheStorageListChanged(origin.Serialize());
}
void OnCacheContentChanged(const url::Origin& origin,
const std::string& cache_name) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (origins_.find(origin) == origins_.end())
return;
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&StorageHandler::NotifyCacheStorageContentChanged,
- owner_, origin.Serialize(), cache_name));
+ owner_->NotifyCacheStorageContentChanged(origin.Serialize(), cache_name);
}
private:
- void AddObserverOnIOThread() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- context_->AddObserver(this);
- }
-
// Maintained on the IO thread to avoid thread contention.
base::flat_set<url::Origin> origins_;
@@ -264,10 +254,7 @@ void StorageHandler::SetRenderer(int process_host_id,
}
Response StorageHandler::Disable() {
- if (cache_storage_observer_) {
- BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
- cache_storage_observer_.release());
- }
+ cache_storage_observer_.reset();
if (indexed_db_observer_) {
scoped_refptr<base::SequencedTaskRunner> observer_task_runner =
indexed_db_observer_->TaskRunner();
@@ -349,11 +336,7 @@ Response StorageHandler::TrackCacheStorageForOrigin(const std::string& origin) {
if (!origin_url.is_valid())
return Response::InvalidParams(origin + " is not a valid URL");
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&CacheStorageObserver::TrackOriginOnIOThread,
- base::Unretained(GetCacheStorageObserver()),
- url::Origin::Create(origin_url)));
+ GetCacheStorageObserver()->TrackOrigin(url::Origin::Create(origin_url));
return Response::OK();
}
@@ -366,11 +349,7 @@ Response StorageHandler::UntrackCacheStorageForOrigin(
if (!origin_url.is_valid())
return Response::InvalidParams(origin + " is not a valid URL");
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&CacheStorageObserver::UntrackOriginOnIOThread,
- base::Unretained(GetCacheStorageObserver()),
- url::Origin::Create(origin_url)));
+ GetCacheStorageObserver()->UntrackOrigin(url::Origin::Create(origin_url));
return Response::OK();
}
diff --git a/chromium/content/browser/devtools/protocol/system_info_handler.cc b/chromium/content/browser/devtools/protocol/system_info_handler.cc
index bdd75624aec..66730f3ec5a 100644
--- a/chromium/content/browser/devtools/protocol/system_info_handler.cc
+++ b/chromium/content/browser/devtools/protocol/system_info_handler.cc
@@ -94,10 +94,6 @@ class AuxGPUInfoEnumerator : public gpu::GPUInfo::Enumerator {
void EndImageDecodeAcceleratorSupportedProfile() override {}
- void BeginOverlayCapability() override {}
-
- void EndOverlayCapability() override {}
-
void BeginDx12VulkanVersionInfo() override {}
void EndDx12VulkanVersionInfo() override {}
@@ -121,6 +117,8 @@ std::unique_ptr<GPUDevice> GPUDeviceToProtocol(
.SetDeviceId(device.device_id)
.SetVendorString(device.vendor_string)
.SetDeviceString(device.device_string)
+ .SetDriverVendor(device.driver_vendor)
+ .SetDriverVersion(device.driver_version)
.Build();
}
diff --git a/chromium/content/browser/devtools/protocol/target_auto_attacher.cc b/chromium/content/browser/devtools/protocol/target_auto_attacher.cc
index 30a258059ef..97a14a18a0b 100644
--- a/chromium/content/browser/devtools/protocol/target_auto_attacher.cc
+++ b/chromium/content/browser/devtools/protocol/target_auto_attacher.cc
@@ -13,6 +13,7 @@
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/navigation_request.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
namespace content {
namespace protocol {
@@ -135,9 +136,34 @@ void TargetAutoAttacher::SetRenderFrameHost(
RenderFrameHostImpl* render_frame_host) {
render_frame_host_ = render_frame_host;
UpdateFrames();
+ UpdatePortals();
ReattachServiceWorkers(false);
}
+void TargetAutoAttacher::UpdatePortals() {
+ if (!auto_attach_)
+ return;
+
+ Hosts new_hosts;
+ if (render_frame_host_ &&
+ render_frame_host_->frame_tree_node()->IsMainFrame()) {
+ WebContentsImpl* outer_web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromRenderFrameHost(render_frame_host_));
+ for (WebContents* web_contents :
+ outer_web_contents->GetInnerWebContents()) {
+ WebContentsImpl* web_contents_impl =
+ static_cast<WebContentsImpl*>(web_contents);
+ scoped_refptr<DevToolsAgentHost> new_host =
+ RenderFrameDevToolsAgentHost::GetOrCreateFor(
+ web_contents_impl->GetFrameTree()->root());
+ new_hosts.insert(new_host);
+ }
+ }
+
+ // TODO(dgozman): support wait_for_debugger_on_start_.
+ ReattachTargetsOfType(new_hosts, DevToolsAgentHost::kTypePage, false);
+}
+
void TargetAutoAttacher::UpdateServiceWorkers() {
ReattachServiceWorkers(false);
}
@@ -185,11 +211,23 @@ DevToolsAgentHost* TargetAutoAttacher::AutoAttachToFrame(
FrameTreeNode* frame_tree_node = navigation_handle->frame_tree_node();
RenderFrameHostImpl* new_host = navigation_handle->GetRenderFrameHost();
+
+ // |new_host| can be nullptr for navigation that doesn't commmit
+ // (e.g. download). Skip possibly detaching the old agent host so the DevTools
+ // message logged via the old RFH can be seen.
+ if (!new_host)
+ return nullptr;
+
scoped_refptr<DevToolsAgentHost> agent_host =
RenderFrameDevToolsAgentHost::FindForDangling(frame_tree_node);
bool old_cross_process = !!agent_host;
- bool new_cross_process = new_host && new_host->IsCrossProcessSubframe();
+ bool is_portal_main_frame =
+ frame_tree_node->IsMainFrame() &&
+ static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(new_host))
+ ->IsPortal();
+ bool new_cross_process =
+ new_host->IsCrossProcessSubframe() || is_portal_main_frame;
if (old_cross_process == new_cross_process)
return nullptr;
@@ -262,10 +300,12 @@ void TargetAutoAttacher::SetAutoAttach(bool auto_attach,
ReattachServiceWorkers(false);
}
UpdateFrames();
+ UpdatePortals();
} else if (!auto_attach && auto_attach_) {
auto_attach_ = false;
Hosts empty;
ReattachTargetsOfType(empty, DevToolsAgentHost::kTypeFrame, false);
+ ReattachTargetsOfType(empty, DevToolsAgentHost::kTypePage, false);
if (auto_attaching_service_workers_) {
ServiceWorkerDevToolsManager::GetInstance()->RemoveObserver(this);
ReattachTargetsOfType(empty, DevToolsAgentHost::kTypeServiceWorker,
diff --git a/chromium/content/browser/devtools/protocol/target_auto_attacher.h b/chromium/content/browser/devtools/protocol/target_auto_attacher.h
index 4e49d3d9a9f..e958bc0bc64 100644
--- a/chromium/content/browser/devtools/protocol/target_auto_attacher.h
+++ b/chromium/content/browser/devtools/protocol/target_auto_attacher.h
@@ -35,6 +35,7 @@ class TargetAutoAttacher : public ServiceWorkerDevToolsManager::Observer {
bool wait_for_debugger_on_start,
base::OnceClosure callback);
+ void UpdatePortals();
void UpdateServiceWorkers();
void AgentHostClosed(DevToolsAgentHost* host);
diff --git a/chromium/content/browser/devtools/protocol/target_handler.cc b/chromium/content/browser/devtools/protocol/target_handler.cc
index 275ffb4c5b8..6295cd70f91 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.cc
+++ b/chromium/content/browser/devtools/protocol/target_handler.cc
@@ -335,7 +335,7 @@ class TargetHandler::Session : public DevToolsAgentHostClient {
bool UsesBinaryProtocol() override {
if (flatten_protocol_)
- return handler_->root_session_->UsesBinaryProtocol();
+ return true;
auto* client = handler_->root_session_->client();
return client->UsesBinaryProtocol();
}
@@ -492,6 +492,10 @@ std::unique_ptr<NavigationThrottle> TargetHandler::CreateThrottleForNavigation(
navigation_handle);
}
+void TargetHandler::UpdatePortals() {
+ auto_attacher_.UpdatePortals();
+}
+
void TargetHandler::ClearThrottles() {
base::flat_set<Throttle*> copy(throttles_);
for (Throttle* throttle : copy)
@@ -706,6 +710,8 @@ Response TargetHandler::CreateTarget(const std::string& url,
Maybe<int> height,
Maybe<std::string> context_id,
Maybe<bool> enable_begin_frame_control,
+ Maybe<bool> new_window,
+ Maybe<bool> background,
std::string* out_target_id) {
if (access_mode_ == AccessMode::kAutoAttachOnly)
return Response::Error(kNotAllowedError);
diff --git a/chromium/content/browser/devtools/protocol/target_handler.h b/chromium/content/browser/devtools/protocol/target_handler.h
index 514a59f6ca5..3be9739e7e8 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.h
+++ b/chromium/content/browser/devtools/protocol/target_handler.h
@@ -56,6 +56,7 @@ class TargetHandler : public DevToolsDomainHandler,
void DidFinishNavigation();
std::unique_ptr<NavigationThrottle> CreateThrottleForNavigation(
NavigationHandle* navigation_handle);
+ void UpdatePortals();
// Domain implementation.
Response SetDiscoverTargets(bool discover) override;
@@ -93,6 +94,8 @@ class TargetHandler : public DevToolsDomainHandler,
Maybe<int> height,
Maybe<std::string> context_id,
Maybe<bool> enable_begin_frame_control,
+ Maybe<bool> new_window,
+ Maybe<bool> background,
std::string* out_target_id) override;
Response GetTargets(
std::unique_ptr<protocol::Array<Target::TargetInfo>>* target_infos)
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.cc b/chromium/content/browser/devtools/protocol/tracing_handler.cc
index 326069bfb7d..25bc114a44b 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.cc
@@ -29,6 +29,7 @@
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/devtools_frame_trace_recorder.h"
#include "content/browser/devtools/devtools_io_context.h"
+#include "content/browser/devtools/devtools_protocol_encoding.h"
#include "content/browser/devtools/devtools_stream_file.h"
#include "content/browser/devtools/devtools_traceable_screenshot.h"
#include "content/browser/devtools/devtools_video_consumer.h"
@@ -46,6 +47,7 @@
#include "services/tracing/public/cpp/tracing_features.h"
#include "services/tracing/public/mojom/constants.mojom.h"
#include "services/tracing/public/mojom/perfetto_service.mojom.h"
+#include "third_party/inspector_protocol/encoding/encoding.h"
#ifdef OS_ANDROID
#include "content/browser/renderer_host/compositor_impl_android.h"
@@ -240,6 +242,7 @@ class TracingHandler::TracingSession {
base::OnceCallback<void(float percent_full,
size_t approximate_event_count)>
on_buffer_usage_callback) = 0;
+ virtual bool HasTracingFailed() = 0;
private:
DISALLOW_COPY_AND_ASSIGN(TracingSession);
@@ -280,41 +283,47 @@ class TracingHandler::LegacyTracingSession
TracingController::GetInstance()->GetTraceBufferUsage(
std::move(on_buffer_usage_callback));
}
+
+ bool HasTracingFailed() override { return false; }
};
class TracingHandler::PerfettoTracingSession
: public TracingHandler::TracingSession,
- public tracing::mojom::TracingSession,
+ public tracing::mojom::TracingSessionClient,
public mojo::DataPipeDrainer::Client {
public:
~PerfettoTracingSession() override {
-#if DCHECK_IS_ON()
DCHECK(!tracing_active_);
-#endif
}
// TracingHandler::TracingSession implementation:
void EnableTracing(const base::trace_event::TraceConfig& chrome_config,
base::OnceClosure on_recording_enabled_callback) override {
-#if DCHECK_IS_ON()
+ DCHECK(!tracing_session_host_);
DCHECK(!tracing_active_);
tracing_active_ = true;
-#endif
+
ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
tracing::mojom::kServiceName, &consumer_host_);
perfetto::TraceConfig perfetto_config =
CreatePerfettoConfiguration(chrome_config);
- tracing::mojom::TracingSessionPtr tracing_session;
- binding_.Bind(mojo::MakeRequest(&tracing_session));
+ tracing::mojom::TracingSessionClientPtr tracing_session_client;
+ binding_.Bind(mojo::MakeRequest(&tracing_session_client));
binding_.set_connection_error_handler(
- base::BindOnce(&PerfettoTracingSession::OnTracingSessionEnded,
+ base::BindOnce(&PerfettoTracingSession::OnTracingSessionFailed,
base::Unretained(this)));
on_recording_enabled_callback_ = std::move(on_recording_enabled_callback);
- consumer_host_->EnableTracing(std::move(tracing_session),
- std::move(perfetto_config));
+ consumer_host_->EnableTracing(
+ mojo::MakeRequest(&tracing_session_host_),
+ std::move(tracing_session_client), std::move(perfetto_config),
+ tracing::mojom::TracingClientPriority::kUserInitiated);
+
+ tracing_session_host_.set_connection_error_handler(
+ base::BindOnce(&PerfettoTracingSession::OnTracingSessionFailed,
+ base::Unretained(this)));
}
void AdoptStartupTracingSession() override {
@@ -330,7 +339,7 @@ class TracingHandler::PerfettoTracingSession
void ChangeTraceConfig(
const base::trace_event::TraceConfig& chrome_config) override {
auto perfetto_config = CreatePerfettoConfiguration(chrome_config);
- consumer_host_->ChangeTraceConfig(perfetto_config);
+ tracing_session_host_->ChangeTraceConfig(perfetto_config);
}
void DisableTracing(bool use_proto_format,
@@ -346,22 +355,36 @@ class TracingHandler::PerfettoTracingSession
use_proto_format_ = use_proto_format;
agent_label_ = agent_label;
endpoint_ = endpoint;
-#if DCHECK_IS_ON()
tracing_active_ = false;
-#endif
+
+ if (!tracing_session_host_) {
+ if (endpoint_)
+ endpoint_->ReceiveTraceFinalContents(nullptr);
+
+ return;
+ }
if (!use_proto_format_) {
- mojo::DataPipe data_pipe;
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+
+ MojoResult result =
+ mojo::CreateDataPipe(nullptr, &producer_handle, &consumer_handle);
+ if (result != MOJO_RESULT_OK) {
+ OnTracingSessionFailed();
+ return;
+ }
+
drainer_ = std::make_unique<mojo::DataPipeDrainer>(
- this, std::move(data_pipe.consumer_handle));
- consumer_host_->DisableTracingAndEmitJson(
- agent_label_, std::move(data_pipe.producer_handle),
+ this, std::move(consumer_handle));
+ tracing_session_host_->DisableTracingAndEmitJson(
+ agent_label_, std::move(producer_handle),
base::BindOnce(&PerfettoTracingSession::OnReadBuffersComplete,
base::Unretained(this)));
} else {
- // The host will close the TracingSession connection, calling
- // OnTracingSessionEnded(), once tracing was disabled.
- consumer_host_->DisableTracing();
+ // The host will call OnTracingDisabled once Perfetto has disabled
+ // tracing, at which point we'll pass down the datapipe.
+ tracing_session_host_->DisableTracing();
}
}
@@ -369,7 +392,7 @@ class TracingHandler::PerfettoTracingSession
size_t approximate_event_count)>
on_buffer_usage_callback) override {
DCHECK(on_buffer_usage_callback);
- consumer_host_->RequestBufferUsage(base::BindOnce(
+ tracing_session_host_->RequestBufferUsage(base::BindOnce(
&PerfettoTracingSession::OnBufferUsage, base::Unretained(this),
std::move(on_buffer_usage_callback)));
}
@@ -386,13 +409,42 @@ class TracingHandler::PerfettoTracingSession
std::move(on_buffer_usage_callback).Run(percent_full, 0);
}
- // tracing::mojom::TracingSession implementation:
+ bool HasTracingFailed() override {
+ return tracing_active_ && !tracing_session_host_;
+ }
+
+ // tracing::mojom::TracingSessionClient implementation:
void OnTracingEnabled() override {
if (on_recording_enabled_callback_) {
std::move(on_recording_enabled_callback_).Run();
}
}
+ void OnTracingDisabled() override {
+ // If we're converting to JSON, we will receive the data via
+ // ConsumerHost::DisableTracingAndEmitJson().
+ if (!use_proto_format_)
+ return;
+
+ DCHECK(agent_label_.empty());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+
+ MojoResult result =
+ mojo::CreateDataPipe(nullptr, &producer_handle, &consumer_handle);
+ if (result != MOJO_RESULT_OK) {
+ OnTracingSessionFailed();
+ return;
+ }
+
+ drainer_ = std::make_unique<mojo::DataPipeDrainer>(
+ this, std::move(consumer_handle));
+ tracing_session_host_->ReadBuffers(
+ std::move(producer_handle),
+ base::BindOnce(&PerfettoTracingSession::OnReadBuffersComplete,
+ base::Unretained(this)));
+ }
+
private:
perfetto::TraceConfig CreatePerfettoConfiguration(
const base::trace_event::TraceConfig& chrome_config) {
@@ -419,20 +471,21 @@ class TracingHandler::PerfettoTracingSession
std::move(pending_disable_tracing_task_).Run();
}
- void OnTracingSessionEnded() {
- // If we're converting to JSON, we will receive the data via
- // ConsumerHost::DisableTracingAndEmitJson().
- if (!use_proto_format_)
- return;
+ void OnTracingSessionFailed() {
+ tracing_session_host_.reset();
+ binding_.Close();
+ drainer_.reset();
- DCHECK(agent_label_.empty());
- mojo::DataPipe data_pipe;
- drainer_ = std::make_unique<mojo::DataPipeDrainer>(
- this, std::move(data_pipe.consumer_handle));
- consumer_host_->ReadBuffers(
- std::move(data_pipe.producer_handle),
- base::BindOnce(&PerfettoTracingSession::OnReadBuffersComplete,
- base::Unretained(this)));
+ if (on_recording_enabled_callback_)
+ std::move(on_recording_enabled_callback_).Run();
+
+ if (pending_disable_tracing_task_)
+ std::move(pending_disable_tracing_task_).Run();
+
+ if (endpoint_) {
+ // TODO(oysteine): Signal to the client that tracing failed.
+ endpoint_->ReceiveTraceFinalContents(nullptr);
+ }
}
// mojo::DataPipeDrainer::Client implementation:
@@ -453,11 +506,14 @@ class TracingHandler::PerfettoTracingSession
}
void MaybeTraceComplete() {
- if (read_buffers_complete_ && data_complete_)
+ if (read_buffers_complete_ && data_complete_ && endpoint_) {
endpoint_->ReceiveTraceFinalContents(nullptr);
+ }
}
- mojo::Binding<tracing::mojom::TracingSession> binding_{this};
+ mojo::Binding<tracing::mojom::TracingSessionClient> binding_{this};
+ tracing::mojom::TracingSessionHostPtr tracing_session_host_;
+
tracing::mojom::ConsumerHostPtr consumer_host_;
bool use_proto_format_;
@@ -469,18 +525,16 @@ class TracingHandler::PerfettoTracingSession
std::unique_ptr<mojo::DataPipeDrainer> drainer_;
bool data_complete_ = false;
bool read_buffers_complete_ = false;
+ bool tracing_active_ = false;
#if DCHECK_IS_ON()
- bool tracing_active_ = false;
base::trace_event::TraceConfig last_config_for_perfetto_;
#endif
};
TracingHandler::TracingHandler(FrameTreeNode* frame_tree_node_,
- DevToolsIOContext* io_context,
- bool use_binary_protocol)
+ DevToolsIOContext* io_context)
: DevToolsDomainHandler(Tracing::Metainfo::domainName),
- use_binary_protocol_(use_binary_protocol),
io_context_(io_context),
frame_tree_node_(frame_tree_node_),
did_initiate_recording_(false),
@@ -559,12 +613,11 @@ void TracingHandler::OnTraceDataCollected(
message.append(valid_trace_fragment.c_str() +
trace_data_buffer_state_.offset);
message += "] } }";
- if (use_binary_protocol_) {
- auto parsed = protocol::StringUtil::parseMessage(message, false);
- frontend_->sendRawNotification(parsed->serializeToBinary());
- } else {
- frontend_->sendRawNotification(std::move(message));
- }
+ std::vector<uint8_t> cbor;
+ ::inspector_protocol_encoding::Status status = ConvertJSONToCBOR(
+ ::inspector_protocol_encoding::SpanFrom(message), &cbor);
+ LOG_IF(ERROR, !status.ok()) << status.ToASCIIString();
+ frontend_->sendRawCBORNotification(std::move(cbor));
}
void TracingHandler::OnTraceComplete() {
@@ -720,7 +773,7 @@ void TracingHandler::Start(Maybe<std::string> categories,
base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE, {BrowserThread::IO}, base::BindOnce([]() {
GpuProcessHost* gpu_process_host =
- GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED,
/* force_create */ false);
return gpu_process_host ? gpu_process_host->process_id()
: base::kNullProcessId;
@@ -817,6 +870,9 @@ Response TracingHandler::End() {
if (!session_)
return Response::Error("Tracing is not started");
+ if (session_->HasTracingFailed())
+ return Response::Error("Tracing failed");
+
scoped_refptr<TracingController::TraceDataEndpoint> endpoint;
if (return_as_stream_) {
endpoint = new DevToolsStreamEndpoint(
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.h b/chromium/content/browser/devtools/protocol/tracing_handler.h
index 2584945cf6f..49836ca7be5 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.h
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.h
@@ -46,8 +46,7 @@ namespace protocol {
class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend {
public:
CONTENT_EXPORT TracingHandler(FrameTreeNode* frame_tree_node,
- DevToolsIOContext* io_context,
- bool use_binary_protocol);
+ DevToolsIOContext* io_context);
CONTENT_EXPORT ~TracingHandler() override;
static std::vector<TracingHandler*> ForAgentHost(DevToolsAgentHostImpl* host);
@@ -130,7 +129,6 @@ class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend {
std::unordered_set<base::ProcessId>* process_set);
void OnProcessReady(RenderProcessHost*);
- const bool use_binary_protocol_;
std::unique_ptr<base::RepeatingTimer> buffer_usage_poll_timer_;
std::unique_ptr<Tracing::Frontend> frontend_;
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc b/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
index a8e3dba4dcc..1dde2ea9479 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
+++ b/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
@@ -72,7 +72,7 @@ const char kCustomTraceConfigStringDevToolsStyle[] =
class TracingHandlerTest : public testing::Test {
public:
void SetUp() override {
- tracing_handler_.reset(new TracingHandler(nullptr, nullptr, false));
+ tracing_handler_.reset(new TracingHandler(nullptr, nullptr));
}
void TearDown() override { tracing_handler_.reset(); }
diff --git a/chromium/content/browser/devtools/protocol/webauthn_handler.cc b/chromium/content/browser/devtools/protocol/webauthn_handler.cc
new file mode 100644
index 00000000000..0895ce10c24
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/webauthn_handler.cc
@@ -0,0 +1,40 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/protocol/webauthn_handler.h"
+
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/webauth/authenticator_environment_impl.h"
+
+namespace content {
+namespace protocol {
+
+WebAuthnHandler::WebAuthnHandler()
+ : DevToolsDomainHandler(WebAuthn::Metainfo::domainName) {}
+
+WebAuthnHandler::~WebAuthnHandler() = default;
+
+void WebAuthnHandler::SetRenderer(int process_host_id,
+ RenderFrameHostImpl* frame_host) {
+ frame_host_ = frame_host;
+}
+
+void WebAuthnHandler::Wire(UberDispatcher* dispatcher) {
+ WebAuthn::Dispatcher::wire(dispatcher, this);
+}
+
+Response WebAuthnHandler::Enable() {
+ AuthenticatorEnvironmentImpl::GetInstance()->EnableVirtualAuthenticatorFor(
+ frame_host_);
+ return Response::OK();
+}
+
+Response WebAuthnHandler::Disable() {
+ AuthenticatorEnvironmentImpl::GetInstance()->DisableVirtualAuthenticatorFor(
+ frame_host_);
+ return Response::OK();
+}
+
+} // namespace protocol
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/webauthn_handler.h b/chromium/content/browser/devtools/protocol/webauthn_handler.h
new file mode 100644
index 00000000000..a6b75052522
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/webauthn_handler.h
@@ -0,0 +1,37 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_WEBAUTHN_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_WEBAUTHN_HANDLER_H_
+
+#include "base/macros.h"
+#include "content/browser/devtools/protocol/devtools_domain_handler.h"
+#include "content/browser/devtools/protocol/web_authn.h"
+
+namespace content {
+namespace protocol {
+
+class WebAuthnHandler : public DevToolsDomainHandler, public WebAuthn::Backend {
+ public:
+ WebAuthnHandler();
+ ~WebAuthnHandler() override;
+
+ // DevToolsDomainHandler:
+ void SetRenderer(int process_host_id,
+ RenderFrameHostImpl* frame_host) override;
+ void Wire(UberDispatcher* dispatcher) override;
+
+ // WebAuthn::Backend
+ Response Enable() override;
+ Response Disable() override;
+
+ private:
+ RenderFrameHostImpl* frame_host_;
+ DISALLOW_COPY_AND_ASSIGN(WebAuthnHandler);
+};
+
+} // namespace protocol
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_WEBAUTHN_HANDLER_H_
diff --git a/chromium/content/browser/devtools/protocol_config.json b/chromium/content/browser/devtools/protocol_config.json
index 3e9a57148aa..252a0fab2db 100644
--- a/chromium/content/browser/devtools/protocol_config.json
+++ b/chromium/content/browser/devtools/protocol_config.json
@@ -58,7 +58,7 @@
"include": ["enable", "disable", "reload", "navigate", "stopLoading", "getNavigationHistory", "navigateToHistoryEntry", "resetNavigationHistory", "captureScreenshot",
"startScreencast", "stopScreencast", "screencastFrameAck", "handleJavaScriptDialog", "setColorPickerEnabled",
"printToPDF", "bringToFront", "setDownloadBehavior", "getAppManifest", "crash", "close", "setWebLifecycleState", "captureSnapshot", "getInstallabilityErrors"],
- "include_events": ["colorPicked", "interstitialShown", "interstitialHidden", "javascriptDialogOpening", "javascriptDialogClosed", "screencastVisibilityChanged", "screencastFrame"],
+ "include_events": ["colorPicked", "interstitialShown", "interstitialHidden", "javascriptDialogOpening", "javascriptDialogClosed", "downloadWillBegin", "screencastVisibilityChanged", "screencastFrame"],
"async": ["captureScreenshot", "printToPDF", "navigate", "getAppManifest", "reload", "captureSnapshot", "getInstallabilityErrors"]
},
{
@@ -99,6 +99,10 @@
{
"domain": "Fetch",
"async": ["enable", "continueRequest", "failRequest", "fulfillRequest", "continueWithAuth", "getResponseBody", "takeResponseBodyAsStream"]
+ },
+ {
+ "domain": "WebAuthn",
+ "include": ["enable", "disable"]
}
]
},
@@ -109,5 +113,10 @@
"string_header": "content/browser/devtools/protocol/base_string_adapter.h",
"export_macro": "CONTENT_EXPORT",
"export_header": "content/common/content_export.h"
+ },
+
+ "encoding_lib": {
+ "header": "third_party/inspector_protocol/encoding/encoding.h",
+ "namespace": ["inspector_protocol_encoding"]
}
}
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 365778461c5..2166aad81b9 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -65,6 +65,8 @@
#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"
+#else
+#include "content/browser/devtools/protocol/webauthn_handler.h"
#endif
namespace content {
@@ -321,8 +323,11 @@ bool RenderFrameDevToolsAgentHost::AttachSession(DevToolsSession* session) {
session->AddHandler(std::make_unique<protocol::SecurityHandler>());
if (!frame_tree_node_ || !frame_tree_node_->parent()) {
session->AddHandler(std::make_unique<protocol::TracingHandler>(
- frame_tree_node_, GetIOContext(), session->UsesBinaryProtocol()));
+ frame_tree_node_, GetIOContext()));
}
+#if !defined(OS_ANDROID)
+ session->AddHandler(std::make_unique<protocol::WebAuthnHandler>());
+#endif // !defined(OS_ANDROID)
if (sessions().empty()) {
bool use_video_capture_api = true;
@@ -631,6 +636,10 @@ std::string RenderFrameDevToolsAgentHost::GetOpenerId() {
std::string RenderFrameDevToolsAgentHost::GetType() {
if (web_contents() &&
+ static_cast<WebContentsImpl*>(web_contents())->IsPortal()) {
+ return kTypePage;
+ }
+ if (web_contents() &&
static_cast<WebContentsImpl*>(web_contents())->GetOuterWebContents()) {
return kTypeGuest;
}
@@ -717,7 +726,7 @@ base::TimeTicks RenderFrameDevToolsAgentHost::GetLastActivityTime() {
void RenderFrameDevToolsAgentHost::SignalSynchronousSwapCompositorFrame(
RenderFrameHost* frame_host,
- viz::CompositorFrameMetadata frame_metadata) {
+ const DevToolsFrameMetadata& frame_metadata) {
scoped_refptr<RenderFrameDevToolsAgentHost> dtah(FindAgentHost(
static_cast<RenderFrameHostImpl*>(frame_host)->frame_tree_node()));
if (dtah) {
@@ -726,14 +735,14 @@ void RenderFrameDevToolsAgentHost::SignalSynchronousSwapCompositorFrame(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame,
- dtah.get(), std::move(frame_metadata)));
+ dtah.get(), frame_metadata));
}
}
void RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame(
- viz::CompositorFrameMetadata frame_metadata) {
+ const DevToolsFrameMetadata& frame_metadata) {
for (auto* page : protocol::PageHandler::ForAgentHost(this))
- page->OnSynchronousSwapCompositorFrame(frame_metadata.Clone());
+ page->OnSynchronousSwapCompositorFrame(frame_metadata);
if (!frame_trace_recorder_)
return;
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 81bb442136f..3f780494fec 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -27,10 +27,6 @@
#include "ui/android/view_android.h"
#endif // OS_ANDROID
-namespace viz {
-class CompositorFrameMetadata;
-}
-
namespace content {
class BrowserContext;
@@ -38,6 +34,7 @@ class DevToolsFrameTraceRecorder;
class FrameTreeNode;
class NavigationHandleImpl;
class RenderFrameHostImpl;
+struct DevToolsFrameMetadata;
class CONTENT_EXPORT RenderFrameDevToolsAgentHost
: public DevToolsAgentHostImpl,
@@ -64,8 +61,7 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
static void SignalSynchronousSwapCompositorFrame(
RenderFrameHost* frame_host,
- viz::CompositorFrameMetadata frame_metadata);
-
+ const DevToolsFrameMetadata& frame_metadata);
FrameTreeNode* frame_tree_node() { return frame_tree_node_; }
// DevToolsAgentHost overrides.
@@ -119,7 +115,6 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
bool IsChildFrame();
- void OnSwapCompositorFrame(const IPC::Message& message);
void DestroyOnRenderFrameGone();
void UpdateFrameHost(RenderFrameHostImpl* frame_host);
void SetFrameTreeNode(FrameTreeNode* frame_tree_node);
@@ -131,7 +126,7 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
#endif
void SynchronousSwapCompositorFrame(
- viz::CompositorFrameMetadata frame_metadata);
+ const DevToolsFrameMetadata& frame_metadata);
void UpdateResourceLoaderFactories();
std::unique_ptr<DevToolsFrameTraceRecorder> frame_trace_recorder_;
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 fee17f17393..762dadbe2be 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
@@ -37,7 +37,6 @@
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "services/file/public/mojom/constants.mojom.h"
#include "services/file/user_id_map.h"
-#include "services/service_manager/public/mojom/service_factory.mojom.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/env_chromium.h"
@@ -1037,8 +1036,7 @@ TEST_F(LocalStorageContextMojoTestWithService, CorruptionOnDisk) {
TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
FakeLevelDBService mock_leveldb_service;
- file_service()->GetBinderRegistryForTesting()->AddInterface(
- leveldb::mojom::LevelDBService::Name_,
+ file_service()->GetBinderMapForTesting().Add(
base::BindRepeating(&test::FakeLevelDBService::Bind,
base::Unretained(&mock_leveldb_service)));
@@ -1186,8 +1184,7 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
TEST_F(LocalStorageContextMojoTestWithService,
DontRecreateOnRepeatedCommitFailure) {
FakeLevelDBService mock_leveldb_service;
- file_service()->GetBinderRegistryForTesting()->AddInterface(
- leveldb::mojom::LevelDBService::Name_,
+ file_service()->GetBinderMapForTesting().Add(
base::BindRepeating(&test::FakeLevelDBService::Bind,
base::Unretained(&mock_leveldb_service)));
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 727afbba43a..711345b9230 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
@@ -632,8 +632,7 @@ TEST_F(SessionStorageContextMojoTest, RecreateOnCommitFailure) {
url::Origin origin3 = url::Origin::Create(GURL("http://example.com"));
test::FakeLevelDBService fake_leveldb_service;
- file_service()->GetBinderRegistryForTesting()->AddInterface(
- leveldb::mojom::LevelDBService::Name_,
+ file_service()->GetBinderMapForTesting().Add(
base::BindRepeating(&test::FakeLevelDBService::Bind,
base::Unretained(&fake_leveldb_service)));
@@ -768,8 +767,7 @@ TEST_F(SessionStorageContextMojoTest, DontRecreateOnRepeatedCommitFailure) {
url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
test::FakeLevelDBService fake_leveldb_service;
- file_service()->GetBinderRegistryForTesting()->AddInterface(
- leveldb::mojom::LevelDBService::Name_,
+ file_service()->GetBinderMapForTesting().Add(
base::BindRepeating(&test::FakeLevelDBService::Bind,
base::Unretained(&fake_leveldb_service)));
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 916ebe18f46..720da730833 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
@@ -88,7 +88,7 @@ SessionStorageNamespaceImpl::CloneFrom(
std::move(context), std::move(context_impl), std::move(namespace_id)));
}
-const std::string& SessionStorageNamespaceImpl::id() const {
+const std::string& SessionStorageNamespaceImpl::id() {
return namespace_id_;
}
@@ -96,7 +96,7 @@ void SessionStorageNamespaceImpl::SetShouldPersist(bool should_persist) {
should_persist_ = should_persist;
}
-bool SessionStorageNamespaceImpl::should_persist() const {
+bool SessionStorageNamespaceImpl::should_persist() {
return should_persist_;
}
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 7f3de289774..70cf707939a 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
@@ -52,9 +52,9 @@ class SessionStorageNamespaceImpl : public SessionStorageNamespace {
DOMStorageContextWrapper* context() const { return context_wrapper_.get(); }
// SessionStorageNamespace implementation.
- const std::string& id() const override;
+ const std::string& id() override;
void SetShouldPersist(bool should_persist) override;
- bool should_persist() const override;
+ bool should_persist() override;
bool IsMojoSessionStorage() { return context_.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 25a4a2f5c20..7c93f6c0ddd 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
@@ -131,8 +131,10 @@ void SessionStorageNamespaceImplMojo::RemoveOriginData(
}
DCHECK(IsPopulated());
auto it = origin_areas_.find(origin);
- if (it == origin_areas_.end())
+ if (it == origin_areas_.end()) {
+ std::move(callback).Run();
return;
+ }
// Renderer process expects |source| to always be two newline separated
// strings.
it->second->DeleteAll(
diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc
index 7be1ad12796..14c33ea03c4 100644
--- a/chromium/content/browser/download/download_browsertest.cc
+++ b/chromium/content/browser/download/download_browsertest.cc
@@ -11,7 +11,6 @@
#include <vector>
#include "base/bind.h"
-#include "base/callback_helpers.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
@@ -75,6 +74,7 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/web_mouse_event.h"
#include "url/gurl.h"
+#include "url/origin.h"
#if BUILDFLAG(ENABLE_PLUGINS)
#include "content/browser/plugin_service_impl.h"
@@ -522,8 +522,6 @@ class TestShellDownloadManagerDelegate : public ShellDownloadManagerDelegate {
return true;
}
- bool GenerateFileHash() override { return true; }
-
void SetDelayedOpen(bool delay) {
delay_download_open_ = delay;
}
@@ -563,7 +561,7 @@ class DownloadCreateObserver : DownloadManager::Observer {
item_ = download;
if (!completion_closure_.is_null())
- base::ResetAndReturn(&completion_closure_).Run();
+ std::move(completion_closure_).Run();
}
download::DownloadItem* WaitForFinished() {
@@ -597,7 +595,7 @@ class ErrorStreamCountingObserver : download::DownloadItem::Observer {
"Download.ParallelDownloadAddStreamSuccess");
if (samples->GetCount(0 /* failure */) == count_ &&
!completion_closure_.is_null())
- base::ResetAndReturn(&completion_closure_).Run();
+ std::move(completion_closure_).Run();
}
void OnDownloadDestroyed(download::DownloadItem* download) override {
@@ -905,6 +903,81 @@ class DownloadContentTest : public ContentBrowserTest {
return observer->WaitForFinished();
}
+ // Starts a download without strong validators, interrupts it, and resumes it.
+ // If |fail_content_validation| is true, download content will change during
+ // resumption.
+ void InterruptAndResumeDownloadWithoutStrongValidators(
+ bool fail_content_validation) {
+ int validation_length = 1024;
+ base::test::ScopedFeatureList scoped_feature_list;
+ std::map<std::string, std::string> params = {
+ {download::kDownloadContentValidationLengthFinchKey,
+ base::NumberToString(validation_length)}};
+ scoped_feature_list.InitAndEnableFeatureWithParameters(
+ download::features::kAllowDownloadResumptionWithoutStrongValidators,
+ params);
+ SetupErrorInjectionDownloads();
+ GURL url = TestDownloadHttpResponse::GetNextURLForDownload();
+ GURL server_url = embedded_test_server()->GetURL(url.host(), url.path());
+ TestDownloadHttpResponse::Parameters parameters =
+ TestDownloadHttpResponse::Parameters::WithSingleInterruption(
+ inject_error_callback());
+ parameters.etag.clear();
+ parameters.last_modified.clear();
+ TestDownloadHttpResponse::StartServing(parameters, server_url);
+
+ int64_t interruption_offset = parameters.injected_errors.front();
+ download::DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), server_url);
+ WaitForInterrupt(download);
+
+ ASSERT_EQ(interruption_offset, download->GetReceivedBytes());
+ ASSERT_EQ(parameters.size, download->GetTotalBytes());
+
+ parameters.ClearInjectedErrors();
+ if (fail_content_validation)
+ ++parameters.pattern_generator_seed;
+ TestDownloadHttpResponse::StartServing(parameters, server_url);
+
+ // Download should complete regardless whether content changes or not.
+ download->Resume(false);
+ WaitForCompletion(download);
+
+ ASSERT_EQ(parameters.size, download->GetReceivedBytes());
+ ASSERT_EQ(parameters.size, download->GetTotalBytes());
+ ASSERT_NO_FATAL_FAILURE(ReadAndVerifyFileContents(
+ parameters.pattern_generator_seed, parameters.size,
+ download->GetTargetFilePath()));
+
+ const TestDownloadResponseHandler::CompletedRequests& requests =
+ test_response_handler()->completed_requests();
+ ASSERT_EQ(fail_content_validation ? 3u : 2u, requests.size());
+
+ // The first request only transferrs bytes up until the interruption point.
+ EXPECT_EQ(interruption_offset, requests[0]->transferred_byte_count);
+
+ // The second request is a range request.
+ std::string value;
+ ASSERT_TRUE(requests[1]->http_request.headers.find(
+ net::HttpRequestHeaders::kIfRange) ==
+ requests[1]->http_request.headers.end());
+
+ ASSERT_TRUE(requests[1]->http_request.headers.find(
+ net::HttpRequestHeaders::kRange) !=
+ requests[1]->http_request.headers.end());
+ EXPECT_EQ(
+ base::StringPrintf("bytes=%" PRId64 "-",
+ interruption_offset - validation_length),
+ requests[1]->http_request.headers.at(net::HttpRequestHeaders::kRange));
+ if (fail_content_validation) {
+ // The third request is a restart request.
+ ASSERT_TRUE(requests[2]->http_request.headers.find(
+ net::HttpRequestHeaders::kRange) ==
+ requests[2]->http_request.headers.end());
+ EXPECT_EQ(parameters.size, requests[2]->transferred_byte_count);
+ }
+ }
+
TestDownloadResponseHandler* test_response_handler() {
return &test_response_handler_;
}
@@ -1014,7 +1087,7 @@ class ParallelDownloadTest : public DownloadContentTest {
download::DownloadItem* download =
DownloadManagerForShell(shell())->CreateDownloadItem(
"F7FB1F59-7DE1-4845-AFDB-8A688F70F583", 1, path, base::FilePath(),
- url_chain, GURL(), GURL(), GURL(), GURL(),
+ url_chain, GURL(), GURL(), GURL(), GURL(), url::Origin(),
"application/octet-stream", "application/octet-stream",
base::Time::Now(), base::Time(), parameters.etag,
parameters.last_modified, total_bytes, parameters.size,
@@ -1510,7 +1583,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) {
}
// Test resumption with a response that contains strong validators.
-IN_PROC_BROWSER_TEST_F(DownloadContentTest, StrongValidators) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithStrongValidators) {
SetupErrorInjectionDownloads();
GURL url = TestDownloadHttpResponse::GetNextURLForDownload();
GURL server_url = embedded_test_server()->GetURL(url.host(), url.path());
@@ -1571,6 +1644,18 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, StrongValidators) {
requests[1]->http_request.headers.at(net::HttpRequestHeaders::kRange));
}
+// Test resumption when strong validators are not present in the response.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithoutStrongValidators) {
+ InterruptAndResumeDownloadWithoutStrongValidators(false);
+}
+
+// Test resumption when strong validators are not present in the response and
+// the content of the download changes.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest,
+ ResumeWithoutStrongValidatorsAndFailValidation) {
+ InterruptAndResumeDownloadWithoutStrongValidators(true);
+}
+
// Resumption should only attempt to contact the final URL if the download has a
// URL chain.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, RedirectBeforeResume) {
@@ -2469,7 +2554,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_NoFile) {
DownloadManagerForShell(shell())->CreateDownloadItem(
"F7FB1F59-7DE1-4845-AFDB-8A688F70F583", 1, intermediate_file_path,
base::FilePath(), url_chain, GURL(), GURL(), GURL(), GURL(),
- "application/octet-stream", "application/octet-stream",
+ url::Origin(), "application/octet-stream", "application/octet-stream",
base::Time::Now(), base::Time(), parameters.etag, std::string(),
kIntermediateSize, parameters.size, std::string(),
download::DownloadItem::INTERRUPTED,
@@ -2536,7 +2621,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_NoHash) {
DownloadManagerForShell(shell())->CreateDownloadItem(
"F7FB1F59-7DE1-4845-AFDB-8A688F70F583", 1, intermediate_file_path,
base::FilePath(), url_chain, GURL(), GURL(), GURL(), GURL(),
- "application/octet-stream", "application/octet-stream",
+ url::Origin(), "application/octet-stream", "application/octet-stream",
base::Time::Now(), base::Time(), parameters.etag, std::string(),
kIntermediateSize, parameters.size, std::string(),
download::DownloadItem::INTERRUPTED,
@@ -2590,7 +2675,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
DownloadManagerForShell(shell())->CreateDownloadItem(
"F7FB1F59-7DE1-4845-AFDB-8A688F70F583", 1, intermediate_file_path,
base::FilePath(), url_chain, GURL(), GURL(), GURL(), GURL(),
- "application/octet-stream", "application/octet-stream",
+ url::Origin(), "application/octet-stream", "application/octet-stream",
base::Time::Now(), base::Time(), "fake-etag", std::string(),
kIntermediateSize, parameters.size, std::string(),
download::DownloadItem::INTERRUPTED,
@@ -2650,7 +2735,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
DownloadManagerForShell(shell())->CreateDownloadItem(
"F7FB1F59-7DE1-4845-AFDB-8A688F70F583", 1, intermediate_file_path,
base::FilePath(), url_chain, GURL(), GURL(), GURL(), GURL(),
- "application/octet-stream", "application/octet-stream",
+ url::Origin(), "application/octet-stream", "application/octet-stream",
base::Time::Now(), base::Time(), parameters.etag, std::string(),
kIntermediateSize, parameters.size,
std::string(std::begin(kPartialHash), std::end(kPartialHash)),
@@ -2717,7 +2802,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_WrongHash) {
DownloadManagerForShell(shell())->CreateDownloadItem(
"F7FB1F59-7DE1-4845-AFDB-8A688F70F583", 1, intermediate_file_path,
base::FilePath(), url_chain, GURL(), GURL(), GURL(), GURL(),
- "application/octet-stream", "application/octet-stream",
+ url::Origin(), "application/octet-stream", "application/octet-stream",
base::Time::Now(), base::Time(), parameters.etag, std::string(),
kIntermediateSize, parameters.size,
std::string(std::begin(kPartialHash), std::end(kPartialHash)),
@@ -2794,7 +2879,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_ShortFile) {
DownloadManagerForShell(shell())->CreateDownloadItem(
"F7FB1F59-7DE1-4845-AFDB-8A688F70F583", 1, intermediate_file_path,
base::FilePath(), url_chain, GURL(), GURL(), GURL(), GURL(),
- "application/octet-stream", "application/octet-stream",
+ url::Origin(), "application/octet-stream", "application/octet-stream",
base::Time::Now(), base::Time(), parameters.etag, std::string(),
kIntermediateSize, parameters.size, std::string(),
download::DownloadItem::INTERRUPTED,
@@ -2868,7 +2953,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_LongFile) {
DownloadManagerForShell(shell())->CreateDownloadItem(
"F7FB1F59-7DE1-4845-AFDB-8A688F70F583", 1, intermediate_file_path,
base::FilePath(), url_chain, GURL(), GURL(), GURL(), GURL(),
- "application/octet-stream", "application/octet-stream",
+ url::Origin(), "application/octet-stream", "application/octet-stream",
base::Time::Now(), base::Time(), parameters.etag, std::string(),
kIntermediateSize, parameters.size, std::string(),
download::DownloadItem::INTERRUPTED,
@@ -3800,7 +3885,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, FetchErrorResponseBodyResumption) {
// Verify WebUI download will success with an associated renderer process.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadFromWebUI) {
- GURL webui_url("chrome://resources/images/apps/blue_button.png");
+ GURL webui_url(GetWebUIURL("resources/images/apps/blue_button.png"));
NavigateToURL(shell(), webui_url);
SetupEnsureNoPendingDownloads();
diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc
index a87254980c4..236bfe85ff7 100644
--- a/chromium/content/browser/download/download_manager_impl.cc
+++ b/chromium/content/browser/download/download_manager_impl.cc
@@ -81,9 +81,9 @@
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
+#include "services/service_manager/public/cpp/connector.h"
#include "storage/browser/blob/blob_url_loader_factory.h"
#include "storage/browser/blob/blob_url_request_job_factory.h"
-#include "url/origin.h"
#if defined(USE_X11)
#include "base/nix/xdg_util.h"
@@ -219,6 +219,7 @@ class DownloadItemFactoryImpl : public download::DownloadItemFactory {
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_refererr_url,
+ const base::Optional<url::Origin>& request_initiator,
const std::string& mime_type,
const std::string& original_mime_type,
base::Time start_time,
@@ -244,10 +245,10 @@ class DownloadItemFactoryImpl : public download::DownloadItemFactory {
return new download::DownloadItemImpl(
delegate, guid, download_id, current_path, target_path, url_chain,
- referrer_url, site_url, tab_url, tab_refererr_url, mime_type,
- original_mime_type, start_time, end_time, etag, last_modified,
- received_bytes, total_bytes, auto_resume_count, hash, state,
- danger_type, interrupt_reason, false /* paused */,
+ referrer_url, site_url, tab_url, tab_refererr_url, request_initiator,
+ mime_type, original_mime_type, start_time, end_time, etag,
+ last_modified, received_bytes, total_bytes, auto_resume_count, hash,
+ state, danger_type, interrupt_reason, false /* paused */,
false /* allow_metered */, opened, last_access_time, transient,
received_slices);
}
@@ -361,16 +362,13 @@ DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context)
in_progress_manager_ =
std::make_unique<download::InProgressDownloadManager>(
this, base::FilePath(), base::BindRepeating(&IsOriginSecure),
- base::BindRepeating(&DownloadRequestUtils::IsURLSafe));
+ base::BindRepeating(&DownloadRequestUtils::IsURLSafe), nullptr);
} else {
- in_progress_manager_->set_delegate(this);
+ in_progress_manager_->SetDelegate(this);
in_progress_manager_->set_download_start_observer(nullptr);
in_progress_manager_->set_is_origin_secure_cb(
base::BindRepeating(&IsOriginSecure));
}
- in_progress_manager_->NotifyWhenInitialized(base::BindOnce(
- &DownloadManagerImpl::OnInProgressDownloadManagerInitialized,
- weak_factory_.GetWeakPtr()));
}
DownloadManagerImpl::~DownloadManagerImpl() {
@@ -494,7 +492,7 @@ void DownloadManagerImpl::SetDelegate(DownloadManagerDelegate* delegate) {
delegate_ = delegate;
}
-DownloadManagerDelegate* DownloadManagerImpl::GetDelegate() const {
+DownloadManagerDelegate* DownloadManagerImpl::GetDelegate() {
return delegate_;
}
@@ -566,15 +564,17 @@ bool DownloadManagerImpl::InterceptDownload(
}
}
- if (!delegate_ ||
- !delegate_->InterceptDownloadIfApplicable(
- info.url(), user_agent, info.content_disposition, info.mime_type,
- info.request_origin, info.total_bytes, web_contents)) {
- return false;
+ if (delegate_ && delegate_->InterceptDownloadIfApplicable(
+ info.url(), user_agent, info.content_disposition,
+ info.mime_type, info.request_origin, info.total_bytes,
+ info.transient, web_contents)) {
+ if (info.request_handle)
+ info.request_handle->CancelRequest(false);
+ return true;
}
- if (info.request_handle)
- info.request_handle->CancelRequest(false);
- return true;
+ content::devtools_instrumentation::WillBeginDownload(
+ info.render_process_id, info.render_frame_id, info.url());
+ return false;
}
base::FilePath DownloadManagerImpl::GetDefaultDownloadDirectory() {
@@ -603,7 +603,7 @@ base::FilePath DownloadManagerImpl::GetDefaultDownloadDirectory() {
return default_download_directory;
}
-void DownloadManagerImpl::OnInProgressDownloadManagerInitialized() {
+void DownloadManagerImpl::OnDownloadsInitialized() {
in_progress_downloads_ = in_progress_manager_->TakeInProgressDownloads();
uint32_t max_id = download::DownloadItem::kInvalidId;
for (auto it = in_progress_downloads_.begin();
@@ -678,6 +678,13 @@ net::URLRequestContextGetter* DownloadManagerImpl::GetURLRequestContextGetter(
: nullptr;
}
+service_manager::Connector* DownloadManagerImpl::GetServiceManagerConnector() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (auto* connection = ServiceManagerConnection::GetForProcess())
+ return connection->GetConnector();
+ return nullptr;
+}
+
void DownloadManagerImpl::StartDownload(
std::unique_ptr<download::DownloadCreateInfo> info,
std::unique_ptr<download::InputStream> stream,
@@ -735,7 +742,7 @@ std::string DownloadManagerImpl::GetApplicationClientIdForFileScanning() const {
return std::string();
}
-BrowserContext* DownloadManagerImpl::GetBrowserContext() const {
+BrowserContext* DownloadManagerImpl::GetBrowserContext() {
return browser_context_;
}
@@ -949,11 +956,15 @@ int DownloadManagerImpl::RemoveDownloadsByURLAndTime(
return count;
}
-bool DownloadManagerImpl::DownloadUrl(
+bool DownloadManagerImpl::CanDownload(
+ download::DownloadUrlParameters* parameters) {
+ return true;
+}
+
+void DownloadManagerImpl::DownloadUrl(
std::unique_ptr<download::DownloadUrlParameters> params) {
DownloadUrl(std::move(params), nullptr /* blob_data_handle */,
nullptr /* blob_url_loader_factory */);
- return true;
}
void DownloadManagerImpl::DownloadUrl(
@@ -996,6 +1007,7 @@ download::DownloadItem* DownloadManagerImpl::CreateDownloadItem(
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_refererr_url,
+ const base::Optional<url::Origin>& request_initiator,
const std::string& mime_type,
const std::string& original_mime_type,
base::Time start_time,
@@ -1031,10 +1043,10 @@ download::DownloadItem* DownloadManagerImpl::CreateDownloadItem(
#endif
auto item = base::WrapUnique(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,
- start_time, end_time, etag, last_modified, received_bytes, total_bytes,
- hash, state, danger_type, interrupt_reason, opened, last_access_time,
- transient, received_slices));
+ site_url, tab_url, tab_refererr_url, request_initiator, mime_type,
+ original_mime_type, start_time, end_time, etag, last_modified,
+ received_bytes, total_bytes, hash, state, danger_type, interrupt_reason,
+ opened, last_access_time, transient, received_slices));
if (in_progress_download) {
// If the download item from history db is already in terminal state,
// remove it from the in-progress db. Otherwise, use the in-progress db one.
@@ -1128,8 +1140,9 @@ void DownloadManagerImpl::PostInitialization(
}
void DownloadManagerImpl::ImportInProgressDownloads(uint32_t id) {
- for (auto& download : in_progress_downloads_) {
- auto item = std::move(download);
+ auto download = in_progress_downloads_.begin();
+ while (download != in_progress_downloads_.end()) {
+ auto item = std::move(*download);
// If the in-progress download doesn't have an ID, generate new IDs for it.
if (item->GetId() == download::DownloadItem::kInvalidId) {
item->SetDownloadId(id++);
@@ -1139,10 +1152,9 @@ void DownloadManagerImpl::ImportInProgressDownloads(uint32_t id) {
}
item->SetDelegate(this);
DownloadItemUtils::AttachInfo(item.get(), GetBrowserContext(), nullptr);
+ download = in_progress_downloads_.erase(download);
OnDownloadCreated(std::move(item));
}
- in_progress_downloads_.clear();
-
OnDownloadManagerInitialized();
}
@@ -1153,11 +1165,11 @@ void DownloadManagerImpl::OnDownloadManagerInitialized() {
observer.OnManagerInitialized();
}
-bool DownloadManagerImpl::IsManagerInitialized() const {
+bool DownloadManagerImpl::IsManagerInitialized() {
return initialized_;
}
-int DownloadManagerImpl::InProgressCount() const {
+int DownloadManagerImpl::InProgressCount() {
int count = 0;
for (const auto& it : downloads_) {
if (it.second->GetState() == download::DownloadItem::IN_PROGRESS)
@@ -1166,7 +1178,7 @@ int DownloadManagerImpl::InProgressCount() const {
return count;
}
-int DownloadManagerImpl::NonMaliciousInProgressCount() const {
+int DownloadManagerImpl::NonMaliciousInProgressCount() {
int count = 0;
for (const auto& it : downloads_) {
if (it.second->GetState() == download::DownloadItem::IN_PROGRESS &&
@@ -1192,6 +1204,12 @@ download::DownloadItem* DownloadManagerImpl::GetDownload(uint32_t download_id) {
download::DownloadItem* DownloadManagerImpl::GetDownloadByGuid(
const std::string& guid) {
+ if (!in_progress_downloads_.empty()) {
+ for (const auto& it : in_progress_downloads_) {
+ if (it->GetGuid() == guid)
+ return it.get();
+ }
+ }
return base::ContainsKey(downloads_by_guid_, guid) ? downloads_by_guid_[guid]
: nullptr;
}
@@ -1219,9 +1237,10 @@ void DownloadManagerImpl::OnUrlDownloadStopped(
void DownloadManagerImpl::GetAllDownloads(
download::SimpleDownloadManager::DownloadVector* downloads) {
- for (const auto& it : downloads_) {
+ for (const auto& it : downloads_)
downloads->push_back(it.second.get());
- }
+ for (const auto& it : in_progress_downloads_)
+ downloads->push_back(it.get());
}
void DownloadManagerImpl::OpenDownload(download::DownloadItemImpl* download) {
diff --git a/chromium/content/browser/download/download_manager_impl.h b/chromium/content/browser/download/download_manager_impl.h
index 25e6ab5e470..19639281a2c 100644
--- a/chromium/content/browser/download/download_manager_impl.h
+++ b/chromium/content/browser/download/download_manager_impl.h
@@ -18,6 +18,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
+#include "base/optional.h"
#include "base/sequenced_task_runner_helpers.h"
#include "base/synchronization/lock.h"
#include "build/build_config.h"
@@ -33,6 +34,7 @@
#include "content/public/browser/ssl_status.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/mojom/url_loader.mojom.h"
+#include "url/origin.h"
namespace download {
class DownloadFileFactory;
@@ -74,7 +76,7 @@ class CONTENT_EXPORT DownloadManagerImpl
// DownloadManager functions.
void SetDelegate(DownloadManagerDelegate* delegate) override;
- DownloadManagerDelegate* GetDelegate() const override;
+ DownloadManagerDelegate* GetDelegate() override;
void Shutdown() override;
void GetAllDownloads(
download::SimpleDownloadManager::DownloadVector* result) override;
@@ -84,12 +86,12 @@ class CONTENT_EXPORT DownloadManagerImpl
url_loader_factory_getter,
const download::DownloadUrlParameters::OnStartedCallback&
on_started) override;
-
int RemoveDownloadsByURLAndTime(
const base::Callback<bool(const GURL&)>& url_filter,
base::Time remove_begin,
base::Time remove_end) override;
- bool DownloadUrl(
+ bool CanDownload(download::DownloadUrlParameters* parameters) override;
+ void DownloadUrl(
std::unique_ptr<download::DownloadUrlParameters> parameters) override;
void DownloadUrl(std::unique_ptr<download::DownloadUrlParameters> params,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
@@ -107,6 +109,7 @@ class CONTENT_EXPORT DownloadManagerImpl
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_refererr_url,
+ const base::Optional<url::Origin>& request_initiator,
const std::string& mime_type,
const std::string& original_mime_type,
base::Time start_time,
@@ -125,10 +128,10 @@ class CONTENT_EXPORT DownloadManagerImpl
const std::vector<download::DownloadItem::ReceivedSlice>& received_slices)
override;
void PostInitialization(DownloadInitializationDependency dependency) override;
- bool IsManagerInitialized() const override;
- int InProgressCount() const override;
- int NonMaliciousInProgressCount() const override;
- BrowserContext* GetBrowserContext() const override;
+ bool IsManagerInitialized() override;
+ int InProgressCount() override;
+ int NonMaliciousInProgressCount() override;
+ BrowserContext* GetBrowserContext() override;
void CheckForHistoryFilesRemoval() override;
void OnHistoryQueryComplete(
base::OnceClosure load_history_downloads_cb) override;
@@ -197,6 +200,7 @@ class CONTENT_EXPORT DownloadManagerImpl
uint32_t id);
// InProgressDownloadManager::Delegate implementations.
+ void OnDownloadsInitialized() override;
bool InterceptDownload(const download::DownloadCreateInfo& info) override;
base::FilePath GetDefaultDownloadDirectory() override;
void StartDownloadItem(
@@ -207,9 +211,6 @@ class CONTENT_EXPORT DownloadManagerImpl
net::URLRequestContextGetter* GetURLRequestContextGetter(
const download::DownloadCreateInfo& info) override;
- // Called when InProgressDownloadManager is initialzed.
- void OnInProgressDownloadManagerInitialized();
-
// Creates a new download item and call |callback|.
void CreateNewDownloadItemToStart(
std::unique_ptr<download::DownloadCreateInfo> info,
@@ -259,6 +260,7 @@ class CONTENT_EXPORT DownloadManagerImpl
download::DownloadItemImpl* download) override;
bool IsOffTheRecord() const override;
void ReportBytesWasted(download::DownloadItemImpl* download) override;
+ service_manager::Connector* GetServiceManagerConnector() override;
// Drops a download before it is created.
void DropDownload();
diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc
index 7f9ee7201f6..78f18bccce9 100644
--- a/chromium/content/browser/download/download_manager_impl_unittest.cc
+++ b/chromium/content/browser/download/download_manager_impl_unittest.cc
@@ -19,6 +19,7 @@
#include "base/guid.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
@@ -135,6 +136,7 @@ class MockDownloadItemFactory
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_referrer_url,
+ const base::Optional<url::Origin>& request_initiator,
const std::string& mime_type,
const std::string& original_mime_type,
base::Time start_time,
@@ -214,6 +216,7 @@ download::DownloadItemImpl* MockDownloadItemFactory::CreatePersistedItem(
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_referrer_url,
+ const base::Optional<url::Origin>& request_initiator,
const std::string& mime_type,
const std::string& original_mime_type,
base::Time start_time,
@@ -380,7 +383,8 @@ TestInProgressManager::TestInProgressManager()
nullptr,
base::FilePath(),
download::InProgressDownloadManager::IsOriginSecureCallback(),
- base::BindRepeating(&URLAlwaysSafe)) {}
+ base::BindRepeating(&URLAlwaysSafe),
+ nullptr) {}
void TestInProgressManager::AddDownloadItem(
std::unique_ptr<download::DownloadItemImpl> item) {
@@ -523,7 +527,7 @@ class DownloadManagerTest : public testing::Test {
}
void OnInProgressDownloadManagerInitialized() {
- download_manager_->OnInProgressDownloadManagerInitialized();
+ download_manager_->OnDownloadsInitialized();
}
void OnHistoryDBInitialized() {
@@ -695,6 +699,7 @@ TEST_F(DownloadManagerTest, GetDownloadByGuid) {
kGuid, 10, base::FilePath(), base::FilePath(), url_chain,
GURL("http://example.com/a"), GURL("http://example.com/a"),
GURL("http://example.com/a"), GURL("http://example.com/a"),
+ url::Origin::Create(GURL("http://example.com/")),
"application/octet-stream", "application/octet-stream",
base::Time::Now(), base::Time::Now(), std::string(), std::string(),
10, 10, std::string(), download::DownloadItem::INTERRUPTED,
@@ -747,6 +752,7 @@ TEST_F(DownloadManagerTest, OnInProgressDownloadsLoaded) {
in_progress_manager.get(), kGuid, 10, base::FilePath(), base::FilePath(),
url_chain, GURL("http://example.com/a"), GURL("http://example.com/a"),
GURL("http://example.com/a"), GURL("http://example.com/a"),
+ url::Origin::Create(GURL("http://example.com")),
"application/octet-stream", "application/octet-stream", base::Time::Now(),
base::Time::Now(), std::string(), std::string(), 10, 10, 0, std::string(),
download::DownloadItem::INTERRUPTED,
@@ -759,7 +765,10 @@ TEST_F(DownloadManagerTest, OnInProgressDownloadsLoaded) {
EXPECT_CALL(GetMockObserver(), OnDownloadCreated(download_manager_.get(), _))
.WillOnce(Return());
OnInProgressDownloadManagerInitialized();
- ASSERT_FALSE(download_manager_->GetDownloadByGuid(kGuid));
+ ASSERT_TRUE(download_manager_->GetDownloadByGuid(kGuid));
+ std::vector<download::DownloadItem*> vector;
+ download_manager_->GetAllDownloads(&vector);
+ ASSERT_EQ(1u, vector.size());
EXPECT_CALL(GetMockDownloadManagerDelegate(), GetNextId(_))
.WillOnce(RunCallback<0>(1));
diff --git a/chromium/content/browser/download/download_request_core.cc b/chromium/content/browser/download/download_request_core.cc
index 0458f8db174..87b1ff430c1 100644
--- a/chromium/content/browser/download/download_request_core.cc
+++ b/chromium/content/browser/download/download_request_core.cc
@@ -5,9 +5,9 @@
#include "content/browser/download/download_request_core.h"
#include <string>
+#include <utility>
#include "base/bind.h"
-#include "base/callback_helpers.h"
#include "base/format_macros.h"
#include "base/location.h"
#include "base/logging.h"
@@ -266,9 +266,11 @@ bool DownloadRequestCore::OnResponseStarted(
std::unique_ptr<download::DownloadCreateInfo> create_info =
CreateDownloadCreateInfo(result);
if (result != download::DOWNLOAD_INTERRUPT_REASON_NONE) {
+ auto cb = std::move(on_started_callback_);
+ // TODO(https://crbug.com/957713): Use OnceCallback and eliminate the need
+ // for a callback on the stack.
delegate_->OnStart(std::move(create_info),
- std::unique_ptr<ByteStreamReader>(),
- base::ResetAndReturn(&on_started_callback_));
+ std::unique_ptr<ByteStreamReader>(), cb);
return false;
}
@@ -320,8 +322,10 @@ bool DownloadRequestCore::OnResponseStarted(
download::RecordDownloadSourcePageTransitionType(
create_info->transition_type);
- delegate_->OnStart(std::move(create_info), std::move(stream_reader),
- base::ResetAndReturn(&on_started_callback_));
+ auto cb = std::move(on_started_callback_);
+ // TODO(https://crbug.com/957713): Use OnceCallback and eliminate the need for
+ // a callback on the stack.
+ delegate_->OnStart(std::move(create_info), std::move(stream_reader), cb);
return true;
}
@@ -440,8 +444,10 @@ void DownloadRequestCore::OnResponseCompleted(
std::unique_ptr<download::DownloadCreateInfo> create_info =
CreateDownloadCreateInfo(reason);
std::unique_ptr<ByteStreamReader> empty_byte_stream;
- delegate_->OnStart(std::move(create_info), std::move(empty_byte_stream),
- base::ResetAndReturn(&on_started_callback_));
+ auto cb = std::move(on_started_callback_);
+ // TODO(https://crbug.com/957713): Use OnceCallback and eliminate the need for
+ // a callback on the stack.
+ delegate_->OnStart(std::move(create_info), std::move(empty_byte_stream), cb);
}
void DownloadRequestCore::PauseRequest() {
diff --git a/chromium/content/browser/download/mhtml_generation_browsertest.cc b/chromium/content/browser/download/mhtml_generation_browsertest.cc
index 97edcac6be3..0f107682fac 100644
--- a/chromium/content/browser/download/mhtml_generation_browsertest.cc
+++ b/chromium/content/browser/download/mhtml_generation_browsertest.cc
@@ -16,6 +16,7 @@
#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_restrictions.h"
+#include "build/build_config.h"
#include "components/download/public/common/download_task_runner.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/common/download/mhtml_file_writer.mojom.h"
@@ -456,7 +457,16 @@ IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest, GenerateMHTML) {
}
// Regression test for the crash/race from https://crbug.com/612098.
-IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest, GenerateMHTMLAndCloseConnection) {
+//
+// TODO(crbug.com/959435): Flaky on Android.
+#if defined(OS_ANDROID)
+#define MAYBE_GenerateMHTMLAndCloseConnection \
+ DISABLED_GenerateMHTMLAndCloseConnection
+#else
+#define MAYBE_GenerateMHTMLAndCloseConnection GenerateMHTMLAndCloseConnection
+#endif
+IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest,
+ MAYBE_GenerateMHTMLAndCloseConnection) {
RespondAndDisconnectMockWriter mock_writer;
NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html"));
diff --git a/chromium/content/browser/download/save_file_manager.cc b/chromium/content/browser/download/save_file_manager.cc
index 9aab4195b5f..78d9257dad8 100644
--- a/chromium/content/browser/download/save_file_manager.cc
+++ b/chromium/content/browser/download/save_file_manager.cc
@@ -241,6 +241,13 @@ void SaveFileManager::SaveURL(SaveItemId save_item_id,
request->priority = net::DEFAULT_PRIORITY;
request->load_flags = net::LOAD_SKIP_CACHE_VALIDATION;
+ // To avoid https://crbug.com/974312, downloads initiated by Save-Page-As
+ // should be treated as navigations. This definitely makes sense for the
+ // top-level page (e.g. in SAVE_PAGE_TYPE_AS_ONLY_HTML mode). This is
+ // probably also okay for subresources downloaded in
+ // SAVE_PAGE_TYPE_AS_COMPLETE_HTML mode.
+ request->fetch_request_mode = network::mojom::FetchRequestMode::kNavigate;
+
network::mojom::URLLoaderFactory* factory = nullptr;
std::unique_ptr<DataURLLoaderFactory> data_url_loader_factory;
diff --git a/chromium/content/browser/download/save_types.h b/chromium/content/browser/download/save_types.h
index 20c8089d4a5..219aa86c3c8 100644
--- a/chromium/content/browser/download/save_types.h
+++ b/chromium/content/browser/download/save_types.h
@@ -13,16 +13,16 @@
#include <vector>
#include "base/files/file_path.h"
-#include "gpu/command_buffer/common/id_type.h"
+#include "base/util/type_safety/id_type.h"
#include "url/gurl.h"
namespace content {
class SavePackage;
-using SavePackageId = gpu::IdType32<SavePackage>;
+using SavePackageId = util::IdType32<SavePackage>;
class SaveItem;
-using SaveItemId = gpu::IdType32<SaveItem>;
+using SaveItemId = util::IdType32<SaveItem>;
// Map from save_item_id into final file path.
using FinalNamesMap =
diff --git a/chromium/content/browser/download/url_downloader_factory.cc b/chromium/content/browser/download/url_downloader_factory.cc
index 9d2c16550a8..387b79dea83 100644
--- a/chromium/content/browser/download/url_downloader_factory.cc
+++ b/chromium/content/browser/download/url_downloader_factory.cc
@@ -9,6 +9,7 @@
#include "content/browser/download/download_request_core.h"
#include "content/browser/download/url_downloader.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/service_manager/public/cpp/connector.h"
namespace content {
@@ -24,6 +25,7 @@ UrlDownloaderFactory::CreateUrlDownloadHandler(
url_loader_factory_getter,
const download::URLSecurityPolicy& url_security_policy,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+ std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
std::unique_ptr<net::URLRequest> url_request =
DownloadRequestCore::CreateRequestOnIOThread(
diff --git a/chromium/content/browser/download/url_downloader_factory.h b/chromium/content/browser/download/url_downloader_factory.h
index 23b287feb37..6c70cc8ad6f 100644
--- a/chromium/content/browser/download/url_downloader_factory.h
+++ b/chromium/content/browser/download/url_downloader_factory.h
@@ -35,6 +35,7 @@ class UrlDownloaderFactory : public download::UrlDownloadHandlerFactory {
shared_url_loader_factory,
const download::URLSecurityPolicy& url_security_policy,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+ std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) override;
};
diff --git a/chromium/content/browser/file_url_loader_factory.cc b/chromium/content/browser/file_url_loader_factory.cc
index 5a2d0680e76..669e3f3b3a1 100644
--- a/chromium/content/browser/file_url_loader_factory.cc
+++ b/chromium/content/browser/file_url_loader_factory.cc
@@ -118,6 +118,23 @@ bool AskIfSharedCorsOriginAccessListNotAllowOnIO(
network::cors::OriginAccessList::AccessState::kAllowed;
}
+base::File::Error ToFileError(int net_error) {
+ // Note: For now, only return specific errors that our obervers care about.
+ switch (net_error) {
+ case net::OK:
+ return base::File::FILE_OK;
+ case net::ERR_FILE_NOT_FOUND:
+ return base::File::FILE_ERROR_NOT_FOUND;
+ case net::ERR_ACCESS_DENIED:
+ return base::File::FILE_ERROR_ACCESS_DENIED;
+ case net::ERR_ABORTED:
+ case net::ERR_CONNECTION_ABORTED:
+ return base::File::FILE_ERROR_ABORT;
+ default:
+ return base::File::FILE_ERROR_FAILED;
+ }
+}
+
class FileURLDirectoryLoader
: public network::mojom::URLLoader,
public net::DirectoryLister::DirectoryListerDelegate {
@@ -668,8 +685,11 @@ class FileURLLoader : public network::mojom::URLLoader {
std::unique_ptr<FileURLLoaderObserver> observer) {
client_->OnComplete(network::URLLoaderCompletionStatus(net_error));
client_.reset();
- if (observer)
+ if (observer) {
+ if (net_error != net::OK)
+ observer->OnBytesRead(nullptr, 0u, ToFileError(net_error));
observer->OnDoneReading();
+ }
MaybeDeleteSelf();
}
diff --git a/chromium/content/browser/fileapi/README.md b/chromium/content/browser/fileapi/README.md
index 470736189bf..ac24aa5e861 100644
--- a/chromium/content/browser/fileapi/README.md
+++ b/chromium/content/browser/fileapi/README.md
@@ -17,7 +17,3 @@ contains the mojom interfaces for these APIs.
[`FileSystemManagerImpl`](file_system_manager_impl.h) is the main entry point
for calls from the renderer, it mostly redirects incoming mojom calls to a
`storage::FileSystemContext` instance.
-
-[`FileSystemChooser`](file_system_chooser.h) uses ui::SelectFileDialog to show
-a file or directory picker, and is responsible for granting a process the right
-permissions for actually accessing the files that were selected.
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper.cc b/chromium/content/browser/fileapi/browser_file_system_helper.cc
index e278fff7f54..7caf1a9a58d 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper.cc
+++ b/chromium/content/browser/fileapi/browser_file_system_helper.cc
@@ -251,22 +251,24 @@ void PrepareDropDataForChildProcess(
file_system_context->CrackURL(file_system_file.url);
std::string register_name;
- std::string filesystem_id = isolated_context->RegisterFileSystemForPath(
- file_system_url.type(), file_system_url.filesystem_id(),
- file_system_url.path(), &register_name);
-
- if (!filesystem_id.empty()) {
- // Grant the permission iff the ID is valid.
- security_policy->GrantReadFileSystem(child_id, filesystem_id);
+ storage::IsolatedContext::ScopedFSHandle filesystem =
+ isolated_context->RegisterFileSystemForPath(
+ file_system_url.type(), file_system_url.filesystem_id(),
+ file_system_url.path(), &register_name);
+
+ if (filesystem.is_valid()) {
+ // Grant the permission iff the ID is valid. This will also keep the FS
+ // alive after |filesystem| goes out of scope.
+ security_policy->GrantReadFileSystem(child_id, filesystem.id());
}
// Note: We are using the origin URL provided by the sender here. It may be
// different from the receiver's.
file_system_file.url = GURL(
storage::GetIsolatedFileSystemRootURIString(
- file_system_url.origin().GetURL(), filesystem_id, std::string())
+ file_system_url.origin().GetURL(), filesystem.id(), std::string())
.append(register_name));
- file_system_file.filesystem_id = filesystem_id;
+ file_system_file.filesystem_id = filesystem.id();
}
}
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper_unittest.cc b/chromium/content/browser/fileapi/browser_file_system_helper_unittest.cc
index 97e416240cd..2dd288048f6 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper_unittest.cc
+++ b/chromium/content/browser/fileapi/browser_file_system_helper_unittest.cc
@@ -15,6 +15,7 @@
#include "content/public/common/drop_data.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"
#include "net/base/filename_util.h"
#include "storage/browser/fileapi/external_mount_points.h"
#include "storage/browser/fileapi/file_system_options.h"
@@ -44,7 +45,7 @@ TEST(BrowserFileSystemHelperTest,
// Prepare |original_file| FileSystemURL that comes from a |sensitive_origin|.
// This attempts to simulate for unit testing the drive URL from
// https://crbug.com/705295#c23.
- const GURL kSensitiveOrigin("chrome://hhaomjibdihmijegdhdafkllkbggdgoj/");
+ const GURL kSensitiveOrigin(GetWebUIURL("hhaomjibdihmijegdhdafkllkbggdgoj"));
const char kMountName[] = "drive-testuser%40gmail.com-hash";
const base::FilePath kTestPath(FILE_PATH_LITERAL("root/dir/testfile.jpg"));
base::FilePath mount_path = temp_dir.GetPath().AppendASCII(kMountName);
diff --git a/chromium/content/browser/fileapi/file_system_manager_impl.cc b/chromium/content/browser/fileapi/file_system_manager_impl.cc
index bfa57a3ee99..930af72a6a7 100644
--- a/chromium/content/browser/fileapi/file_system_manager_impl.cc
+++ b/chromium/content/browser/fileapi/file_system_manager_impl.cc
@@ -25,7 +25,6 @@
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
-#include "content/browser/fileapi/file_system_chooser.h"
#include "content/common/fileapi/webblob_messages.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -38,7 +37,6 @@
#include "storage/browser/fileapi/file_observers.h"
#include "storage/browser/fileapi/file_permission_policy.h"
#include "storage/browser/fileapi/file_system_context.h"
-#include "storage/browser/fileapi/file_writer_impl.h"
#include "storage/browser/fileapi/isolated_context.h"
#include "storage/common/fileapi/file_system_info.h"
#include "storage/common/fileapi/file_system_type_converters.h"
@@ -123,11 +121,9 @@ struct FileSystemManagerImpl::ReadDirectorySyncCallbackEntry {
FileSystemManagerImpl::FileSystemManagerImpl(
int process_id,
- int frame_id,
scoped_refptr<storage::FileSystemContext> file_system_context,
scoped_refptr<ChromeBlobStorageContext> blob_storage_context)
: process_id_(process_id),
- frame_id_(frame_id),
context_(std::move(file_system_context)),
security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()),
blob_storage_context_(std::move(blob_storage_context)),
@@ -569,53 +565,6 @@ void FileSystemManagerImpl::GetPlatformPath(const GURL& path,
process_id_, context_, GetWeakPtr(), std::move(callback)));
}
-void FileSystemManagerImpl::CreateWriter(const GURL& file_path,
- CreateWriterCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (!base::FeatureList::IsEnabled(blink::features::kNativeFilesystemAPI)) {
- bindings_.ReportBadMessage("FileSystemManager.CreateWriter");
- return;
- }
-
- FileSystemURL url(context_->CrackURL(file_path));
- base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(url);
- if (opt_error) {
- std::move(callback).Run(opt_error.value(), nullptr);
- return;
- }
- if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
- std::move(callback).Run(base::File::FILE_ERROR_SECURITY, nullptr);
- return;
- }
-
- blink::mojom::FileWriterPtr writer;
- mojo::MakeStrongBinding(std::make_unique<storage::FileWriterImpl>(
- url, context_->CreateFileSystemOperationRunner(),
- blob_storage_context_->context()->AsWeakPtr()),
- MakeRequest(&writer));
- std::move(callback).Run(base::File::FILE_OK, std::move(writer));
-}
-
-void FileSystemManagerImpl::ChooseEntry(
- blink::mojom::ChooseFileSystemEntryType type,
- std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts,
- bool include_accepts_all,
- ChooseEntryCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!base::FeatureList::IsEnabled(blink::features::kNativeFilesystemAPI)) {
- bindings_.ReportBadMessage("FSMI_WRITABLE_FILES_DISABLED");
- return;
- }
-
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(
- &FileSystemChooser::CreateAndShow, process_id_, frame_id_, type,
- std::move(accepts), include_accepts_all, std::move(callback),
- base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})));
-}
-
void FileSystemManagerImpl::Cancel(
OperationID op_id,
FileSystemCancellableOperationImpl::CancelCallback callback) {
diff --git a/chromium/content/browser/fileapi/file_system_manager_impl.h b/chromium/content/browser/fileapi/file_system_manager_impl.h
index 5055e5061ca..d7b44bd4c59 100644
--- a/chromium/content/browser/fileapi/file_system_manager_impl.h
+++ b/chromium/content/browser/fileapi/file_system_manager_impl.h
@@ -62,7 +62,6 @@ class CONTENT_EXPORT FileSystemManagerImpl
// and pepper (via the render process host).
FileSystemManagerImpl(
int process_id,
- int frame_id,
scoped_refptr<storage::FileSystemContext> file_system_context,
scoped_refptr<ChromeBlobStorageContext> blob_storage_context);
~FileSystemManagerImpl() override;
@@ -123,13 +122,6 @@ class CONTENT_EXPORT FileSystemManagerImpl
CreateSnapshotFileCallback callback) override;
void GetPlatformPath(const GURL& file_path,
GetPlatformPathCallback callback) override;
- void CreateWriter(const GURL& file_path,
- CreateWriterCallback callback) override;
- void ChooseEntry(
- blink::mojom::ChooseFileSystemEntryType type,
- std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts,
- bool include_accepts_all,
- ChooseEntryCallback callback) override;
private:
class FileSystemCancellableOperationImpl;
@@ -212,7 +204,6 @@ class CONTENT_EXPORT FileSystemManagerImpl
void OnConnectionErrorForOpListeners(OperationListenerID listener_id);
const int process_id_;
- const int frame_id_;
const scoped_refptr<storage::FileSystemContext> context_;
ChildProcessSecurityPolicyImpl* const security_policy_;
const scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
diff --git a/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc b/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
index 5f22097758b..10bcc0be69b 100644
--- a/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
@@ -235,7 +235,7 @@ TEST_F(MultiThreadFileSystemOperationRunnerTest, OpenAndShutdown) {
operation_runner()->Shutdown();
// Wait until the task posted on the blocking thread is done.
- base::ThreadPool::GetInstance()->FlushForTesting();
+ base::ThreadPoolInstance::Get()->FlushForTesting();
// This should finish without thread assertion failure on debug build.
}
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 f7a7d52f3fb..5b4ffbdff75 100644
--- a/chromium/content/browser/fileapi/file_system_url_loader_factory.cc
+++ b/chromium/content/browser/fileapi/file_system_url_loader_factory.cc
@@ -161,8 +161,11 @@ class FileSystemEntryURLLoader
return;
}
+ // If the requested URL is not commitable in the current process, block the
+ // request. This prevents one origin from fetching filesystem: resources
+ // belonging to another origin, see https://crbug.com/964245.
if (params_.render_process_host_id != ChildProcessHost::kInvalidUniqueID &&
- !ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
+ !ChildProcessSecurityPolicyImpl::GetInstance()->CanCommitURL(
params_.render_process_host_id, request.url)) {
DVLOG(1) << "Denied unauthorized request for "
<< request.url.possibly_invalid_spec();
@@ -336,8 +339,7 @@ class FileSystemDirectoryURLLoader : public FileSystemEntryURLLoader {
options.struct_size = sizeof(MojoCreateDataPipeOptions);
options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
options.element_num_bytes = 1;
- options.capacity_num_bytes =
- std::max(data_.size(), kDefaultFileSystemUrlPipeSize);
+ options.capacity_num_bytes = kDefaultFileSystemUrlPipeSize;
mojo::ScopedDataPipeProducerHandle producer_handle;
mojo::ScopedDataPipeConsumerHandle consumer_handle;
@@ -475,7 +477,7 @@ class FileSystemFileURLLoader : public FileSystemEntryURLLoader {
options.struct_size = sizeof(MojoCreateDataPipeOptions);
options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
options.element_num_bytes = 1;
- options.capacity_num_bytes = remaining_bytes_;
+ options.capacity_num_bytes = kDefaultFileSystemUrlPipeSize;
mojo::ScopedDataPipeProducerHandle producer_handle;
MojoResult rv =
@@ -493,15 +495,16 @@ class FileSystemFileURLLoader : public FileSystemEntryURLLoader {
data_producer_ = std::make_unique<mojo::StringDataPipeProducer>(
std::move(producer_handle));
- file_data_ =
- base::MakeRefCounted<net::IOBuffer>(kDefaultFileSystemUrlPipeSize);
+ size_t bytes_to_read = std::min(
+ static_cast<int64_t>(kDefaultFileSystemUrlPipeSize), remaining_bytes_);
+ file_data_ = base::MakeRefCounted<net::IOBuffer>(bytes_to_read);
ReadMoreFileData();
}
void ReadMoreFileData() {
int64_t bytes_to_read = std::min(
static_cast<int64_t>(kDefaultFileSystemUrlPipeSize), remaining_bytes_);
- if (!bytes_to_read) {
+ if (bytes_to_read == 0) {
if (consumer_handle_.is_valid()) {
// This was an empty file; make sure to call OnReceiveResponse and
// OnStartLoadingResponseBody regardless.
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 7e30c919441..ac69f74095a 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
@@ -9,19 +9,24 @@
#include <vector>
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/i18n/unicodestring.h"
#include "base/rand_util.h"
#include "base/task/post_task.h"
+#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/fileapi/file_system_url_loader_factory.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_task_traits.h"
+#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
+#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "net/base/mime_util.h"
+#include "net/dns/mock_host_resolver.h"
#include "net/http/http_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/features.h"
@@ -30,8 +35,10 @@
#include "services/network/test/test_url_loader_client.h"
#include "storage/browser/fileapi/external_mount_points.h"
#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_features.h"
#include "storage/browser/fileapi/file_system_file_util.h"
#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
#include "storage/browser/fileapi/file_system_url.h"
#include "storage/browser/test/async_file_test_helper.h"
#include "storage/browser/test/mock_special_storage_policy.h"
@@ -42,6 +49,7 @@
#include "third_party/icu/source/i18n/unicode/datefmt.h"
#include "third_party/icu/source/i18n/unicode/regex.h"
+using base::BindLambdaForTesting;
using content::AsyncFileTestHelper;
using network::mojom::URLLoaderFactory;
using storage::FileSystemContext;
@@ -51,6 +59,8 @@ using storage::FileSystemURL;
namespace content {
namespace {
+enum class TestMode { kRegular, kIncognito, kRegularWithIncognitoEnabled };
+
// We always use the TEMPORARY FileSystem in these tests.
const char kFileSystemURLPrefix[] = "filesystem:http://remote/temporary/";
@@ -146,74 +156,101 @@ bool IsDirectoryListingTitle(const std::string& line) {
return line.find("<script>start(\"") == 0;
}
-void ShutdownFileSystemContextOnIOThread(
- scoped_refptr<FileSystemContext> file_system_context) {
- if (!file_system_context)
- return;
- file_system_context->Shutdown();
- file_system_context = nullptr;
-}
-
} // namespace
-class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
+class FileSystemURLLoaderFactoryTest
+ : public ContentBrowserTest,
+ public ::testing::WithParamInterface<TestMode> {
protected:
- FileSystemURLLoaderFactoryTest() {}
+ FileSystemURLLoaderFactoryTest() : file_util_(nullptr) {
+ std::vector<base::Feature> features;
+ features.push_back(network::features::kNetworkService);
+ if (GetParam() == TestMode::kIncognito ||
+ GetParam() == TestMode::kRegularWithIncognitoEnabled) {
+ features.push_back(storage::features::kEnableFilesystemInIncognito);
+ }
+ feature_list_.InitWithFeatures(features, std::vector<base::Feature>());
+ }
~FileSystemURLLoaderFactoryTest() override = default;
+ bool IsInMemoryFileSystemEnabled() {
+ return base::FeatureList::IsEnabled(
+ storage::features::kEnableFilesystemInIncognito);
+ }
+
+ bool IsIncognito() { return GetParam() == TestMode::kIncognito; }
+
void SetUpOnMainThread() override {
- feature_list_.InitAndEnableFeature(network::features::kNetworkService);
+ io_task_runner_ =
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
+ blocking_task_runner_ =
+ base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()});
special_storage_policy_ = new MockSpecialStoragePolicy;
+ // Support multiple sites on the test server.
+ host_resolver()->AddRule("*", "127.0.0.1");
+
+ ContentBrowserTest::SetUpOnMainThread();
+
// 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());
- base::RunLoop run_loop;
- file_system_context_->OpenFileSystem(
- GURL("http://remote/"), storage::kFileSystemTypeTemporary,
- storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- base::BindOnce(&FileSystemURLLoaderFactoryTest::OnOpenFileSystem,
- run_loop.QuitWhenIdleClosure()));
- run_loop.Run();
-
- ContentBrowserTest::SetUpOnMainThread();
+ CreateFileSystemContext(nullptr, temp_dir_.GetPath());
+ file_util_ = file_system_context_->sandbox_delegate()->sync_file_util();
+
+ // The filesystem must be opened on the IO sequence.
+ base::RunLoop loop;
+ io_task_runner_->PostTask(
+ FROM_HERE, BindLambdaForTesting([&]() {
+ file_system_context_->OpenFileSystem(
+ GURL("http://remote/"), storage::kFileSystemTypeTemporary,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::BindOnce(&FileSystemURLLoaderFactoryTest::OnOpenFileSystem,
+ loop.QuitClosure()));
+ }));
+ loop.Run();
}
void TearDownOnMainThread() override {
loader_.reset();
- base::PostTaskWithTraits(
- FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&ShutdownFileSystemContextOnIOThread,
- std::move(file_system_context_)));
+ base::RunLoop loop;
+ io_task_runner_->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
+ if (file_system_context_) {
+ file_system_context_->Shutdown();
+ file_system_context_ = nullptr;
+ }
+ loop.Quit();
+ }));
+ loop.Run();
special_storage_policy_ = nullptr;
// FileReader posts a task to close the file in destructor.
base::RunLoop().RunUntilIdle();
ContentBrowserTest::TearDownOnMainThread();
}
- void SetUpAutoMountContext(base::FilePath* mnt_point) {
- *mnt_point = temp_dir_.GetPath().AppendASCII("auto_mount_dir");
- ASSERT_TRUE(base::CreateDirectory(*mnt_point));
+ base::FilePath SetUpAutoMountContext() {
+ base::FilePath mnt_point =
+ temp_dir_.GetPath().AppendASCII("auto_mount_dir");
+ EXPECT_TRUE(base::CreateDirectory(mnt_point));
std::vector<std::unique_ptr<storage::FileSystemBackend>>
additional_providers;
additional_providers.push_back(std::make_unique<TestFileSystemBackend>(
- base::ThreadTaskRunnerHandle::Get().get(), *mnt_point));
+ base::ThreadTaskRunnerHandle::Get().get(), mnt_point));
std::vector<storage::URLRequestAutoMountHandler> handlers = {
base::BindRepeating(&TestAutoMountForURLRequest)};
file_system_context_ = CreateFileSystemContextWithAutoMountersForTesting(
- nullptr, std::move(additional_providers), handlers,
- temp_dir_.GetPath());
+ io_task_runner_, blocking_task_runner_, nullptr,
+ std::move(additional_providers), handlers, temp_dir_.GetPath());
+ return mnt_point;
}
- void SetFileUpAutoMountContext() {
- base::FilePath mnt_point;
- SetUpAutoMountContext(&mnt_point);
+ void SetUpFileAutoMountContext() {
+ const base::FilePath mnt_point = SetUpAutoMountContext();
ASSERT_EQ(static_cast<int>(sizeof(kTestFileData)) - 1,
base::WriteFile(mnt_point.AppendASCII("foo"), kTestFileData,
@@ -226,38 +263,79 @@ class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
}
void CreateDirectory(const base::StringPiece& dir_name) {
- base::FilePath path = base::FilePath().AppendASCII(dir_name);
std::unique_ptr<FileSystemOperationContext> context(NewOperationContext());
- ASSERT_EQ(base::File::FILE_OK,
- file_util()->CreateDirectory(context.get(), CreateURL(path),
- false /* exclusive */,
- false /* recursive */));
+ base::RunLoop loop;
+ blocking_task_runner_->PostTask(
+ FROM_HERE, BindLambdaForTesting([&]() {
+ base::FilePath path = base::FilePath().AppendASCII(dir_name);
+ ASSERT_EQ(base::File::FILE_OK,
+ file_util_->CreateDirectory(context.get(), CreateURL(path),
+ /*exclusive=*/false,
+ /*recursive=*/false));
+ loop.Quit();
+ }));
+ loop.Run();
}
void WriteFile(const base::StringPiece& file_name,
const char* buf,
int buf_size) {
- FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
+ FileSystemURL url;
+ url = file_system_context_->CreateCrackedFileSystemURL(
GURL("http://remote"), storage::kFileSystemTypeTemporary,
base::FilePath().AppendASCII(file_name));
- ASSERT_EQ(base::File::FILE_OK,
- AsyncFileTestHelper::CreateFileWithData(
- file_system_context_.get(), url, buf, buf_size));
+
+ base::File::Error result = base::File::FILE_OK;
+ base::FilePath local_path;
+ base::ScopedTempDir dir;
+ if (!dir.CreateUniqueTempDir())
+ result = base::File::FILE_ERROR_FAILED;
+ local_path = dir.GetPath().AppendASCII("tmp");
+ if (buf_size != base::WriteFile(local_path, buf, buf_size))
+ result = base::File::FILE_ERROR_FAILED;
+ EXPECT_EQ(base::File::FILE_OK, result);
+
+ base::RunLoop loop;
+ io_task_runner_->PostTask(
+ FROM_HERE, BindLambdaForTesting([&]() {
+ file_system_context_->operation_runner()->CopyInForeignFile(
+ local_path, url, BindLambdaForTesting([&](base::File::Error err) {
+ result = err;
+ loop.Quit();
+ }));
+ }));
+ loop.Run();
+ EXPECT_EQ(base::File::FILE_OK, result);
}
void EnsureFileExists(const base::StringPiece file_name) {
- base::FilePath path = base::FilePath().AppendASCII(file_name);
std::unique_ptr<FileSystemOperationContext> context(NewOperationContext());
- ASSERT_EQ(
- base::File::FILE_OK,
- file_util()->EnsureFileExists(context.get(), CreateURL(path), nullptr));
+
+ base::RunLoop loop;
+ blocking_task_runner_->PostTask(
+ FROM_HERE, BindLambdaForTesting([&]() {
+ base::FilePath path = base::FilePath().AppendASCII(file_name);
+ ASSERT_EQ(base::File::FILE_OK,
+ file_util_->EnsureFileExists(context.get(), CreateURL(path),
+ nullptr));
+ loop.Quit();
+ }));
+ loop.Run();
}
void TruncateFile(const base::StringPiece file_name, int64_t length) {
- base::FilePath path = base::FilePath().AppendASCII(file_name);
std::unique_ptr<FileSystemOperationContext> context(NewOperationContext());
- ASSERT_EQ(base::File::FILE_OK,
- file_util()->Truncate(context.get(), CreateURL(path), length));
+
+ base::RunLoop loop;
+ blocking_task_runner_->PostTask(
+ FROM_HERE, BindLambdaForTesting([&]() {
+ base::FilePath path = base::FilePath().AppendASCII(file_name);
+ ASSERT_EQ(
+ base::File::FILE_OK,
+ file_util_->Truncate(context.get(), CreateURL(path), length));
+ loop.Quit();
+ }));
+ loop.Run();
}
// If |size| is negative, the reported size is ignored.
@@ -305,15 +383,15 @@ class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
}
std::unique_ptr<network::TestURLLoaderClient> TestLoad(const GURL& url) {
- auto client = TestLoadHelper(url, /*extra_headers=*/nullptr,
- file_system_context_.get());
+ auto client =
+ TestLoadHelper(url, /*extra_headers=*/nullptr, file_system_context_);
client->RunUntilComplete();
return client;
}
std::unique_ptr<network::TestURLLoaderClient> TestLoadWithContext(
const GURL& url,
- FileSystemContext* file_system_context) {
+ scoped_refptr<storage::FileSystemContext> file_system_context) {
auto client =
TestLoadHelper(url, /*extra_headers=*/nullptr, file_system_context);
client->RunUntilComplete();
@@ -323,15 +401,23 @@ class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
std::unique_ptr<network::TestURLLoaderClient> TestLoadWithHeaders(
const GURL& url,
const net::HttpRequestHeaders* extra_headers) {
- auto client =
- TestLoadHelper(url, extra_headers, file_system_context_.get());
+ auto client = TestLoadHelper(url, extra_headers, file_system_context_);
client->RunUntilComplete();
return client;
}
- std::unique_ptr<network::TestURLLoaderClient> TestLoadNoRun(const GURL& url) {
- return TestLoadHelper(url, /*extra_headers=*/nullptr,
- file_system_context_.get());
+ std::unique_ptr<network::TestURLLoaderClient> TestLoadNoRun(
+ const GURL& url,
+ const net::HttpRequestHeaders* extra_headers = nullptr) {
+ return TestLoadHelper(url, extra_headers, file_system_context_);
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner() {
+ return io_task_runner_;
+ }
+
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner() {
+ return blocking_task_runner_;
}
// |temp_dir_| must be deleted last.
@@ -347,8 +433,22 @@ class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
std::move(done_closure).Run();
}
- storage::FileSystemFileUtil* file_util() {
- return file_system_context_->sandbox_delegate()->sync_file_util();
+ storage::FileSystemContext* CreateFileSystemContext(
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ const base::FilePath& base_path) {
+ std::vector<std::unique_ptr<storage::FileSystemBackend>>
+ additional_providers;
+ additional_providers.push_back(std::make_unique<TestFileSystemBackend>(
+ blocking_task_runner_.get(), base_path));
+ if (IsIncognito()) {
+ return CreateIncognitoFileSystemContextWithAdditionalProvidersForTesting(
+ io_task_runner_, blocking_task_runner_, quota_manager_proxy,
+ std::move(additional_providers), base_path);
+ } else {
+ return CreateFileSystemContextWithAdditionalProvidersForTesting(
+ io_task_runner_, blocking_task_runner_, quota_manager_proxy,
+ std::move(additional_providers), base_path);
+ }
}
FileSystemOperationContext* NewOperationContext() {
@@ -362,28 +462,10 @@ class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
return shell()->web_contents()->GetMainFrame();
}
- // Starts |request| using |loader_factory| and sets |out_loader| and
- // |out_loader_client| to the resulting URLLoader and its URLLoaderClient. The
- // caller can then use functions like client.RunUntilComplete() to wait for
- // completion.
- void StartRequest(
- URLLoaderFactory* loader_factory,
- const network::ResourceRequest& request,
- network::mojom::URLLoaderPtr* out_loader,
- std::unique_ptr<network::TestURLLoaderClient>* out_loader_client) {
- *out_loader_client = std::make_unique<network::TestURLLoaderClient>();
- loader_factory->CreateLoaderAndStart(
- mojo::MakeRequest(out_loader), 0, 0, network::mojom::kURLLoadOptionNone,
- request, (*out_loader_client)->CreateInterfacePtr(),
- net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
- }
-
- content::WebContents* GetWebContents() { return shell()->web_contents(); }
-
std::unique_ptr<network::TestURLLoaderClient> TestLoadHelper(
const GURL& url,
const net::HttpRequestHeaders* extra_headers,
- FileSystemContext* file_system_context) {
+ scoped_refptr<storage::FileSystemContext> file_system_context) {
network::ResourceRequest request;
request.url = url;
if (extra_headers)
@@ -393,19 +475,35 @@ class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
auto factory = content::CreateFileSystemURLLoaderFactory(
render_frame_host(), /*is_navigation=*/false, file_system_context,
storage_domain);
- std::unique_ptr<network::TestURLLoaderClient> client;
- StartRequest(factory.get(), request, &loader_, &client);
+
+ auto client = std::make_unique<network::TestURLLoaderClient>();
+ factory->CreateLoaderAndStart(
+ mojo::MakeRequest(&loader_), 0, 0, network::mojom::kURLLoadOptionNone,
+ request, client->CreateInterfacePtr(),
+ net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
+
return client;
}
base::test::ScopedFeatureList feature_list_;
scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
scoped_refptr<FileSystemContext> file_system_context_;
+ // Owned by |file_system_context_| and only usable on |blocking_task_runner_|.
+ storage::FileSystemFileUtil* file_util_;
DISALLOW_COPY_AND_ASSIGN(FileSystemURLLoaderFactoryTest);
};
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, DirectoryListing) {
+INSTANTIATE_TEST_SUITE_P(
+ ,
+ FileSystemURLLoaderFactoryTest,
+ testing::Values(TestMode::kRegular,
+ TestMode::kIncognito,
+ TestMode::kRegularWithIncognitoEnabled));
+
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, DirectoryListing) {
base::ScopedAllowBlockingForTesting allow_blocking;
CreateDirectory("foo");
CreateDirectory("foo/bar");
@@ -448,7 +546,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, DirectoryListing) {
VerifyListingEntry(listing_entries[1], "hoge", "hoge", false, 10);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, InvalidURL) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, InvalidURL) {
base::ScopedAllowBlockingForTesting allow_blocking;
auto client = TestLoad(GURL("filesystem:/foo/bar/baz"));
ASSERT_FALSE(client->has_received_response());
@@ -456,7 +554,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, InvalidURL) {
EXPECT_EQ(net::ERR_INVALID_URL, client->completion_status().error_code);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, NoSuchRoot) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, NoSuchRoot) {
base::ScopedAllowBlockingForTesting allow_blocking;
auto client = TestLoad(GURL("filesystem:http://remote/persistent/somedir/"));
ASSERT_FALSE(client->has_received_response());
@@ -464,7 +562,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, NoSuchRoot) {
EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, NoSuchDirectory) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, NoSuchDirectory) {
base::ScopedAllowBlockingForTesting allow_blocking;
auto client = TestLoad(CreateFileSystemURL("somedir/"));
ASSERT_FALSE(client->has_received_response());
@@ -472,7 +570,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, NoSuchDirectory) {
EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, Cancel) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, Cancel) {
base::ScopedAllowBlockingForTesting allow_blocking;
CreateDirectory("foo");
auto client = TestLoadNoRun(CreateFileSystemURL("foo/"));
@@ -485,31 +583,41 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, Cancel) {
// If we get here, success! we didn't crash!
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, Incognito) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, Incognito) {
base::ScopedAllowBlockingForTesting allow_blocking;
CreateDirectory("foo");
scoped_refptr<FileSystemContext> file_system_context =
- CreateIncognitoFileSystemContextForTesting(nullptr, temp_dir_.GetPath());
+ CreateIncognitoFileSystemContextForTesting(io_task_runner(),
+ blocking_task_runner(),
+ nullptr, temp_dir_.GetPath());
auto client =
TestLoadWithContext(CreateFileSystemURL("/"), file_system_context.get());
- ASSERT_TRUE(client->has_received_response());
- ASSERT_TRUE(client->has_received_completion());
+ if (IsInMemoryFileSystemEnabled()) {
+ // When in-memory file system is enabled, the request fails as the requested
+ // directory does not exist in in-memory obfuscated file system.
+ ASSERT_FALSE(client->has_received_response());
+ ASSERT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
+ } else {
+ ASSERT_TRUE(client->has_received_response());
+ ASSERT_TRUE(client->has_received_completion());
- std::string response_text = ReadDataPipe(client->response_body_release());
- EXPECT_GT(response_text.size(), 0ul);
+ std::string response_text = ReadDataPipe(client->response_body_release());
+ EXPECT_GT(response_text.size(), 0ul);
- std::istringstream in(response_text);
+ std::istringstream in(response_text);
- int num_entries = 0;
- std::string line;
- while (!!std::getline(in, line)) {
- if (IsDirectoryListingLine(line))
- num_entries++;
- }
+ int num_entries = 0;
+ std::string line;
+ while (!!std::getline(in, line)) {
+ if (IsDirectoryListingLine(line))
+ num_entries++;
+ }
- EXPECT_EQ(0, num_entries);
+ EXPECT_EQ(0, num_entries);
+ }
client = TestLoadWithContext(CreateFileSystemURL("foo"),
file_system_context.get());
@@ -518,11 +626,10 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, Incognito) {
EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest,
AutoMountDirectoryListing) {
base::ScopedAllowBlockingForTesting allow_blocking;
- base::FilePath mnt_point;
- SetUpAutoMountContext(&mnt_point);
+ base::FilePath mnt_point = SetUpAutoMountContext();
EXPECT_TRUE(base::CreateDirectory(mnt_point));
EXPECT_TRUE(base::CreateDirectory(mnt_point.AppendASCII("foo")));
EXPECT_EQ(10,
@@ -558,10 +665,9 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
kValidExternalMountPoint));
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, AutoMountInvalidRoot) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, AutoMountInvalidRoot) {
base::ScopedAllowBlockingForTesting allow_blocking;
- base::FilePath mnt_point;
- SetUpAutoMountContext(&mnt_point);
+ base::FilePath mnt_point = SetUpAutoMountContext();
auto client = TestLoad(GURL("filesystem:http://automount/external/invalid"));
EXPECT_FALSE(client->has_received_response());
@@ -573,10 +679,9 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, AutoMountInvalidRoot) {
"invalid"));
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, AutoMountNoHandler) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, AutoMountNoHandler) {
base::ScopedAllowBlockingForTesting allow_blocking;
- base::FilePath mnt_point;
- SetUpAutoMountContext(&mnt_point);
+ base::FilePath mnt_point = SetUpAutoMountContext();
auto client = TestLoad(GURL("filesystem:http://noauto/external/mnt_name"));
EXPECT_FALSE(client->has_received_response());
@@ -588,7 +693,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, AutoMountNoHandler) {
kValidExternalMountPoint));
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileTest) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, FileTest) {
base::ScopedAllowBlockingForTesting allow_blocking;
WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
auto client = TestLoad(CreateFileSystemURL("file1.dat"));
@@ -605,10 +710,37 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileTest) {
EXPECT_EQ("no-cache", cache_control);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
+// Verify that when site isolation is enabled, a renderer process for one
+// origin can't request filesystem: URLs belonging to another origin. See
+// https://crbug.com/964245.
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, CrossOriginFileBlocked) {
+ IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess());
+
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
+
+ // Navigate main frame to foo.com.
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_TRUE(
+ NavigateToURL(shell()->web_contents(),
+ embedded_test_server()->GetURL("foo.com", "/title1.html")));
+
+ // Try requesting filesystem:http://remote/temporary/file1.dat from that
+ // frame. This should be blocked, as foo.com isn't allowed to request a
+ // filesystem URL for the http://remote origin.
+ auto client = TestLoad(CreateFileSystemURL("file1.dat"));
+ EXPECT_FALSE(client->has_received_response());
+ ASSERT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_INVALID_URL, client->completion_status().error_code);
+}
+
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest,
FileTestFullSpecifiedRange) {
base::ScopedAllowBlockingForTesting allow_blocking;
- const size_t buffer_size = 4000;
+ // Size should be larger than kDefaultFileSystemUrlPipeSize to test
+ // that large files are properly read in chunks and not entirely into
+ // memory.
+ const size_t buffer_size = 180'000;
std::unique_ptr<char[]> buffer(new char[buffer_size]);
FillBuffer(buffer.get(), buffer_size);
WriteFile("bigfile", buffer.get(), buffer_size);
@@ -623,15 +755,16 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
net::HttpRequestHeaders::kRange,
net::HttpByteRange::Bounded(first_byte_position, last_byte_position)
.GetHeaderValue());
- auto client = TestLoadWithHeaders(CreateFileSystemURL("bigfile"), &headers);
-
+ auto client = TestLoadNoRun(CreateFileSystemURL("bigfile"), &headers);
+ client->RunUntilResponseBodyArrived();
ASSERT_TRUE(client->has_received_response());
- EXPECT_TRUE(client->has_received_completion());
std::string response_text = ReadDataPipe(client->response_body_release());
+ client->RunUntilComplete();
+ EXPECT_TRUE(client->has_received_completion());
EXPECT_TRUE(partial_buffer_string == response_text);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest,
FileTestHalfSpecifiedRange) {
base::ScopedAllowBlockingForTesting allow_blocking;
const size_t buffer_size = 4000;
@@ -655,7 +788,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
EXPECT_TRUE(partial_buffer_string == response_text);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest,
FileTestMultipleRangesNotSupported) {
base::ScopedAllowBlockingForTesting allow_blocking;
WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
@@ -669,7 +802,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
client->completion_status().error_code);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileRangeOutOfBounds) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, FileRangeOutOfBounds) {
base::ScopedAllowBlockingForTesting allow_blocking;
WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
net::HttpRequestHeaders headers;
@@ -683,7 +816,9 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileRangeOutOfBounds) {
client->completion_status().error_code);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileDirRedirect) {
+// This test times out: http://crbug.com/944647.
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest,
+ DISABLED_FileDirRedirect) {
base::ScopedAllowBlockingForTesting allow_blocking;
CreateDirectory("dir");
auto client = TestLoad(CreateFileSystemURL("dir"));
@@ -695,7 +830,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileDirRedirect) {
EXPECT_EQ(CreateFileSystemURL("dir/"), client->redirect_info().new_url);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileNoSuchRoot) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, FileNoSuchRoot) {
base::ScopedAllowBlockingForTesting allow_blocking;
auto client = TestLoad(GURL("filesystem:http://remote/persistent/somefile"));
EXPECT_FALSE(client->has_received_response());
@@ -703,7 +838,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileNoSuchRoot) {
EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, NoSuchFile) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, NoSuchFile) {
base::ScopedAllowBlockingForTesting allow_blocking;
auto client = TestLoad(CreateFileSystemURL("somefile"));
EXPECT_FALSE(client->has_received_response());
@@ -711,7 +846,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, NoSuchFile) {
EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileCancel) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, FileCancel) {
base::ScopedAllowBlockingForTesting allow_blocking;
WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
auto client = TestLoadNoRun(CreateFileSystemURL("file1.dat"));
@@ -721,7 +856,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileCancel) {
// If we get here, success! we didn't crash!
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileGetMimeType) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, FileGetMimeType) {
base::ScopedAllowBlockingForTesting allow_blocking;
std::string file_data =
"<!DOCTYPE HTML><html><head>test</head>"
@@ -745,13 +880,15 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileGetMimeType) {
EXPECT_TRUE(client->response_head().did_mime_sniff);
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileIncognito) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, FileIncognito) {
base::ScopedAllowBlockingForTesting allow_blocking;
WriteFile("file", kTestFileData, base::size(kTestFileData) - 1);
// Creates a new filesystem context for incognito mode.
scoped_refptr<FileSystemContext> file_system_context =
- CreateIncognitoFileSystemContextForTesting(nullptr, temp_dir_.GetPath());
+ CreateIncognitoFileSystemContextForTesting(io_task_runner(),
+ blocking_task_runner(),
+ nullptr, temp_dir_.GetPath());
// The request should return NOT_FOUND error if it's in incognito mode.
auto client = TestLoadWithContext(CreateFileSystemURL("file"),
@@ -769,9 +906,9 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileIncognito) {
EXPECT_EQ(200, client->response_head().headers->response_code());
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileAutoMountFileTest) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, FileAutoMountFileTest) {
base::ScopedAllowBlockingForTesting allow_blocking;
- SetFileUpAutoMountContext();
+ SetUpFileAutoMountContext();
auto client =
TestLoad(GURL("filesystem:http://automount/external/mnt_name/foo"));
@@ -791,10 +928,10 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileAutoMountFileTest) {
kValidExternalMountPoint));
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest,
FileAutoMountInvalidRoot) {
base::ScopedAllowBlockingForTesting allow_blocking;
- SetFileUpAutoMountContext();
+ SetUpFileAutoMountContext();
auto client =
TestLoad(GURL("filesystem:http://automount/external/invalid/foo"));
@@ -807,9 +944,9 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
"invalid"));
}
-IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileAutoMountNoHandler) {
+IN_PROC_BROWSER_TEST_P(FileSystemURLLoaderFactoryTest, FileAutoMountNoHandler) {
base::ScopedAllowBlockingForTesting allow_blocking;
- SetFileUpAutoMountContext();
+ SetUpFileAutoMountContext();
auto client =
TestLoad(GURL("filesystem:http://noauto/external/mnt_name/foo"));
diff --git a/chromium/content/browser/find_request_manager.cc b/chromium/content/browser/find_request_manager.cc
index 5917984705d..3e0ca8d4771 100644
--- a/chromium/content/browser/find_request_manager.cc
+++ b/chromium/content/browser/find_request_manager.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/containers/queue.h"
+#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/find_in_page_client.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -30,23 +31,28 @@ namespace {
// Returns all child frames of |node|.
std::vector<FrameTreeNode*> GetChildren(FrameTreeNode* node) {
- std::vector<FrameTreeNode*> children(node->child_count());
- for (size_t i = 0; i != node->child_count(); ++i)
- children[i] = node->child_at(i);
-
- if (auto* contents = WebContentsImpl::FromOuterFrameTreeNode(node)) {
- children.push_back(contents->GetMainFrame()->frame_tree_node());
- } else {
- contents = WebContentsImpl::FromFrameTreeNode(node);
- if (node->IsMainFrame() && contents->GetBrowserPluginEmbedder()) {
- for (auto* inner_contents : contents->GetInnerWebContents()) {
- children.push_back(static_cast<WebContentsImpl*>(inner_contents)
- ->GetMainFrame()
- ->frame_tree_node());
- }
+ std::vector<FrameTreeNode*> children;
+ for (size_t i = 0; i != node->child_count(); ++i) {
+ if (auto* contents = static_cast<WebContentsImpl*>(
+ WebContentsImpl::FromOuterFrameTreeNode(node->child_at(i)))) {
+ // If the child is used for an inner WebContents then add the inner
+ // WebContents.
+ children.push_back(contents->GetFrameTree()->root());
+ } else {
+ children.push_back(node->child_at(i));
}
}
+ for (auto* contents :
+ WebContentsImpl::FromFrameTreeNode(node)->GetInnerWebContents()) {
+ auto* contents_impl = static_cast<WebContentsImpl*>(contents);
+ auto* guest = contents_impl->GetBrowserPluginGuest();
+ if (!GuestMode::IsCrossProcessFrameGuest(contents) && guest &&
+ guest->GetEmbedderFrame() &&
+ guest->GetEmbedderFrame()->frame_tree_node() == node) {
+ children.push_back(contents_impl->GetFrameTree()->root());
+ }
+ }
return children;
}
@@ -83,21 +89,25 @@ RenderFrameHost* GetDeepestLastChild(RenderFrameHost* rfh) {
// Returns the parent FrameTreeNode of |node|, if |node| has a parent, or
// nullptr otherwise.
FrameTreeNode* GetParent(FrameTreeNode* node) {
+ if (!node)
+ return nullptr;
if (node->parent())
return node->parent();
- // The parent frame may be in another WebContents.
- if (node->IsMainFrame()) {
- auto* contents = WebContentsImpl::FromFrameTreeNode(node);
- if (GuestMode::IsCrossProcessFrameGuest(contents)) {
- int node_id = contents->GetOuterDelegateFrameTreeNodeId();
- if (node_id != FrameTreeNode::kFrameTreeNodeInvalidId)
- return FrameTreeNode::GloballyFindByID(node_id);
- } else if (auto* outer_contents = contents->GetOuterWebContents()) {
- return outer_contents->GetMainFrame()->frame_tree_node();
+ auto* contents = WebContentsImpl::FromFrameTreeNode(node);
+
+ if (node->IsMainFrame() && contents->GetOuterWebContents()) {
+ if (!GuestMode::IsCrossProcessFrameGuest(contents) &&
+ contents->GetBrowserPluginGuest() &&
+ contents->GetBrowserPluginGuest()->GetEmbedderFrame()) {
+ return contents->GetBrowserPluginGuest()
+ ->GetEmbedderFrame()
+ ->frame_tree_node();
+ } else {
+ return GetParent(FrameTreeNode::GloballyFindByID(
+ contents->GetOuterDelegateFrameTreeNodeId()));
}
}
-
return nullptr;
}
diff --git a/chromium/content/browser/font_unique_name_lookup/font_unique_name_browsertest.cc b/chromium/content/browser/font_unique_name_lookup/font_unique_name_browsertest.cc
index afef87c9e01..c79d06edd95 100644
--- a/chromium/content/browser/font_unique_name_lookup/font_unique_name_browsertest.cc
+++ b/chromium/content/browser/font_unique_name_lookup/font_unique_name_browsertest.cc
@@ -4,6 +4,7 @@
#include "base/stl_util.h"
#include "base/test/scoped_feature_list.h"
+#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "content/browser/devtools/protocol/devtools_protocol_test_support.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -131,6 +132,7 @@ class FontUniqueNameBrowserTest : public DevToolsProtocolTest {
#endif
void LoadAndWait(const std::string& url) {
+ base::ScopedAllowBlockingForTesting blocking_for_load;
ASSERT_TRUE(embedded_test_server()->Start());
TestNavigationObserver navigation_observer(
static_cast<WebContentsImpl*>(shell()->web_contents()));
diff --git a/chromium/content/browser/frame_host/DEPS b/chromium/content/browser/frame_host/DEPS
index 09569cb1402..3da57e57e31 100644
--- a/chromium/content/browser/frame_host/DEPS
+++ b/chromium/content/browser/frame_host/DEPS
@@ -20,4 +20,7 @@ specific_include_rules = {
"+content/browser/web_contents",
"+content/public/browser/web_contents_delegate.h",
],
+ "popup_menu_helper_mac.mm": [
+ "+content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h",
+ ]
}
diff --git a/chromium/content/browser/frame_host/back_forward_cache_metrics_browsertest.cc b/chromium/content/browser/frame_host/back_forward_cache_metrics_browsertest.cc
index 90ae4798caf..f5a279aabce 100644
--- a/chromium/content/browser/frame_host/back_forward_cache_metrics_browsertest.cc
+++ b/chromium/content/browser/frame_host/back_forward_cache_metrics_browsertest.cc
@@ -14,6 +14,7 @@
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
#include "net/dns/mock_host_resolver.h"
+#include "services/device/public/cpp/test/scoped_geolocation_overrider.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h"
@@ -22,12 +23,16 @@ namespace content {
namespace {
-constexpr int kPageShowFeature = static_cast<int>(
+constexpr uint64_t kPageShowFeature = static_cast<uint64_t>(
blink::scheduler::WebSchedulerTrackedFeature::kPageShowEventListener);
-constexpr int kHasScriptableFramesInMultipleTabsFeature =
- static_cast<int>(blink::scheduler::WebSchedulerTrackedFeature::
- kHasScriptableFramesInMultipleTabs);
+constexpr uint64_t kHasScriptableFramesInMultipleTabsFeature =
+ static_cast<uint64_t>(blink::scheduler::WebSchedulerTrackedFeature::
+ kHasScriptableFramesInMultipleTabs);
+
+constexpr uint64_t kRequestedGeolocationPermissionFeature =
+ static_cast<uint64_t>(blink::scheduler::WebSchedulerTrackedFeature::
+ kRequestedGeolocationPermission);
ukm::SourceId ToSourceId(int64_t navigation_id) {
return ukm::ConvertToSourceId(navigation_id,
@@ -80,6 +85,12 @@ std::vector<UkmMetrics> GetMetrics(ukm::TestUkmRecorder* recorder,
class BackForwardCacheMetricsBrowserTest : public ContentBrowserTest,
public WebContentsObserver {
+ public:
+ BackForwardCacheMetricsBrowserTest() {
+ geolocation_override_ =
+ std::make_unique<device::ScopedGeolocationOverrider>(1.0, 1.0);
+ }
+
protected:
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
@@ -92,8 +103,10 @@ class BackForwardCacheMetricsBrowserTest : public ContentBrowserTest,
navigation_ids_.push_back(navigation_handle->GetNavigationId());
}
- protected:
std::vector<int64_t> navigation_ids_;
+
+ private:
+ std::unique_ptr<device::ScopedGeolocationOverrider> geolocation_override_;
};
IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest, UKM) {
@@ -598,4 +611,21 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest,
id3, 1 << kHasScriptableFramesInMultipleTabsFeature, 0, 0}));
}
+IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest, Geolocation) {
+ const GURL url1(embedded_test_server()->GetURL("/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url1));
+
+ RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+ EXPECT_EQ("success", EvalJs(main_frame, R"(
+ new Promise(resolve => {
+ navigator.geolocation.getCurrentPosition(
+ resolve.bind(this, "success"),
+ resolve.bind(this, "failure"))
+ });
+ )"));
+ EXPECT_TRUE(main_frame->scheduler_tracked_features() &
+ (1 << kRequestedGeolocationPermissionFeature));
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/back_forward_cache_metrics_unittest.cc b/chromium/content/browser/frame_host/back_forward_cache_metrics_unittest.cc
index 8f8e8eb4fd7..7c229b9a942 100644
--- a/chromium/content/browser/frame_host/back_forward_cache_metrics_unittest.cc
+++ b/chromium/content/browser/frame_host/back_forward_cache_metrics_unittest.cc
@@ -30,6 +30,11 @@ class BackForwardCacheMetricsTest : public RenderViewHostImplTestHarness,
BackForwardCacheMetrics::OverrideTimeForTesting(&clock_);
}
+ void TearDown() override {
+ BackForwardCacheMetrics::OverrideTimeForTesting(nullptr);
+ RenderViewHostImplTestHarness::TearDown();
+ }
+
void DidStartNavigation(NavigationHandle* navigation_handle) override {
navigation_ids_.push_back(navigation_handle->GetNavigationId());
}
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 4c78d6507fa..cb10370e8a1 100644
--- a/chromium/content/browser/frame_host/blocked_scheme_navigation_browsertest.cc
+++ b/chromium/content/browser/frame_host/blocked_scheme_navigation_browsertest.cc
@@ -100,7 +100,7 @@ class BlockedURLWarningConsoleObserverDelegate : public WebContentsDelegate {
// WebContentsDelegate method:
bool DidAddMessageToConsole(WebContents* source,
- int32_t level,
+ blink::mojom::ConsoleMessageLevel log_level,
const base::string16& message,
int32_t line_no,
const base::string16& source_id) override {
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 ddffe8c11cb..481a73e8e5a 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
@@ -28,7 +28,6 @@
#include "content/public/common/use_zoom_for_dsf_policy.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "third_party/blink/public/platform/web_input_event.h"
-#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/gfx/geometry/dip_util.h"
@@ -153,8 +152,7 @@ void CrossProcessFrameConnector::SetView(RenderWidgetHostViewChildFrame* view) {
if (visibility_ != blink::mojom::FrameVisibility::kRenderedInViewport)
OnVisibilityChanged(visibility_);
FrameMsg_ViewChanged_Params params;
- if (!features::IsMultiProcessMash())
- params.frame_sink_id = view_->GetFrameSinkId();
+ params.frame_sink_id = view_->GetFrameSinkId();
frame_proxy_in_parent_renderer_->Send(new FrameMsg_ViewChanged(
frame_proxy_in_parent_renderer_->GetRoutingID(), params));
}
@@ -178,6 +176,10 @@ void CrossProcessFrameConnector::RenderProcessGone() {
frame_proxy_in_parent_renderer_->Send(new FrameMsg_ChildFrameProcessGone(
frame_proxy_in_parent_renderer_->GetRoutingID()));
+
+ auto* parent_view = GetParentRenderWidgetHostView();
+ if (parent_view && parent_view->host()->delegate())
+ parent_view->host()->delegate()->SubframeCrashed(visibility_);
}
void CrossProcessFrameConnector::FirstSurfaceActivation(
@@ -403,7 +405,7 @@ void CrossProcessFrameConnector::OnVisibilityChanged(
// Show/Hide on all the RenderWidgetHostViews (including this) one.
if (frame_proxy_in_parent_renderer_->frame_tree_node()
->render_manager()
- ->ForInnerDelegate()) {
+ ->IsMainFrameForInnerDelegate()) {
view_->host()->delegate()->OnRenderFrameProxyVisibilityChanged(visibility_);
return;
}
@@ -473,22 +475,6 @@ bool CrossProcessFrameConnector::IsHidden() const {
return visibility_ == blink::mojom::FrameVisibility::kNotRendered;
}
-#if defined(USE_AURA)
-void CrossProcessFrameConnector::EmbedRendererWindowTreeClientInParent(
- ws::mojom::WindowTreeClientPtr window_tree_client) {
- RenderWidgetHostViewBase* root = GetRootRenderWidgetHostView();
- RenderWidgetHostViewBase* parent = GetParentRenderWidgetHostView();
- if (!parent || !root)
- return;
- const int frame_routing_id = frame_proxy_in_parent_renderer_->GetRoutingID();
- parent->EmbedChildFrameRendererWindowTreeClient(
- root, frame_routing_id, std::move(window_tree_client));
- frame_proxy_in_parent_renderer_->SetDestructionCallback(
- base::BindOnce(&RenderWidgetHostViewBase::OnChildFrameDestroyed,
- parent->GetWeakPtr(), frame_routing_id));
-}
-#endif
-
void CrossProcessFrameConnector::DidUpdateVisualProperties(
const cc::RenderFrameMetadata& metadata) {
frame_proxy_in_parent_renderer_->Send(new FrameMsg_DidUpdateVisualProperties(
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 e1f4c6f4630..12b07781f75 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.h
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.h
@@ -111,10 +111,6 @@ class CONTENT_EXPORT CrossProcessFrameConnector
bool IsHidden() const override;
bool IsThrottled() const override;
bool IsSubtreeThrottled() const override;
-#if defined(USE_AURA)
- void EmbedRendererWindowTreeClientInParent(
- ws::mojom::WindowTreeClientPtr window_tree_client) override;
-#endif
void DidUpdateVisualProperties(
const cc::RenderFrameMetadata& metadata) override;
diff --git a/chromium/content/browser/frame_host/debug_urls.cc b/chromium/content/browser/frame_host/debug_urls.cc
index d47b0305167..59396b7f26e 100644
--- a/chromium/content/browser/frame_host/debug_urls.cc
+++ b/chromium/content/browser/frame_host/debug_urls.cc
@@ -172,7 +172,7 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
}
if (url == kChromeUIGpuCleanURL) {
- GpuProcessHost::CallOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED,
false /* force_create */,
base::Bind([](GpuProcessHost* host) {
if (host)
@@ -182,7 +182,7 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
}
if (url == kChromeUIGpuCrashURL) {
- GpuProcessHost::CallOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED,
false /* force_create */,
base::Bind([](GpuProcessHost* host) {
if (host)
@@ -193,7 +193,7 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
#if defined(OS_ANDROID)
if (url == kChromeUIGpuJavaCrashURL) {
- GpuProcessHost::CallOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED,
false /* force_create */,
base::Bind([](GpuProcessHost* host) {
if (host)
@@ -204,7 +204,7 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
#endif
if (url == kChromeUIGpuHangURL) {
- GpuProcessHost::CallOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED,
false /* force_create */,
base::Bind([](GpuProcessHost* host) {
if (host)
diff --git a/chromium/content/browser/frame_host/frame_tree.cc b/chromium/content/browser/frame_host/frame_tree.cc
index 664d2c20408..f68548fd04a 100644
--- a/chromium/content/browser/frame_host/frame_tree.cc
+++ b/chromium/content/browser/frame_host/frame_tree.cc
@@ -408,6 +408,15 @@ void FrameTree::ReleaseRenderViewHostRef(RenderViewHostImpl* rvh) {
render_view_host_map_.erase(it);
}
+void FrameTree::FrameUnloading(FrameTreeNode* frame) {
+ if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
+ focused_frame_tree_node_id_ = FrameTreeNode::kFrameTreeNodeInvalidId;
+
+ // Ensure frames that are about to be deleted aren't visible from the other
+ // processes anymore.
+ frame->render_manager()->ResetProxyHosts();
+}
+
void FrameTree::FrameRemoved(FrameTreeNode* frame) {
if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
focused_frame_tree_node_id_ = FrameTreeNode::kFrameTreeNodeInvalidId;
diff --git a/chromium/content/browser/frame_host/frame_tree.h b/chromium/content/browser/frame_host/frame_tree.h
index ccccd552d62..646b2f4b2bf 100644
--- a/chromium/content/browser/frame_host/frame_tree.h
+++ b/chromium/content/browser/frame_host/frame_tree.h
@@ -222,6 +222,10 @@ class CONTENT_EXPORT FrameTree {
void AddRenderViewHostRef(RenderViewHostImpl* render_view_host);
void ReleaseRenderViewHostRef(RenderViewHostImpl* render_view_host);
+ // This is called when the frame is about to be removed and started to run
+ // unload handlers.
+ void FrameUnloading(FrameTreeNode* frame);
+
// This is only meant to be called by FrameTreeNode. Triggers calling
// the listener installed by SetFrameRemoveListener.
void FrameRemoved(FrameTreeNode* frame);
diff --git a/chromium/content/browser/frame_host/frame_tree_browsertest.cc b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
index c7fcb2d9c49..0be281e17b5 100644
--- a/chromium/content/browser/frame_host/frame_tree_browsertest.cc
+++ b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
@@ -1300,9 +1300,7 @@ class TransferUserActivationFrameTreeBrowserTest : public ContentBrowserTest {
};
IN_PROC_BROWSER_TEST_F(TransferUserActivationFrameTreeBrowserTest,
- PostMessageTransferActivation) {
- // TODO(lanwei): Also test transferring user activation in the frame trees
- // for the same origin case a(b,b). crbug.com/928838.
+ PostMessageTransferActivationCrossOrigin) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b,c)"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1378,6 +1376,71 @@ IN_PROC_BROWSER_TEST_F(TransferUserActivationFrameTreeBrowserTest,
EXPECT_TRUE(child2->HasBeenActivated());
EXPECT_TRUE(child2->HasTransientUserActivation());
}
+
+IN_PROC_BROWSER_TEST_F(TransferUserActivationFrameTreeBrowserTest,
+ PostMessageTransferActivationSameOrigin) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(b))"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ WebContentsImpl* contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ FrameTreeNode* root = contents->GetFrameTree()->root();
+ FrameTreeNode* child1 = root->child_at(0);
+ FrameTreeNode* child2 = child1->child_at(0);
+ EXPECT_FALSE(root->HasBeenActivated());
+ EXPECT_FALSE(root->HasTransientUserActivation());
+ EXPECT_FALSE(child1->HasBeenActivated());
+ EXPECT_FALSE(child1->HasTransientUserActivation());
+ EXPECT_FALSE(child2->HasBeenActivated());
+ EXPECT_FALSE(child2->HasTransientUserActivation());
+
+ // Activate the root frame and transfer the user activation state from root
+ // to child1.
+ std::string message_event_listener =
+ "window.addEventListener('message', function(event) {\n"
+ " domAutomationController.send('done-' + event.data);\n"
+ "});";
+ EXPECT_TRUE(ExecuteScript(shell(), ""));
+ EXPECT_TRUE(ExecuteScriptWithoutUserGesture(child1->current_frame_host(),
+ message_event_listener));
+ DOMMessageQueue msg_queue;
+ std::string actual_test_reply;
+ EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
+ shell(),
+ "window.frames[0].postMessage('Hello', "
+ "{targetOrigin: '*', transferUserActivation: true})"));
+ while (msg_queue.WaitForMessage(&actual_test_reply)) {
+ if (actual_test_reply == "\"done-Hello\"")
+ break;
+ }
+ EXPECT_FALSE(root->HasBeenActivated());
+ EXPECT_FALSE(root->HasTransientUserActivation());
+ EXPECT_TRUE(child1->HasBeenActivated());
+ EXPECT_TRUE(child1->HasTransientUserActivation());
+ EXPECT_FALSE(child2->HasBeenActivated());
+ EXPECT_FALSE(child2->HasTransientUserActivation());
+
+ // Post a message from child1 to its child child2 in the same origin with
+ // |transferUserActivation| true to transfer the user activation state from
+ // one node to its child node in the frame tree.
+ EXPECT_TRUE(ExecuteScriptWithoutUserGesture(child2->current_frame_host(),
+ message_event_listener));
+ EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
+ child1->current_frame_host(),
+ "window.frames[0].postMessage('Hey', "
+ "{targetOrigin: '*', transferUserActivation: true})"));
+ while (msg_queue.WaitForMessage(&actual_test_reply)) {
+ if (actual_test_reply == "\"done-Hey\"")
+ break;
+ }
+ EXPECT_FALSE(root->HasBeenActivated());
+ EXPECT_FALSE(root->HasTransientUserActivation());
+ EXPECT_FALSE(child1->HasBeenActivated());
+ EXPECT_FALSE(child1->HasTransientUserActivation());
+ EXPECT_TRUE(child2->HasBeenActivated());
+ EXPECT_TRUE(child2->HasTransientUserActivation());
+}
#endif
} // namespace content
diff --git a/chromium/content/browser/frame_host/frame_tree_node.cc b/chromium/content/browser/frame_host/frame_tree_node.cc
index fff13c33952..424deca67bf 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.cc
+++ b/chromium/content/browser/frame_host/frame_tree_node.cc
@@ -508,13 +508,13 @@ void FrameTreeNode::DidStopLoading() {
// the WebContents of the load progress change.
DidChangeLoadProgress(kLoadingProgressDone);
+ // Notify the RenderFrameHostManager of the event.
+ render_manager()->OnDidStopLoading();
+
// Notify the WebContents.
if (!frame_tree_->IsLoading())
navigator()->GetDelegate()->DidStopLoading();
- // Notify the RenderFrameHostManager of the event.
- render_manager()->OnDidStopLoading();
-
// Notify accessibility that the user is no longer trying to load or
// reload a page.
BrowserAccessibilityManager* manager =
diff --git a/chromium/content/browser/frame_host/frame_tree_unittest.cc b/chromium/content/browser/frame_host/frame_tree_unittest.cc
index bb017951772..90167b043d0 100644
--- a/chromium/content/browser/frame_host/frame_tree_unittest.cc
+++ b/chromium/content/browser/frame_host/frame_tree_unittest.cc
@@ -552,8 +552,8 @@ TEST_F(FrameTreeTest, ObserverWalksTreeAfterCrash) {
main_test_rfh()->GetProcess()->SimulateCrash();
EXPECT_EQ(
"RenderProcessGone -> 3*: [22*: [], 23*: []]\n"
- "RenderFrameDeleted(23) -> 3*: [22*: [], 23*: []]\n"
- "RenderFrameDeleted(22) -> 3*: [22*: [], 23*: []]\n"
+ "RenderFrameDeleted(23) -> 3*: []\n"
+ "RenderFrameDeleted(22) -> 3*: []\n"
"RenderFrameDeleted(3) -> 3*: []",
activity.GetLog());
}
diff --git a/chromium/content/browser/frame_host/input/OWNERS b/chromium/content/browser/frame_host/input/OWNERS
index 86bfa17ec3d..b560ee2f06f 100644
--- a/chromium/content/browser/frame_host/input/OWNERS
+++ b/chromium/content/browser/frame_host/input/OWNERS
@@ -1,5 +1,6 @@
dtapuska@chromium.org
tdresser@chromium.org
+bokan@chromium.org
# TEAM: input-dev@chromium.org
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.cc b/chromium/content/browser/frame_host/interstitial_page_impl.cc
index dbc6281ef73..106239c65d0 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.cc
@@ -484,7 +484,7 @@ RenderViewHostDelegateView* InterstitialPageImpl::GetDelegateView() {
return rvh_delegate_view_.get();
}
-WebContents* InterstitialPageImpl::GetWebContents() const {
+WebContents* InterstitialPageImpl::GetWebContents() {
return web_contents();
}
@@ -762,7 +762,7 @@ RenderWidgetHostView* InterstitialPageImpl::GetView() {
return render_view_host_->GetWidget()->GetView();
}
-RenderFrameHost* InterstitialPageImpl::GetMainFrame() const {
+RenderFrameHost* InterstitialPageImpl::GetMainFrame() {
if (!render_view_host_)
return nullptr;
return render_view_host_->GetMainFrame();
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.h b/chromium/content/browser/frame_host/interstitial_page_impl.h
index 77bee15f1eb..c2b1d79fd89 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.h
@@ -71,8 +71,8 @@ class CONTENT_EXPORT InterstitialPageImpl : public InterstitialPage,
void Hide() override;
void DontProceed() override;
void Proceed() override;
- WebContents* GetWebContents() const override;
- RenderFrameHost* GetMainFrame() const override;
+ WebContents* GetWebContents() override;
+ RenderFrameHost* GetMainFrame() override;
InterstitialPageDelegate* GetDelegateForTesting() override;
void DontCreateViewForTesting() override;
void SetSize(const gfx::Size& size) override;
diff --git a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc
index 3355fdd0161..ef977b6ee77 100644
--- a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc
@@ -37,8 +37,8 @@ void InterstitialPageNavigatorImpl::DidNavigate(
if (!enabled_)
return;
- navigation_request->navigation_handle()->DidCommitNavigation(
- input_params, true, false, GURL(), NAVIGATION_TYPE_NEW_PAGE);
+ navigation_request->DidCommitNavigation(input_params, true, false, GURL(),
+ NAVIGATION_TYPE_NEW_PAGE);
navigation_request.reset();
// TODO(nasko): Move implementation here, but for the time being call out
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.cc b/chromium/content/browser/frame_host/navigation_controller_android.cc
index 519b640b714..3c08d560080 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_android.cc
@@ -389,6 +389,18 @@ NavigationControllerAndroid::GetEntryAtIndex(JNIEnv* env,
}
base::android::ScopedJavaLocalRef<jobject>
+NavigationControllerAndroid::GetVisibleEntry(JNIEnv* env,
+ const JavaParamRef<jobject>& obj) {
+ content::NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
+
+ if (!entry)
+ return base::android::ScopedJavaLocalRef<jobject>();
+
+ return JNI_NavigationControllerImpl_CreateJavaNavigationEntry(env, entry,
+ /*index=*/-1);
+}
+
+base::android::ScopedJavaLocalRef<jobject>
NavigationControllerAndroid::GetPendingEntry(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
content::NavigationEntry* entry = navigation_controller_->GetPendingEntry();
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.h b/chromium/content/browser/frame_host/navigation_controller_android.h
index 034b76197d3..7f01993722c 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.h
+++ b/chromium/content/browser/frame_host/navigation_controller_android.h
@@ -96,6 +96,9 @@ class CONTENT_EXPORT NavigationControllerAndroid {
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
int index);
+ base::android::ScopedJavaLocalRef<jobject> GetVisibleEntry(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& /* obj */);
base::android::ScopedJavaLocalRef<jobject> GetPendingEntry(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& /* obj */);
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.cc b/chromium/content/browser/frame_host/navigation_controller_impl.cc
index 25f8796f96b..f50c1283c19 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.cc
@@ -2137,7 +2137,8 @@ void NavigationControllerImpl::NotifyUserActivation() {
bool NavigationControllerImpl::StartHistoryNavigationInNewSubframe(
RenderFrameHostImpl* render_frame_host,
- const GURL& default_url) {
+ const GURL& default_url,
+ mojom::NavigationClientAssociatedPtrInfo* navigation_client) {
NavigationEntryImpl* entry =
GetEntryWithUniqueID(render_frame_host->nav_entry_id());
if (!entry)
@@ -2176,6 +2177,9 @@ bool NavigationControllerImpl::StartHistoryNavigationInNewSubframe(
if (!request)
return false;
+ request->SetNavigationClient(std::move(*navigation_client),
+ render_frame_host->GetSiteInstance()->GetId());
+
render_frame_host->frame_tree_node()->navigator()->Navigate(
std::move(request), ReloadType::NONE, RestoreType::NONE);
@@ -2193,7 +2197,7 @@ void NavigationControllerImpl::GoToOffsetInSandboxedFrame(
void NavigationControllerImpl::NavigateFromFrameProxy(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
- const url::Origin& initiator_origin,
+ const base::Optional<url::Origin>& initiator_origin,
bool is_renderer_initiated,
SiteInstance* source_site_instance,
const Referrer& referrer,
@@ -2204,6 +2208,9 @@ void NavigationControllerImpl::NavigateFromFrameProxy(
scoped_refptr<network::ResourceRequestBody> post_body,
const std::string& extra_headers,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
+ if (is_renderer_initiated)
+ DCHECK(initiator_origin.has_value());
+
FrameTreeNode* node = render_frame_host->frame_tree_node();
// Create a NavigationEntry for the transfer, without making it the pending
@@ -2392,8 +2399,12 @@ bool NavigationControllerImpl::NeedsReload() {
}
void NavigationControllerImpl::SetNeedsReload() {
+ SetNeedsReload(NeedsReloadType::kRequestedByClient);
+}
+
+void NavigationControllerImpl::SetNeedsReload(NeedsReloadType type) {
needs_reload_ = true;
- needs_reload_type_ = NeedsReloadType::kRequestedByClient;
+ needs_reload_type_ = type;
if (last_committed_entry_index_ != -1) {
entries_[last_committed_entry_index_]->SetTransitionType(
@@ -3103,15 +3114,15 @@ NavigationControllerImpl::CreateNavigationRequestFromLoadParams(
params.load_type == LOAD_TYPE_HTTP_POST ? "POST" : "GET",
params.post_data, base::Optional<SourceLocation>(),
params.started_from_context_menu, has_user_gesture, InitiatorCSPInfo(),
- params.href_translate, params.input_start);
+ std::vector<int>(), params.href_translate,
+ false /* is_history_navigation_in_new_child_frame */, params.input_start);
CommitNavigationParams commit_params(
frame_entry->committed_origin(), override_user_agent,
params.redirect_chain, common_params.url, common_params.method,
params.can_load_local_resources, frame_entry->page_state(),
- entry->GetUniqueID(), false /* is_history_navigation_in_new_child */,
- entry->GetSubframeUniqueNames(node), true /* intended_as_new_entry */,
- -1 /* pending_history_list_offset */,
+ entry->GetUniqueID(), entry->GetSubframeUniqueNames(node),
+ true /* intended_as_new_entry */, -1 /* pending_history_list_offset */,
params.should_clear_history_list ? -1 : GetLastCommittedEntryIndex(),
params.should_clear_history_list ? 0 : GetEntryCount(),
is_view_source_mode, params.should_clear_history_list);
@@ -3143,7 +3154,7 @@ NavigationControllerImpl::CreateNavigationRequestFromEntry(
FrameNavigationEntry* frame_entry,
ReloadType reload_type,
bool is_same_document_history_load,
- bool is_history_navigation_in_new_child) {
+ bool is_history_navigation_in_new_child_frame) {
GURL dest_url = frame_entry->url();
base::Optional<url::Origin> origin_to_commit =
frame_entry->committed_origin();
@@ -3218,13 +3229,14 @@ NavigationControllerImpl::CreateNavigationRequestFromEntry(
CommonNavigationParams common_params = entry->ConstructCommonNavigationParams(
*frame_entry, request_body, dest_url, dest_referrer, navigation_type,
previews_state, navigation_start, base::TimeTicks() /* input_start */);
+ common_params.is_history_navigation_in_new_child_frame =
+ is_history_navigation_in_new_child_frame;
// TODO(clamy): |intended_as_new_entry| below should always be false once
// Reload no longer leads to this being called for a pending NavigationEntry
// of index -1.
CommitNavigationParams commit_params = entry->ConstructCommitNavigationParams(
*frame_entry, common_params.url, origin_to_commit, common_params.method,
- is_history_navigation_in_new_child,
entry->GetSubframeUniqueNames(frame_tree_node),
GetPendingEntryIndex() == -1 /* intended_as_new_entry */,
GetIndexOfEntry(entry), GetLastCommittedEntryIndex(), GetEntryCount());
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.h b/chromium/content/browser/frame_host/navigation_controller_impl.h
index e14e48f00a9..949174415fd 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.h
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.h
@@ -14,6 +14,7 @@
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "base/optional.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/frame_host/back_forward_cache.h"
@@ -99,7 +100,8 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
// navigation to |default_url| should be done instead.
bool StartHistoryNavigationInNewSubframe(
RenderFrameHostImpl* render_frame_host,
- const GURL& default_url);
+ const GURL& default_url,
+ mojom::NavigationClientAssociatedPtrInfo* navigation_client);
// Navigates to a specified offset from the "current entry". Currently records
// a histogram indicating whether the session history navigation would only
@@ -112,7 +114,7 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
void NavigateFromFrameProxy(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
- const url::Origin& initiator_origin,
+ const base::Optional<url::Origin>& initiator_origin,
bool is_renderer_initiated,
SiteInstance* source_site_instance,
const Referrer& referrer,
@@ -147,6 +149,21 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
return delegate_;
}
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ enum class NeedsReloadType {
+ kRequestedByClient = 0,
+ kRestoreSession = 1,
+ kCopyStateFrom = 2,
+ kCrashedSubframe = 3,
+ kMaxValue = kCrashedSubframe
+ };
+
+ // Request a reload to happen when activated. Same as the public
+ // SetNeedsReload(), but takes in a |type| which specifies why the reload is
+ // being requested.
+ void SetNeedsReload(NeedsReloadType type);
+
// For use by WebContentsImpl ------------------------------------------------
// Allow renderer-initiated navigations to create a pending entry when the
@@ -256,15 +273,6 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
FRIEND_TEST_ALL_PREFIXES(TimeSmoother, ManyDuplicates);
FRIEND_TEST_ALL_PREFIXES(TimeSmoother, ClockBackwardsJump);
- // These values are persisted to logs. Entries should not be renumbered and
- // numeric values should never be reused.
- enum class NeedsReloadType {
- kRequestedByClient = 0,
- kRestoreSession = 1,
- kCopyStateFrom = 2,
- kMaxValue = kCopyStateFrom
- };
-
// Helper class to smooth out runs of duplicate timestamps while still
// allowing time to jump backwards.
class CONTENT_EXPORT TimeSmoother {
@@ -353,7 +361,7 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
FrameNavigationEntry* frame_entry,
ReloadType reload_type,
bool is_same_document_history_load,
- bool is_history_navigation_in_new_child);
+ bool is_history_navigation_in_new_child_frame);
// Returns whether there is a pending NavigationEntry whose unique ID matches
// the given NavigationHandle's pending_nav_entry_id.
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 4029f48e31e..296fe15710c 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -146,8 +146,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, LoadDataWithBaseURL) {
// without an origin lock]). Therefore, skip the test in --site-per-process
// mode to avoid renderer kills which won't happen in practice as described
// above.
- // TODO(lukasza): https://crbug.com/614463: Consider enabling this test
- // once WebView guests support OOPIFs and/or origin locks.
+ //
+ // TODO(https://crbug.com/962643): Consider enabling this test once Android
+ // Webview or WebView guests support OOPIFs and/or origin locks.
if (AreAllSitesIsolatedForTesting())
return;
@@ -209,8 +210,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// without an origin lock]). Therefore, skip the test in --site-per-process
// mode to avoid renderer kills which won't happen in practice as described
// above.
- // TODO(lukasza): https://crbug.com/614463: Consider enabling this test
- // once WebView guests support OOPIFs and/or origin locks.
+ //
+ // TODO(https://crbug.com/962643): Consider enabling this test once Android
+ // Webview or WebView guests support OOPIFs and/or origin locks.
if (AreAllSitesIsolatedForTesting())
return;
@@ -315,6 +317,18 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
#if defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadDataWithInvalidBaseURL) {
+ // LoadDataWithBaseURL is never subject to --site-per-process policy today
+ // (this API is only used by Android WebView [where OOPIFs have not shipped
+ // yet] and GuestView cases [which always hosts guests inside a renderer
+ // without an origin lock]). Therefore, skip the test in --site-per-process
+ // mode to avoid renderer kills which won't happen in practice as described
+ // above.
+ //
+ // TODO(https://crbug.com/962643): Consider enabling this test once Android
+ // Webview or WebView guests support OOPIFs and/or origin locks.
+ if (AreAllSitesIsolatedForTesting())
+ return;
+
const GURL base_url("http://"); // Invalid.
const GURL history_url("http://historyurl");
const std::string title = "invalid_base_url";
@@ -348,8 +362,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// without an origin lock]). Therefore, skip the test in --site-per-process
// mode to avoid renderer kills which won't happen in practice as described
// above.
- // TODO(lukasza): https://crbug.com/614463: Consider enabling this test
- // once WebView guests support OOPIFs and/or origin locks.
+ //
+ // TODO(https://crbug.com/962643): Consider enabling this test once Android
+ // Webview or WebView guests support OOPIFs and/or origin locks.
if (AreAllSitesIsolatedForTesting())
return;
@@ -401,8 +416,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// without an origin lock]). Therefore, skip the test in --site-per-process
// mode to avoid renderer kills which won't happen in practice as described
// above.
- // TODO(lukasza): https://crbug.com/614463: Consider enabling this test
- // once WebView guests support OOPIFs and/or origin locks.
+ //
+ // TODO(https://crbug.com/962643): Consider enabling this test once Android
+ // Webview or WebView guests support OOPIFs and/or origin locks.
if (AreAllSitesIsolatedForTesting())
return;
@@ -770,8 +786,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// without an origin lock]). Therefore, skip the test in --site-per-process
// mode to avoid renderer kills which won't happen in practice as described
// above.
- // TODO(lukasza): https://crbug.com/614463: Consider enabling this test
- // once WebView guests support OOPIFs and/or origin locks.
+ //
+ // TODO(https://crbug.com/962643): Consider enabling this test once Android
+ // Webview or WebView guests support OOPIFs and/or origin locks.
if (AreAllSitesIsolatedForTesting())
return;
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 8ef7d204ca8..0b40d953efe 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -82,12 +82,6 @@ bool DoImagesMatch(const gfx::Image& a, const gfx::Image& b) {
a_bitmap.computeByteSize()) == 0;
}
-int64_t GenerateSequenceNumber() {
- // Based on how Blink generates sequence numbers.
- static int64_t next_number = base::Time::Now().ToDoubleT() * 1000000;
- return ++next_number;
-}
-
} // namespace
namespace content {
@@ -430,15 +424,11 @@ TEST_F(NavigationControllerTestWithBrowserSideNavigation,
std::string());
EXPECT_EQ(url_2, controller.GetVisibleEntry()->GetURL());
- // The DidFailProvsionalLoad IPC is received from the current RFH that is
- // committing an error page. This should not reset the pending entry for the
- // new ongoing navigation.
- FrameHostMsg_DidFailProvisionalLoadWithError_Params error;
- error.error_code = net::ERR_TIMED_OUT;
- error.url = url_1;
- main_test_rfh()->OnMessageReceived(
- FrameHostMsg_DidFailProvisionalLoadWithError(
- main_test_rfh()->GetRoutingID(), error));
+ // The DidFailProvsionalLoad mojo call is received from the current RFH that
+ // is committing an error page. This should not reset the pending entry for
+ // the new ongoing navigation.
+ main_test_rfh()->DidFailProvisionalLoadWithError(url_1, net::ERR_TIMED_OUT,
+ base::string16(), false);
EXPECT_EQ(url_2, controller.GetVisibleEntry()->GetURL());
}
@@ -785,19 +775,10 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage_DifferentMethod) {
const GURL url1("http://foo1");
- controller.LoadURL(
- url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.nav_entry_id = controller.GetPendingEntry()->GetUniqueID();
- params.did_create_new_entry = true;
- params.url = url1;
- params.transition = ui::PAGE_TRANSITION_TYPED;
- params.method = "POST";
- params.post_id = 123;
- params.page_state =
- PageState::CreateForTesting(url1, false, nullptr, nullptr);
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigateWithParams(&params, false);
+ auto navigation1 =
+ NavigationSimulatorImpl::CreateBrowserInitiated(url1, contents());
+ navigation1->SetIsPostWithId(123);
+ navigation1->Commit();
// The post data should be visible.
NavigationEntry* entry = controller.GetVisibleEntry();
@@ -805,19 +786,17 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage_DifferentMethod) {
EXPECT_TRUE(entry->GetHasPostData());
EXPECT_EQ(entry->GetPostID(), 123);
- controller.LoadURL(
- url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigateWithTransition(
- controller.GetPendingEntry()->GetUniqueID(),
- false, url1, ui::PAGE_TRANSITION_TYPED);
+ auto navigation2 =
+ NavigationSimulatorImpl::CreateBrowserInitiated(url1, contents());
+ navigation2->set_did_create_new_entry(false);
+ navigation2->Commit();
// We should not have produced a new session history entry.
ASSERT_EQ(controller.GetVisibleEntry(), entry);
// The post data should have been cleared due to the GET.
EXPECT_FALSE(entry->GetHasPostData());
- EXPECT_EQ(entry->GetPostID(), 0);
+ EXPECT_EQ(entry->GetPostID(), -1);
}
// Tests loading a URL but discarding it before the load commits.
@@ -1135,14 +1114,8 @@ TEST_F(NavigationControllerTest, LoadURL_AbortDoesntCancelPending) {
// It may abort before committing, if it's a download or due to a stop or
// a new navigation from the user.
- FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
- params.error_code = net::ERR_ABORTED;
- params.error_description = base::string16();
- params.url = kNewURL;
- params.showing_repost_interstitial = false;
- main_test_rfh()->OnMessageReceived(
- FrameHostMsg_DidFailProvisionalLoadWithError(0, // routing_id
- params));
+ main_test_rfh()->DidFailProvisionalLoadWithError(kNewURL, net::ERR_ABORTED,
+ base::string16(), false);
// This should not clear the pending entry or notify of a navigation state
// change, so that we keep displaying kNewURL (until the user clears it).
@@ -1468,6 +1441,7 @@ TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {
// Fake a commit response.
navigation->set_should_replace_current_entry(true);
+ navigation->Commit();
// Certain values that are only used for pending entries get reset after
// commit.
@@ -2189,69 +2163,27 @@ TEST_F(NavigationControllerTest, BackSubframe) {
blink::WebTreeScopeType::kDocument, std::string(), unique_name, false,
base::UnguessableToken::Create(), blink::FramePolicy(),
FrameOwnerProperties(), blink::FrameOwnerElementType::kIframe);
- TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
- contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
- RenderFrameHostManager* subframe_rfhm =
- subframe->frame_tree_node()->render_manager();
+ FrameTreeNode* subframe = contents()->GetFrameTree()->root()->child_at(0);
+ TestRenderFrameHost* subframe_rfh =
+ static_cast<TestRenderFrameHost*>(subframe->current_frame_host());
const GURL subframe_url("http://foo1/subframe");
- // Compute the sequence number assigned by Blink.
- int64_t item_sequence_number1 = GenerateSequenceNumber();
- int64_t document_sequence_number1 = GenerateSequenceNumber();
-
- {
- FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.nav_entry_id = 0;
- params.did_create_new_entry = false;
- params.url = subframe_url;
- params.origin = url::Origin::Create(subframe_url);
- params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
- params.should_update_history = false;
- params.gesture = NavigationGestureUser;
- params.method = "GET";
- params.page_state = PageState::CreateForTestingWithSequenceNumbers(
- subframe_url, item_sequence_number1, document_sequence_number1);
- params.item_sequence_number = item_sequence_number1;
- params.document_sequence_number = document_sequence_number1;
-
- // Navigating should do nothing.
- subframe->SendRendererInitiatedNavigationRequest(subframe_url, false);
- subframe->PrepareForCommit();
- subframe->SendNavigateWithParams(&params, false);
+ // Navigating should do nothing.
+ auto navigation1 =
+ NavigationSimulator::CreateRendererInitiated(subframe_url, subframe_rfh);
+ navigation1->SetTransition(ui::PAGE_TRANSITION_AUTO_SUBFRAME);
+ navigation1->Commit();
- // We notify of a PageState update here rather than during UpdateState for
- // auto subframe navigations.
- EXPECT_EQ(1u, navigation_entry_changed_counter_);
- }
+ // We notify of a PageState update here rather than during UpdateState for
+ // auto subframe navigations.
+ EXPECT_EQ(1u, navigation_entry_changed_counter_);
- // First manual subframe navigation.
+ // First manual subframe_rfh navigation.
const GURL url2("http://foo2");
- int64_t item_sequence_number2 = GenerateSequenceNumber();
- int64_t document_sequence_number2 = GenerateSequenceNumber();
- FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.nav_entry_id = 0;
- params.did_create_new_entry = true;
- params.url = url2;
- params.origin = url::Origin::Create(url2);
- params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
- params.should_update_history = false;
- params.gesture = NavigationGestureUser;
- params.method = "GET";
- params.page_state = PageState::CreateForTestingWithSequenceNumbers(
- url2, item_sequence_number2, document_sequence_number2);
- params.item_sequence_number = item_sequence_number2;
- params.document_sequence_number = document_sequence_number2;
-
- // This should generate a new entry.
- subframe->SendRendererInitiatedNavigationRequest(url2, false);
- subframe->PrepareForCommit();
- // If the navigation is cross-process, the commit comes from the speculative
- // RenderFrame.
- if (subframe_rfhm->speculative_frame_host()) {
- subframe = static_cast<TestRenderFrameHost*>(
- subframe_rfhm->speculative_frame_host());
- }
- subframe->SendNavigateWithParams(&params, false);
+ auto navigation2 =
+ NavigationSimulator::CreateRendererInitiated(url2, subframe_rfh);
+ navigation2->SetTransition(ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
+ navigation2->Commit();
NavigationEntryImpl* entry2 = controller.GetLastCommittedEntry();
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -2263,24 +2195,12 @@ TEST_F(NavigationControllerTest, BackSubframe) {
// Second manual subframe navigation should also make a new entry.
const GURL url3("http://foo3");
- int64_t item_sequence_number3 = GenerateSequenceNumber();
- int64_t document_sequence_number3 = GenerateSequenceNumber();
- params.nav_entry_id = 0;
- params.did_create_new_entry = true;
- params.url = url3;
- params.origin = url::Origin::Create(url3);
- params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
- params.item_sequence_number = item_sequence_number3;
- params.document_sequence_number = document_sequence_number3;
- params.page_state = PageState::CreateForTestingWithSequenceNumbers(
- url3, item_sequence_number3, document_sequence_number3);
- subframe->SendRendererInitiatedNavigationRequest(url3, false);
- subframe->PrepareForCommit();
- if (subframe_rfhm->speculative_frame_host()) {
- subframe = static_cast<TestRenderFrameHost*>(
- subframe_rfhm->speculative_frame_host());
- }
- subframe->SendNavigateWithParams(&params, false);
+ subframe_rfh =
+ static_cast<TestRenderFrameHost*>(subframe->current_frame_host());
+ auto navigation3 =
+ NavigationSimulator::CreateRendererInitiated(url3, subframe_rfh);
+ navigation3->SetTransition(ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
+ navigation3->Commit();
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
NavigationEntryImpl* entry3 = controller.GetLastCommittedEntry();
@@ -2293,21 +2213,10 @@ TEST_F(NavigationControllerTest, BackSubframe) {
// Go back one.
controller.GoToOffset(-1);
- params.nav_entry_id = entry2->GetUniqueID();
- params.did_create_new_entry = false;
- params.url = url2;
- params.origin = url::Origin::Create(url2);
- params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
- params.page_state = PageState::CreateForTestingWithSequenceNumbers(
- url2, item_sequence_number2, document_sequence_number2);
- params.item_sequence_number = item_sequence_number2;
- params.document_sequence_number = document_sequence_number2;
- subframe->PrepareForCommit();
- if (subframe_rfhm->speculative_frame_host()) {
- subframe = static_cast<TestRenderFrameHost*>(
- subframe_rfhm->speculative_frame_host());
- }
- subframe->SendNavigateWithParams(&params, false);
+ auto back_navigation1 =
+ NavigationSimulatorImpl::CreateFromPendingInFrame(subframe);
+ back_navigation1->SetTransition(ui::PAGE_TRANSITION_AUTO_SUBFRAME);
+ back_navigation1->Commit();
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(entry2, controller.GetLastCommittedEntry());
@@ -2318,21 +2227,10 @@ TEST_F(NavigationControllerTest, BackSubframe) {
// Go back one more.
controller.GoToOffset(-1);
- params.nav_entry_id = entry1->GetUniqueID();
- params.did_create_new_entry = false;
- params.url = subframe_url;
- params.origin = url::Origin::Create(subframe_url);
- params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
- params.page_state = PageState::CreateForTestingWithSequenceNumbers(
- subframe_url, item_sequence_number1, document_sequence_number1);
- params.item_sequence_number = item_sequence_number1;
- params.document_sequence_number = document_sequence_number1;
- subframe->PrepareForCommit();
- if (subframe_rfhm->speculative_frame_host()) {
- subframe = static_cast<TestRenderFrameHost*>(
- subframe_rfhm->speculative_frame_host());
- }
- subframe->SendNavigateWithParams(&params, false);
+ auto back_navigation2 =
+ NavigationSimulatorImpl::CreateFromPendingInFrame(subframe);
+ back_navigation2->SetTransition(ui::PAGE_TRANSITION_AUTO_SUBFRAME);
+ back_navigation2->Commit();
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(entry1, controller.GetLastCommittedEntry());
@@ -2381,27 +2279,11 @@ TEST_F(NavigationControllerTest, SameDocument) {
// Ensure renderer-initiated main frame navigation to same url replaces the
// current entry. This behavior differs from the browser-initiated case.
- FrameHostMsg_DidCommitProvisionalLoad_Params self_params;
- self_params.nav_entry_id = 0;
- self_params.did_create_new_entry = true;
- self_params.should_replace_current_entry = true;
- self_params.url = url1;
- self_params.origin = url::Origin::Create(url1);
- self_params.transition = ui::PAGE_TRANSITION_LINK;
- self_params.should_update_history = false;
- self_params.gesture = NavigationGestureUser;
- self_params.method = "GET";
- self_params.item_sequence_number = GenerateSequenceNumber();
- self_params.document_sequence_number = GenerateSequenceNumber();
- self_params.page_state = PageState::CreateForTestingWithSequenceNumbers(
- url1, self_params.item_sequence_number,
- self_params.document_sequence_number);
-
LoadCommittedDetailsObserver observer(contents());
- main_test_rfh()->SendRendererInitiatedNavigationRequest(url1, false);
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigateWithParams(&self_params, false);
- NavigationEntry* entry1 = controller.GetLastCommittedEntry();
+ auto renderer_initiated_navigation =
+ NavigationSimulatorImpl::CreateRendererInitiated(url1, main_test_rfh());
+ renderer_initiated_navigation->set_should_replace_current_entry(true);
+ renderer_initiated_navigation->Commit();
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_FALSE(observer.is_same_document());
@@ -2410,23 +2292,11 @@ TEST_F(NavigationControllerTest, SameDocument) {
// Fragment navigation to a new page.
const GURL url2("http://foo#a");
- FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.nav_entry_id = 0;
- params.did_create_new_entry = true;
- params.url = url2;
- params.origin = url::Origin::Create(url2);
- params.transition = ui::PAGE_TRANSITION_LINK;
- params.should_update_history = false;
- params.gesture = NavigationGestureUser;
- params.method = "GET";
- params.item_sequence_number = GenerateSequenceNumber();
- params.document_sequence_number = self_params.document_sequence_number;
- params.page_state = PageState::CreateForTestingWithSequenceNumbers(
- url2, params.item_sequence_number, params.document_sequence_number);
+ auto same_document_navigation =
+ NavigationSimulator::CreateRendererInitiated(url2, main_test_rfh());
+ same_document_navigation->CommitSameDocument();
// This should generate a new entry.
- main_test_rfh()->SendNavigateWithParams(&params, true);
- NavigationEntry* entry2 = controller.GetLastCommittedEntry();
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_TRUE(observer.is_same_document());
@@ -2434,59 +2304,36 @@ TEST_F(NavigationControllerTest, SameDocument) {
EXPECT_EQ(2, controller.GetEntryCount());
// Go back one.
- FrameHostMsg_DidCommitProvisionalLoad_Params back_params(self_params);
- controller.GoBack();
- back_params.nav_entry_id = entry1->GetUniqueID();
- back_params.did_create_new_entry = false;
- main_test_rfh()->SendNavigateWithParams(&back_params, true);
+ NavigationSimulator::GoBack(contents());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_TRUE(observer.is_same_document());
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(0, controller.GetCurrentEntryIndex());
- EXPECT_EQ(back_params.url, controller.GetVisibleEntry()->GetURL());
+ EXPECT_EQ(url1, controller.GetLastCommittedEntry()->GetURL());
// Go forward.
- FrameHostMsg_DidCommitProvisionalLoad_Params forward_params(params);
- controller.GoForward();
- forward_params.nav_entry_id = entry2->GetUniqueID();
- forward_params.did_create_new_entry = false;
- main_test_rfh()->SendNavigateWithParams(&forward_params, true);
+ NavigationSimulator::GoForward(contents());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(1, controller.GetCurrentEntryIndex());
- EXPECT_EQ(forward_params.url,
- controller.GetVisibleEntry()->GetURL());
+ EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
// Now go back and forward again. This is to work around a bug where we would
// compare the incoming URL with the last committed entry rather than the
// one identified by an existing page ID. This would result in the second URL
// losing the reference fragment when you navigate away from it and then back.
- controller.GoBack();
- main_test_rfh()->SendNavigateWithParams(&back_params, false);
- controller.GoForward();
- main_test_rfh()->SendNavigateWithParams(&forward_params, false);
- EXPECT_EQ(forward_params.url,
- controller.GetVisibleEntry()->GetURL());
+ NavigationSimulator::GoBack(contents());
+ NavigationSimulator::GoForward(contents());
+ EXPECT_EQ(2U, navigation_entry_committed_counter_);
+ navigation_entry_committed_counter_ = 0;
+ EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
// Finally, navigate to an unrelated URL to make sure same_document is not
// sticky.
const GURL url3("http://bar");
- params.nav_entry_id = 0;
- params.did_create_new_entry = true;
- params.url = url3;
- params.origin = url::Origin::Create(url3);
- params.item_sequence_number = 0;
- params.document_sequence_number = 0;
- params.page_state = PageState::CreateFromURL(url3);
- navigation_entry_committed_counter_ = 0;
- main_test_rfh()->SendRendererInitiatedNavigationRequest(url3, false);
- main_test_rfh()->PrepareForCommit();
- TestRenderFrameHost* navigating_rfh = contents()->GetPendingMainFrame()
- ? contents()->GetPendingMainFrame()
- : main_test_rfh();
- navigating_rfh->SendNavigateWithParams(&params, false);
+ NavigationSimulator::NavigateAndCommitFromDocument(url3, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_FALSE(observer.is_same_document());
@@ -2674,7 +2521,6 @@ TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) {
// Before navigating to the restored entry, it should have a restore_type
// and no SiteInstance.
- NavigationEntry* entry = our_controller.GetEntryAtIndex(0);
EXPECT_EQ(RestoreType::LAST_SESSION_EXITED_CLEANLY,
our_controller.GetEntryAtIndex(0)->restore_type());
EXPECT_FALSE(our_controller.GetEntryAtIndex(0)->site_instance());
@@ -2682,36 +2528,19 @@ TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) {
// After navigating, we should have one entry, and it should be "pending".
EXPECT_TRUE(our_controller.NeedsReload());
our_controller.LoadIfNecessary();
+ auto restore_navigation =
+ NavigationSimulator::CreateFromPending(raw_our_contents);
+ restore_navigation->ReadyToCommit();
EXPECT_EQ(1, our_controller.GetEntryCount());
EXPECT_EQ(our_controller.GetEntryAtIndex(0),
our_controller.GetPendingEntry());
// This pending navigation may have caused a different navigation to fail,
// which causes the pending entry to be cleared.
- FrameHostMsg_DidFailProvisionalLoadWithError_Params fail_load_params;
- fail_load_params.error_code = net::ERR_ABORTED;
- fail_load_params.error_description = base::string16();
- fail_load_params.url = url;
- fail_load_params.showing_repost_interstitial = false;
- main_test_rfh()->InitializeRenderFrameIfNeeded();
- main_test_rfh()->OnMessageReceived(
- FrameHostMsg_DidFailProvisionalLoadWithError(0, // routing_id
- fail_load_params));
-
+ NavigationSimulator::NavigateAndFailFromDocument(url, net::ERR_ABORTED,
+ main_test_rfh());
// Now the pending restored entry commits.
- FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.nav_entry_id = entry->GetUniqueID();
- params.did_create_new_entry = false;
- params.url = url;
- params.transition = ui::PAGE_TRANSITION_LINK;
- params.should_update_history = false;
- params.gesture = NavigationGestureUser;
- params.method = "GET";
- params.page_state = PageState::CreateFromURL(url);
- TestRenderFrameHost* main_rfh =
- static_cast<TestRenderFrameHost*>(raw_our_contents->GetMainFrame());
- main_rfh->PrepareForCommit();
- main_rfh->SendNavigateWithParams(&params, false);
+ restore_navigation->Commit();
// There should be no pending entry and one committed one.
EXPECT_EQ(1, our_controller.GetEntryCount());
@@ -2846,16 +2675,8 @@ TEST_F(NavigationControllerTest, TransientEntry) {
const GURL url4("http://foo/4");
const GURL transient_url("http://foo/transient");
- controller.LoadURL(
- url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller.GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(entry_id, true, url0);
- controller.LoadURL(
- url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller.GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(entry_id, true, url1);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url0);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
navigation_entry_changed_counter_ = 0;
navigation_list_pruned_counter_ = 0;
@@ -2880,11 +2701,7 @@ TEST_F(NavigationControllerTest, TransientEntry) {
EXPECT_FALSE(controller.CanGoForward());
// Navigate.
- controller.LoadURL(
- url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller.GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(entry_id, true, url2);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url2);
// We should have navigated, transient entry should be gone.
EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
@@ -2895,23 +2712,20 @@ TEST_F(NavigationControllerTest, TransientEntry) {
transient_entry->SetURL(transient_url);
controller.SetTransientEntry(std::move(transient_entry));
EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
- main_test_rfh()->SendRendererInitiatedNavigationRequest(url3, true);
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, true, url3);
+ NavigationSimulator::NavigateAndCommitFromDocument(url3, main_test_rfh());
// Transient entry should be gone.
EXPECT_EQ(url3, controller.GetVisibleEntry()->GetURL());
EXPECT_EQ(controller.GetEntryCount(), 4);
// Initiate a navigation, add a transient then commit navigation.
- controller.LoadURL(
- url4, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller.GetPendingEntry()->GetUniqueID();
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(url4, contents());
+ navigation->Start();
transient_entry.reset(new NavigationEntryImpl);
transient_entry->SetURL(transient_url);
controller.SetTransientEntry(std::move(transient_entry));
EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(entry_id, true, url4);
+ navigation->Commit();
EXPECT_EQ(url4, controller.GetVisibleEntry()->GetURL());
EXPECT_EQ(controller.GetEntryCount(), 5);
@@ -2928,11 +2742,7 @@ TEST_F(NavigationControllerTest, TransientEntry) {
EXPECT_EQ(controller.GetEntryCount(), 5);
// Suppose the page requested a history navigation backward.
- controller.GoToOffset(-1);
- entry_id = controller.GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigateWithTransition(
- entry_id, false, url3, controller.GetPendingEntry()->GetTransitionType());
+ NavigationSimulator::GoBack(contents());
// Add a transient and go to an entry before the current one.
transient_entry.reset(new NavigationEntryImpl);
@@ -2940,15 +2750,13 @@ TEST_F(NavigationControllerTest, TransientEntry) {
controller.SetTransientEntry(std::move(transient_entry));
EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
controller.GoToIndex(1);
- entry_id = controller.GetPendingEntry()->GetUniqueID();
+ auto history_navigation1 = NavigationSimulator::CreateFromPending(contents());
// The navigation should have been initiated, transient entry should be gone.
EXPECT_FALSE(controller.GetTransientEntry());
EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
// Visible entry does not update for history navigations until commit.
EXPECT_EQ(url3, controller.GetVisibleEntry()->GetURL());
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigateWithTransition(
- entry_id, false, url1, controller.GetPendingEntry()->GetTransitionType());
+ history_navigation1->Commit();
EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
// Add a transient and go to an entry after the current one.
@@ -2957,15 +2765,13 @@ TEST_F(NavigationControllerTest, TransientEntry) {
controller.SetTransientEntry(std::move(transient_entry));
EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
controller.GoToIndex(3);
- entry_id = controller.GetPendingEntry()->GetUniqueID();
+ auto history_navigation2 = NavigationSimulator::CreateFromPending(contents());
// The navigation should have been initiated, transient entry should be gone.
// Because of the transient entry that is removed, going to index 3 makes us
// land on url2 (which is visible after the commit).
EXPECT_EQ(url2, controller.GetPendingEntry()->GetURL());
EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigateWithTransition(
- entry_id, false, url2, controller.GetPendingEntry()->GetTransitionType());
+ history_navigation2->Commit();
EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
// Add a transient and go forward.
@@ -2974,15 +2780,14 @@ TEST_F(NavigationControllerTest, TransientEntry) {
controller.SetTransientEntry(std::move(transient_entry));
EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
EXPECT_TRUE(controller.CanGoForward());
- controller.GoForward();
- entry_id = controller.GetPendingEntry()->GetUniqueID();
+ auto forward_navigation =
+ NavigationSimulator::CreateHistoryNavigation(1, contents());
+ forward_navigation->Start();
// We should have navigated, transient entry should be gone.
EXPECT_FALSE(controller.GetTransientEntry());
EXPECT_EQ(url3, controller.GetPendingEntry()->GetURL());
EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigateWithTransition(
- entry_id, false, url3, controller.GetPendingEntry()->GetTransitionType());
+ forward_navigation->Commit();
EXPECT_EQ(url3, controller.GetVisibleEntry()->GetURL());
// Add a transient and do an in-page navigation, replacing the current entry.
@@ -3013,13 +2818,10 @@ TEST_F(NavigationControllerTest, ReloadTransient) {
const GURL transient_url("http://foo/transient");
// Load |url0|, and start a pending navigation to |url1|.
- controller.LoadURL(
- url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller.GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(entry_id, true, url0);
- controller.LoadURL(
- url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url0);
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(url1, contents());
+ navigation->Start();
// A transient entry is added, interrupting the navigation.
std::unique_ptr<NavigationEntry> transient_entry(new NavigationEntryImpl);
@@ -3032,7 +2834,6 @@ TEST_F(NavigationControllerTest, ReloadTransient) {
// the transient entry for |transient_url|, and start a navigation to
// |transient_url|.
controller.Reload(ReloadType::NORMAL, true);
- entry_id = controller.GetPendingEntry()->GetUniqueID();
EXPECT_FALSE(controller.GetTransientEntry());
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
@@ -3040,8 +2841,8 @@ TEST_F(NavigationControllerTest, ReloadTransient) {
EXPECT_EQ(controller.GetEntryAtIndex(0)->GetURL(), url0);
// Load of |transient_url| completes.
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(entry_id, true, transient_url);
+ auto reload = NavigationSimulator::CreateFromPending(contents());
+ reload->Commit();
ASSERT_EQ(controller.GetEntryCount(), 2);
EXPECT_EQ(controller.GetEntryAtIndex(0)->GetURL(), url0);
EXPECT_EQ(controller.GetEntryAtIndex(1)->GetURL(), transient_url);
@@ -3246,13 +3047,8 @@ TEST_F(NavigationControllerTest, ShowRendererURLAfterFailUntilModified) {
// Suppose it aborts before committing, if it's a 204 or download or due to a
// stop or a new navigation from the user. The URL should remain visible.
- FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
- params.error_code = net::ERR_ABORTED;
- params.error_description = base::string16();
- params.url = url;
- params.showing_repost_interstitial = false;
- main_test_rfh()->OnMessageReceived(
- FrameHostMsg_DidFailProvisionalLoadWithError(0, params));
+ main_test_rfh()->DidFailProvisionalLoadWithError(url, net::ERR_ABORTED,
+ base::string16(), false);
EXPECT_EQ(url, controller.GetVisibleEntry()->GetURL());
// If something else later modifies the contents of the about:blank page, then
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.cc b/chromium/content/browser/frame_host/navigation_entry_impl.cc
index 85482344f72..306384c03af 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.cc
@@ -680,7 +680,8 @@ CommonNavigationParams NavigationEntryImpl::ConstructCommonNavigationParams(
GetHistoryURLForDataURL(), previews_state, navigation_start,
frame_entry.method(), post_body ? post_body : post_data_,
base::Optional<SourceLocation>(), has_started_from_context_menu(),
- has_user_gesture(), InitiatorCSPInfo(), std::string(), input_start);
+ has_user_gesture(), InitiatorCSPInfo(), std::vector<int>(), std::string(),
+ false /* is_history_navigation_in_new_child_frame */, input_start);
}
CommitNavigationParams NavigationEntryImpl::ConstructCommitNavigationParams(
@@ -688,7 +689,6 @@ CommitNavigationParams NavigationEntryImpl::ConstructCommitNavigationParams(
const GURL& original_url,
const base::Optional<url::Origin>& origin_to_commit,
const std::string& original_method,
- bool is_history_navigation_in_new_child,
const std::map<std::string, bool>& subframe_unique_names,
bool intended_as_new_entry,
int pending_history_list_offset,
@@ -716,9 +716,9 @@ CommitNavigationParams NavigationEntryImpl::ConstructCommitNavigationParams(
CommitNavigationParams commit_params(
origin_to_commit, GetIsOverridingUserAgent(), redirects, original_url,
original_method, GetCanLoadLocalResources(), frame_entry.page_state(),
- GetUniqueID(), is_history_navigation_in_new_child, subframe_unique_names,
- intended_as_new_entry, pending_offset_to_send, current_offset_to_send,
- current_length_to_send, IsViewSourceMode(), should_clear_history_list());
+ GetUniqueID(), subframe_unique_names, intended_as_new_entry,
+ pending_offset_to_send, current_offset_to_send, current_length_to_send,
+ IsViewSourceMode(), should_clear_history_list());
#if defined(OS_ANDROID)
if (NavigationControllerImpl::ValidateDataURLAsString(GetDataURLAsString())) {
commit_params.data_url_as_string = GetDataURLAsString()->data();
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.h b/chromium/content/browser/frame_host/navigation_entry_impl.h
index f7f3b75fc2a..4323013cddb 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.h
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.h
@@ -189,7 +189,6 @@ class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry {
const GURL& original_url,
const base::Optional<url::Origin>& origin_to_commit,
const std::string& original_method,
- bool is_history_navigation_in_new_child,
const std::map<std::string, bool>& subframe_unique_names,
bool intended_as_new_entry,
int pending_offset_to_send,
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.cc b/chromium/content/browser/frame_host/navigation_handle_impl.cc
index 659d66d2d23..958c5eda7ae 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.cc
@@ -59,6 +59,9 @@ int64_t CreateUniqueHandleID() {
// UMA_HISTOGRAM_MEDIUM_TIMES, but a custom kMinTime is used for high fidelity
// near the low end of measured values.
//
+// TODO(zetamoo): This is duplicated in navigation_request. Never update one
+// without the other. And remove this one.
+//
// TODO(csharrison,nasko): This macro is incorrect for subframe navigations,
// which will only have subframe-specific transition types. This means that all
// subframes currently are tagged as NewNavigations.
@@ -121,23 +124,15 @@ void LogIsSameProcess(ui::PageTransition transition, bool is_same_process) {
NavigationHandleImpl::NavigationHandleImpl(
NavigationRequest* navigation_request,
- const std::vector<GURL>& redirect_chain,
int pending_nav_entry_id,
- net::HttpRequestHeaders request_headers,
- const Referrer& sanitized_referrer)
+ net::HttpRequestHeaders request_headers)
: navigation_request_(navigation_request),
net_error_code_(net::OK),
- was_redirected_(false),
- did_replace_entry_(false),
- should_update_history_(false),
- subframe_entry_committed_(false),
request_headers_(std::move(request_headers)),
pending_nav_entry_id_(pending_nav_entry_id),
navigation_id_(CreateUniqueHandleID()),
- redirect_chain_(redirect_chain),
reload_type_(ReloadType::NONE),
restore_type_(RestoreType::NONE),
- navigation_type_(NAVIGATION_TYPE_UNKNOWN),
is_same_process_(true),
weak_factory_(this) {
const GURL& url = navigation_request_->common_params().url;
@@ -148,20 +143,6 @@ NavigationHandleImpl::NavigationHandleImpl(
DCHECK(!navigation_request_->common_params().navigation_start.is_null());
DCHECK(!IsRendererDebugURL(url));
- if (redirect_chain_.empty())
- redirect_chain_.push_back(url);
-
- // Mirrors the logic in RenderFrameImpl::SendDidCommitProvisionalLoad.
- if (navigation_request_->common_params().transition &
- ui::PAGE_TRANSITION_CLIENT_REDIRECT) {
- // If the page contained a client redirect (meta refresh,
- // document.location), set the referrer appropriately.
- sanitized_referrer_ =
- Referrer(redirect_chain_[0], sanitized_referrer.policy);
- } else {
- sanitized_referrer_ = sanitized_referrer;
- }
-
// Try to match this with a pending NavigationEntry if possible. Note that
// the NavigationController itself may be gone if this is a navigation inside
// an interstitial and the interstitial is asynchronously deleting itself due
@@ -185,10 +166,6 @@ NavigationHandleImpl::NavigationHandleImpl(
}
}
-#if defined(OS_ANDROID)
- navigation_handle_proxy_ = std::make_unique<NavigationHandleProxy>(this);
-#endif
-
if (IsInMainFrame()) {
TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
"navigation", "Navigation StartToCommit", this,
@@ -203,9 +180,6 @@ NavigationHandleImpl::NavigationHandleImpl(
}
NavigationHandleImpl::~NavigationHandleImpl() {
-#if defined(OS_ANDROID)
- navigation_handle_proxy_->DidFinish();
-#endif
GetDelegate()->DidFinishNavigation(this);
@@ -250,11 +224,11 @@ bool NavigationHandleImpl::IsRendererInitiated() {
}
bool NavigationHandleImpl::WasServerRedirect() {
- return was_redirected_;
+ return navigation_request_->was_redirected();
}
const std::vector<GURL>& NavigationHandleImpl::GetRedirectChain() {
- return redirect_chain_;
+ return navigation_request_->redirect_chain();
}
int NavigationHandleImpl::GetFrameTreeNodeId() {
@@ -286,7 +260,7 @@ NavigationHandleImpl::GetResourceRequestBody() {
}
const Referrer& NavigationHandleImpl::GetReferrer() {
- return sanitized_referrer_;
+ return navigation_request_->sanitized_referrer();
}
bool NavigationHandleImpl::HasUserGesture() {
@@ -297,7 +271,7 @@ ui::PageTransition NavigationHandleImpl::GetPageTransition() {
return navigation_request_->common_params().transition;
}
-const NavigationUIData* NavigationHandleImpl::GetNavigationUIData() {
+NavigationUIData* NavigationHandleImpl::GetNavigationUIData() {
return navigation_request_->navigation_ui_data();
}
@@ -370,28 +344,19 @@ bool NavigationHandleImpl::IsErrorPage() {
}
bool NavigationHandleImpl::HasSubframeNavigationEntryCommitted() {
- DCHECK(!IsInMainFrame());
- DCHECK(state() == NavigationRequest::DID_COMMIT ||
- state() == NavigationRequest::DID_COMMIT_ERROR_PAGE);
- return subframe_entry_committed_;
+ return navigation_request_->subframe_entry_committed();
}
bool NavigationHandleImpl::DidReplaceEntry() {
- DCHECK(state() == NavigationRequest::DID_COMMIT ||
- state() == NavigationRequest::DID_COMMIT_ERROR_PAGE);
- return did_replace_entry_;
+ return navigation_request_->did_replace_entry();
}
bool NavigationHandleImpl::ShouldUpdateHistory() {
- DCHECK(state() == NavigationRequest::DID_COMMIT ||
- state() == NavigationRequest::DID_COMMIT_ERROR_PAGE);
- return should_update_history_;
+ return navigation_request_->should_update_history();
}
const GURL& NavigationHandleImpl::GetPreviousURL() {
- DCHECK(state() == NavigationRequest::DID_COMMIT ||
- state() == NavigationRequest::DID_COMMIT_ERROR_PAGE);
- return previous_url_;
+ return navigation_request_->previous_url();
}
net::IPEndPoint NavigationHandleImpl::GetSocketAddress() {
@@ -410,13 +375,6 @@ void NavigationHandleImpl::RegisterThrottleForTesting(
std::move(navigation_throttle));
}
-#if defined(OS_ANDROID)
-base::android::ScopedJavaGlobalRef<jobject>
-NavigationHandleImpl::java_navigation_handle() {
- return navigation_handle_proxy_->java_navigation_handle();
-}
-#endif
-
bool NavigationHandleImpl::IsDeferredForTesting() {
return navigation_request_->IsDeferredForTesting();
}
@@ -471,6 +429,10 @@ bool NavigationHandleImpl::IsFormSubmission() {
return navigation_request_->begin_params()->is_form_submission;
}
+bool NavigationHandleImpl::WasInitiatedByLinkClick() {
+ return navigation_request_->begin_params()->was_initiated_by_link_click;
+}
+
const std::string& NavigationHandleImpl::GetHrefTranslate() {
return navigation_request_->common_params().href_translate;
}
@@ -529,36 +491,6 @@ NavigationHandleImpl::TakeAppCacheHandle() {
return std::move(appcache_handle_);
}
-void NavigationHandleImpl::UpdateStateFollowingRedirect(
- const GURL& new_referrer_url,
- ThrottleChecksFinishedCallback callback) {
- // The navigation should not redirect to a "renderer debug" url. It should be
- // blocked in NavigationRequest::OnRequestRedirected or in
- // ResourceLoader::OnReceivedRedirect.
- // Note: the call to GetURL below returns the post-redirect URL.
- // See https://crbug.com/728398.
- CHECK(!IsRendererDebugURL(GetURL()));
-
- // Update the navigation parameters.
- if (!(GetPageTransition() & ui::PAGE_TRANSITION_CLIENT_REDIRECT)) {
- sanitized_referrer_.url = new_referrer_url;
- sanitized_referrer_ =
- Referrer::SanitizeForRequest(GetURL(), sanitized_referrer_);
- }
-
- was_redirected_ = true;
- redirect_chain_.push_back(GetURL());
-
- navigation_request_->set_handle_state(
- NavigationRequest::PROCESSING_WILL_REDIRECT_REQUEST);
-
-#if defined(OS_ANDROID)
- navigation_handle_proxy_->DidRedirect();
-#endif
-
- complete_callback_ = std::move(callback);
-}
-
void NavigationHandleImpl::ReadyToCommitNavigation(bool is_error) {
TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this,
"ReadyToCommitNavigation");
@@ -615,99 +547,6 @@ void NavigationHandleImpl::ReadyToCommitNavigation(bool is_error) {
GetDelegate()->ReadyToCommitNavigation(this);
}
-void NavigationHandleImpl::DidCommitNavigation(
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
- bool navigation_entry_committed,
- bool did_replace_entry,
- const GURL& previous_url,
- NavigationType navigation_type) {
- CHECK_EQ(GetURL(), params.url);
-
- did_replace_entry_ = did_replace_entry;
- should_update_history_ = params.should_update_history;
- previous_url_ = previous_url;
- base_url_ = params.base_url;
- navigation_type_ = navigation_type;
-
- // If an error page reloads, net_error_code might be 200 but we still want to
- // count it as an error page.
- if (params.base_url.spec() == kUnreachableWebDataURL ||
- net_error_code_ != net::OK) {
- TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this,
- "DidCommitNavigation: error page");
- navigation_request_->set_handle_state(
- NavigationRequest::DID_COMMIT_ERROR_PAGE);
- } else {
- TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this,
- "DidCommitNavigation");
- navigation_request_->set_handle_state(NavigationRequest::DID_COMMIT);
- }
-
- StopCommitTimeout();
-
- // Record metrics for the time it took to commit the navigation if it was to
- // another document without error.
- if (!IsSameDocument() && !IsErrorPage()) {
- base::TimeTicks now = base::TimeTicks::Now();
- base::TimeDelta delta =
- now - navigation_request_->common_params().navigation_start;
- ui::PageTransition transition = GetPageTransition();
- base::Optional<bool> is_background =
- GetRenderFrameHost()->GetProcess()->IsProcessBackgrounded();
- LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit", transition, is_background,
- delta);
- if (IsInMainFrame()) {
- LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.MainFrame", transition,
- is_background, delta);
- } else {
- LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.Subframe", transition,
- is_background, delta);
- }
- if (is_same_process_) {
- LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess", transition,
- is_background, delta);
- if (IsInMainFrame()) {
- LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess.MainFrame",
- transition, is_background, delta);
- } else {
- LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess.Subframe",
- transition, is_background, delta);
- }
- } else {
- LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess", transition,
- is_background, delta);
- if (IsInMainFrame()) {
- LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess.MainFrame",
- transition, is_background, delta);
- } else {
- LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess.Subframe",
- transition, is_background, delta);
- }
- }
-
- if (!ready_to_commit_time_.is_null()) {
- LOG_NAVIGATION_TIMING_HISTOGRAM("ReadyToCommitUntilCommit2",
- GetPageTransition(), is_background,
- now - ready_to_commit_time_);
- }
- }
-
- DCHECK(!IsInMainFrame() || navigation_entry_committed)
- << "Only subframe navigations can get here without changing the "
- << "NavigationEntry";
- 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.
- 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
- // possible.
- DCHECK(!IsSameDocument() || !frame_tree_node()->is_collapsed());
- frame_tree_node()->SetCollapsed(false);
- }
-}
-
void NavigationHandleImpl::RunCompleteCallback(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK(result.action() != NavigationThrottle::DEFER);
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.h b/chromium/content/browser/frame_host/navigation_handle_impl.h
index 5dfc0dc1966..33e6549e418 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.h
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.h
@@ -20,7 +20,6 @@
#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
-#include "build/build_config.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigation_request.h"
#include "content/browser/frame_host/navigation_throttle_runner.h"
@@ -36,13 +35,6 @@
#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
#include "url/gurl.h"
-#if defined(OS_ANDROID)
-#include "base/android/scoped_java_ref.h"
-#include "content/browser/android/navigation_handle_proxy.h"
-#endif
-
-struct FrameHostMsg_DidCommitProvisionalLoad_Params;
-
namespace content {
class AppCacheNavigationHandle;
@@ -82,7 +74,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
const Referrer& GetReferrer() override;
bool HasUserGesture() override;
ui::PageTransition GetPageTransition() override;
- const NavigationUIData* GetNavigationUIData() override;
+ NavigationUIData* GetNavigationUIData() override;
bool IsExternalProtocol() override;
net::Error GetNetErrorCode() override;
RenderFrameHostImpl* GetRenderFrameHost() override;
@@ -113,6 +105,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
const GlobalRequestID& GetGlobalRequestID() override;
bool IsDownload() override;
bool IsFormSubmission() override;
+ bool WasInitiatedByLinkClick() override;
bool IsSignedExchangeInnerResponse() override;
bool WasResponseCached() override;
const net::ProxyServer& GetProxyServer() override;
@@ -134,12 +127,6 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
void RegisterSubresourceOverride(
mojom::TransferrableURLLoaderPtr transferrable_loader) override;
-#if defined(OS_ANDROID)
- // Returns a reference to this NavigationHandle Java counterpart. It is used
- // by Java WebContentsObservers.
- base::android::ScopedJavaGlobalRef<jobject> java_navigation_handle();
-#endif
-
// Used in tests.
NavigationRequest::NavigationHandleState state_for_testing() const {
return state();
@@ -192,12 +179,6 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
typedef base::OnceCallback<void(NavigationThrottle::ThrottleCheckResult)>
ThrottleChecksFinishedCallback;
- // Updates the state of the navigation handle after encountering a server
- // redirect.
- void UpdateStateFollowingRedirect(
- const GURL& new_referrer_url,
- ThrottleChecksFinishedCallback callback);
-
// Returns the FrameTreeNode this navigation is happening in.
FrameTreeNode* frame_tree_node() const {
return navigation_request_->frame_tree_node();
@@ -207,18 +188,6 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// |state_| and inform the delegate.
void ReadyToCommitNavigation(bool is_error);
- // Called when the navigation was committed. This will update the |state_|.
- // |navigation_entry_committed| indicates whether the navigation changed which
- // NavigationEntry is current.
- // |did_replace_entry| is true if the committed entry has replaced the
- // existing one. A non-user initiated redirect causes such replacement.
- void DidCommitNavigation(
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
- bool navigation_entry_committed,
- bool did_replace_entry,
- const GURL& previous_url,
- NavigationType navigation_type);
-
// Called during commit. Takes ownership of the embedder's NavigationData
// instance. This NavigationData may have been cloned prior to being added
// here.
@@ -230,11 +199,10 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
return navigation_request_->navigation_ui_data();
}
- const GURL& base_url() { return base_url_; }
+ const GURL& base_url() { return navigation_request_->base_url(); }
NavigationType navigation_type() {
- DCHECK_GE(state(), NavigationRequest::DID_COMMIT);
- return navigation_type_;
+ return navigation_request_->navigation_type();
}
void set_response_headers_for_testing(
@@ -293,10 +261,8 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// |navigation_start| comes from the CommonNavigationParams associated with
// this navigation.
NavigationHandleImpl(NavigationRequest* navigation_request,
- const std::vector<GURL>& redirect_chain,
int pending_nav_entry_id,
- net::HttpRequestHeaders request_headers,
- const Referrer& sanitized_referrer);
+ net::HttpRequestHeaders request_headers);
// Helper function to run and reset the |complete_callback_|. This marks the
// end of a round of NavigationThrottleChecks.
@@ -321,16 +287,15 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
void StopCommitTimeout();
void RestartCommitTimeout();
+ // TODO(zetamoo): Remove once |ready_to_commit_time_| is owned by
+ // NavigationRequest.
+ base::TimeTicks ready_to_commit_time() const { return ready_to_commit_time_; }
+
// The NavigationRequest that owns this NavigationHandle.
NavigationRequest* navigation_request_;
// See NavigationHandle for a description of those member variables.
- Referrer sanitized_referrer_;
net::Error net_error_code_;
- bool was_redirected_;
- bool did_replace_entry_;
- bool should_update_history_;
- bool subframe_entry_committed_;
// The headers used for the request.
net::HttpRequestHeaders request_headers_;
@@ -381,19 +346,12 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// The unique id to identify this to navigation with.
int64_t navigation_id_;
- // The chain of redirects.
- std::vector<GURL> redirect_chain_;
-
// Stores the reload type, or NONE if it's not a reload.
ReloadType reload_type_;
// Stores the restore type, or NONE it it's not a restore.
RestoreType restore_type_;
- GURL previous_url_;
- GURL base_url_;
- NavigationType navigation_type_;
-
// Which proxy server was used for this navigation, if any.
net::ProxyServer proxy_server_;
@@ -404,12 +362,6 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// TODO(clamy): Clean this up once the architecture of unit tests is better.
scoped_refptr<net::HttpResponseHeaders> response_headers_for_testing_;
-#if defined(OS_ANDROID)
- // For each C++ NavigationHandle, there is a Java counterpart. It is the JNI
- // bridge in between the two.
- std::unique_ptr<NavigationHandleProxy> navigation_handle_proxy_;
-#endif
-
base::WeakPtrFactory<NavigationHandleImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(NavigationHandleImpl);
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 01971ad5f02..26a3c591f5a 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -1924,7 +1924,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, ErrorPageNetworkError) {
// the privileged process.
IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
BlockedRequestAfterWebUI) {
- GURL web_ui_url("chrome://gpu");
+ GURL web_ui_url(GetWebUIURL("gpu"));
WebContents* web_contents = shell()->web_contents();
// Navigate to the initial page.
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
index 2ad6c98f474..f9d0d4ba504 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -444,7 +444,7 @@ TEST_F(NavigationHandleImplTest, WillFailRequestSetsSSLInfo) {
const GURL kUrl = GURL("https://chromium.org");
auto navigation =
NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
- navigation->set_ssl_info(ssl_info);
+ navigation->SetSSLInfo(ssl_info);
navigation->Fail(net::ERR_CERT_DATE_INVALID);
EXPECT_EQ(net::CERT_STATUS_AUTHORITY_INVALID,
diff --git a/chromium/content/browser/frame_host/navigation_request.cc b/chromium/content/browser/frame_host/navigation_request.cc
index 05336f93301..7d90767b536 100644
--- a/chromium/content/browser/frame_host/navigation_request.cc
+++ b/chromium/content/browser/frame_host/navigation_request.cc
@@ -12,6 +12,7 @@
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
+#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/rand_util.h"
#include "base/strings/string_util.h"
@@ -36,6 +37,7 @@
#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/loader/prefetched_signed_exchange_cache.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -230,26 +232,12 @@ void AddAdditionalRequestHeaders(net::HttpRequestHeaders* headers,
// TODO(mkwst): Extract this logic out somewhere that can be shared between
// Blink and //content.
if (IsFetchMetadataEnabled() && IsOriginSecure(url)) {
- std::string site_value = "cross-site";
- std::string user_value = has_user_gesture ? "?1" : std::string();
-
// Navigations that aren't triggerable from the web (e.g. typing in the
- // address bar, or clicking a bookmark) are labeled as 'none'. Webby
- // navigations compare the |initiator_origin| to the navigation target.
- if (!PageTransitionIsWebTriggerable(transition)) {
- site_value = "none";
+ // address bar, or clicking a bookmark) are labeled as user-initiated.
+ std::string user_value = has_user_gesture ? "?1" : std::string();
+ if (!PageTransitionIsWebTriggerable(transition))
user_value = "?1";
- } else if (initiator_origin) {
- url::Origin target_origin = url::Origin::Create(url);
- if (initiator_origin->IsSameOriginWith(target_origin)) {
- site_value = "same-origin";
- } else if (net::registry_controlled_domains::SameDomainOrHost(
- *initiator_origin, target_origin,
- net::registry_controlled_domains::
- INCLUDE_PRIVATE_REGISTRIES)) {
- site_value = "same-site";
- }
- }
+
std::string destination;
std::string mode = "navigate";
switch (frame_tree_node->frame_owner_element_type()) {
@@ -278,17 +266,15 @@ void AddAdditionalRequestHeaders(net::HttpRequestHeaders* headers,
headers->SetHeaderIfMissing("Sec-Fetch-Dest", destination.c_str());
}
headers->SetHeaderIfMissing("Sec-Fetch-Mode", mode.c_str());
- headers->SetHeaderIfMissing("Sec-Fetch-Site", site_value.c_str());
if (!user_value.empty())
headers->SetHeaderIfMissing("Sec-Fetch-User", user_value.c_str());
+ // Sec-Fetch-Site is covered by network::SetSecFetchSiteHeader function.
}
// Ask whether we should request a policy.
- std::string origin_policy_request;
- if (OriginPolicyThrottle::ShouldRequestOriginPolicy(url,
- &origin_policy_request)) {
+ if (OriginPolicyThrottle::ShouldRequestOriginPolicy(url)) {
headers->SetHeader(net::HttpRequestHeaders::kSecOriginPolicy,
- origin_policy_request);
+ kDefaultOriginPolicyVersion);
}
// Next, set the HTTP Origin if needed.
@@ -339,6 +325,98 @@ bool ShouldPropagateUserActivation(const url::Origin& previous_origin,
return !previous_domain.empty() && previous_domain == new_domain;
}
+// LOG_NAVIGATION_TIMING_HISTOGRAM logs |value| for "Navigation.<histogram>" UMA
+// as well as supplementary UMAs (depending on |transition| and |is_background|)
+// for BackForward/Reload/NewNavigation variants.
+//
+// kMaxTime and kBuckets constants are consistent with
+// UMA_HISTOGRAM_MEDIUM_TIMES, but a custom kMinTime is used for high fidelity
+// near the low end of measured values.
+//
+// TODO(zetamoo): This is duplicated in navigation_handle_impl. Never update one
+// without the other.
+//
+// TODO(csharrison,nasko): This macro is incorrect for subframe navigations,
+// which will only have subframe-specific transition types. This means that all
+// subframes currently are tagged as NewNavigations.
+#define LOG_NAVIGATION_TIMING_HISTOGRAM(histogram, transition, is_background, \
+ duration) \
+ do { \
+ const base::TimeDelta kMinTime = base::TimeDelta::FromMilliseconds(1); \
+ const base::TimeDelta kMaxTime = base::TimeDelta::FromMinutes(3); \
+ const int kBuckets = 50; \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram, duration, kMinTime, \
+ kMaxTime, kBuckets); \
+ if (transition & ui::PAGE_TRANSITION_FORWARD_BACK) { \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".BackForward", \
+ duration, kMinTime, kMaxTime, kBuckets); \
+ } else if (ui::PageTransitionCoreTypeIs(transition, \
+ ui::PAGE_TRANSITION_RELOAD)) { \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".Reload", duration, \
+ kMinTime, kMaxTime, kBuckets); \
+ } else if (ui::PageTransitionIsNewNavigation(transition)) { \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".NewNavigation", \
+ duration, kMinTime, kMaxTime, kBuckets); \
+ } else { \
+ NOTREACHED() << "Invalid page transition: " << transition; \
+ } \
+ if (is_background.has_value()) { \
+ if (is_background.value()) { \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram \
+ ".BackgroundProcessPriority", \
+ duration, kMinTime, kMaxTime, kBuckets); \
+ } else { \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram \
+ ".ForegroundProcessPriority", \
+ duration, kMinTime, kMaxTime, kBuckets); \
+ } \
+ } \
+ } while (0)
+
+void RecordStartToCommitMetrics(base::TimeTicks navigation_start_time,
+ ui::PageTransition transition,
+ const base::TimeTicks& ready_to_commit_time,
+ base::Optional<bool> is_background,
+ bool is_same_process,
+ bool is_main_frame) {
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeDelta delta = now - navigation_start_time;
+ LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit", transition, is_background,
+ delta);
+ if (is_main_frame) {
+ LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.MainFrame", transition,
+ is_background, delta);
+ } else {
+ LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.Subframe", transition,
+ is_background, delta);
+ }
+ if (is_same_process) {
+ LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess", transition,
+ is_background, delta);
+ if (is_main_frame) {
+ LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess.MainFrame",
+ transition, is_background, delta);
+ } else {
+ LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess.Subframe",
+ transition, is_background, delta);
+ }
+ } else {
+ LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess", transition,
+ is_background, delta);
+ if (is_main_frame) {
+ LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess.MainFrame",
+ transition, is_background, delta);
+ } else {
+ LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess.Subframe",
+ transition, is_background, delta);
+ }
+ }
+ if (!ready_to_commit_time.is_null()) {
+ LOG_NAVIGATION_TIMING_HISTOGRAM("ReadyToCommitUntilCommit2", transition,
+ is_background, now - ready_to_commit_time);
+ }
+}
+
} // namespace
// static
@@ -360,7 +438,7 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
extra_headers, net::LOAD_NORMAL, false /* skip_service_worker */,
blink::mojom::RequestContextType::LOCATION,
blink::WebMixedContentContextType::kBlockable, is_form_submission,
- GURL() /* searchable_form_url */,
+ false /* was_initiated_by_link_click */, GURL() /* searchable_form_url */,
std::string() /* searchable_form_encoding */,
GURL() /* client_side_redirect_url */,
base::nullopt /* devtools_initiator_info */);
@@ -408,7 +486,9 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
bool override_user_agent,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
mojom::NavigationClientAssociatedPtrInfo navigation_client,
- blink::mojom::NavigationInitiatorPtr navigation_initiator) {
+ blink::mojom::NavigationInitiatorPtr navigation_initiator,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache) {
// Only normal navigations to a different document or reloads are expected.
// - Renderer-initiated fragment-navigations never take place in the browser,
// even with PlzNavigate.
@@ -429,7 +509,6 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
false, // can_load_local_resources
PageState(), // page_state
0, // nav_entry_id
- false, // is_history_navigation_in_new_child
std::map<std::string, bool>(), // subframe_unique_names
false, // intended_as_new_entry
-1, // |pending_history_list_offset| is set to -1 because
@@ -447,6 +526,8 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
std::move(navigation_client), std::move(navigation_initiator)));
navigation_request->blob_url_loader_factory_ =
std::move(blob_url_loader_factory);
+ navigation_request->prefetched_signed_exchange_cache_ =
+ std::move(prefetched_signed_exchange_cache);
return navigation_request;
}
@@ -471,12 +552,15 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateForCommit(
base::TimeTicks::Now(), params.method, nullptr,
base::Optional<SourceLocation>(), false /* started_from_context_menu */,
params.gesture == NavigationGestureUser, InitiatorCSPInfo(),
- std::string() /* href_translate */, base::TimeTicks::Now());
+ std::vector<int>() /* initiator_origin_trial_features */,
+ std::string() /* href_translate */,
+ false /* is_history_navigation_in_new_child_frame */,
+ base::TimeTicks::Now());
CommitNavigationParams commit_params(
params.origin, params.is_overriding_user_agent, params.redirects,
params.original_request_url, params.method,
false /* can_load_local_resources */, params.page_state,
- params.nav_entry_id, false /* is_history_navigation_in_new_child */,
+ params.nav_entry_id,
std::map<std::string, bool>() /* subframe_unique_names */,
params.intended_as_new_entry, -1 /* pending_history_list_offset */,
-1 /* current_history_list_offset */,
@@ -497,7 +581,6 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateForCommit(
// navigation just committed.
navigation_request->state_ = RESPONSE_STARTED;
navigation_request->render_frame_host_ = render_frame_host;
- navigation_request->VerifyLoaderAndRenderFrameHostExpectations();
navigation_request->CreateNavigationHandle(true);
DCHECK(navigation_request->navigation_handle());
return navigation_request;
@@ -556,14 +639,8 @@ NavigationRequest::NavigationRequest(
if (IsPerNavigationMojoInterfaceEnabled()) {
DCHECK(navigation_client.is_valid());
- request_navigation_client_ = mojom::NavigationClientAssociatedPtr();
- request_navigation_client_.Bind(std::move(navigation_client));
- // Binds the OnAbort callback
- HandleInterfaceDisconnection(
- &request_navigation_client_,
- base::BindOnce(&NavigationRequest::OnRendererAbortedNavigation,
- base::Unretained(this)));
- associated_site_instance_id_ = source_site_instance_->GetId();
+ SetNavigationClient(std::move(navigation_client),
+ source_site_instance_->GetId());
}
} else if (entry) {
DCHECK(!navigation_client.is_valid());
@@ -668,6 +745,12 @@ NavigationRequest::~NavigationRequest() {
devtools_instrumentation::OnNavigationRequestFailed(
*this, network::URLLoaderCompletionStatus(net::ERR_ABORTED));
}
+
+#if defined(OS_ANDROID)
+ if (navigation_handle_proxy_)
+ navigation_handle_proxy_->DidFinish();
+#endif
+
// This is done manually here because the NavigationHandle destructor
// calls into WebContentsObserver::DidFinishNavigation, some of which need to
// then access navigation_request(). This is only possible if the handle is
@@ -676,23 +759,11 @@ NavigationRequest::~NavigationRequest() {
}
void NavigationRequest::BeginNavigation() {
- DCHECK(!loader_);
- DCHECK(!render_frame_host_);
-
- // TODO(https://crbug.com/936962): Remove this when the bug is fixed.
- if (loader_) {
- FrameMsg_Navigate_Type::Value navigation_type =
- common_params_.navigation_type;
- base::debug::Alias(&navigation_type);
- NavigationState state = state_;
- base::debug::Alias(&state);
- DEBUG_ALIAS_FOR_GURL(url, common_params_.url);
- base::debug::DumpWithoutCrashing();
- loader_.reset();
- }
DCHECK(state_ == NOT_STARTED || state_ == WAITING_FOR_RENDERER_RESPONSE);
TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationRequest", this,
"BeginNavigation");
+ DCHECK(!loader_);
+ DCHECK(!render_frame_host_);
state_ = STARTED;
@@ -794,7 +865,6 @@ void NavigationRequest::BeginNavigation() {
// Select an appropriate RenderFrameHost.
render_frame_host_ =
frame_tree_node_->render_manager()->GetFrameHostForNavigation(*this);
- VerifyLoaderAndRenderFrameHostExpectations();
NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL(render_frame_host_,
common_params_.url);
@@ -825,19 +895,16 @@ void NavigationRequest::CreateNavigationHandle(bool is_for_commit) {
starting_site_instance_ =
frame_tree_node->current_frame_host()->GetSiteInstance();
- // TODO(alexmos): Using |starting_site_instance_|'s IsolationContext may not
- // be correct for cross-BrowsingInstance redirects.
- site_url_ = SiteInstanceImpl::GetSiteForURL(
- starting_site_instance_->GetIsolationContext(), common_params_.url);
+ site_url_ = GetSiteForCommonParamsURL();
// Compute the redirect chain.
// TODO(clamy): Try to simplify this and have the redirects be part of
// CommonNavigationParams.
- std::vector<GURL> redirect_chain;
+ redirect_chain_.clear();
if (!begin_params_->client_side_redirect_url.is_empty()) {
// |begin_params_->client_side_redirect_url| will be set when the navigation
// was triggered by a client-side redirect.
- redirect_chain.push_back(begin_params_->client_side_redirect_url);
+ redirect_chain_.push_back(begin_params_->client_side_redirect_url);
} else if (!commit_params_.redirects.empty()) {
// Redirects that were specified at NavigationRequest creation time should
// be added to the list of redirects. In particular, if the
@@ -845,24 +912,35 @@ void NavigationRequest::CreateNavigationHandle(bool is_for_commit) {
// during the navigation have been added to |commit_params_.redirects| and
// should be passed to the NavigationHandle.
for (const auto& url : commit_params_.redirects)
- redirect_chain.push_back(url);
+ redirect_chain_.push_back(url);
}
// Finally, add the current URL to the vector of redirects.
// Note: for NavigationRequests created at commit time, the current URL has
// been added to |commit_params_.redirects|, so don't add it a second time.
if (!is_for_commit)
- redirect_chain.push_back(common_params_.url);
+ redirect_chain_.push_back(common_params_.url);
net::HttpRequestHeaders headers;
headers.AddHeadersFromString(begin_params_->headers);
+ // Mirrors the logic in RenderFrameImpl::SendDidCommitProvisionalLoad.
+ if (common_params_.transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT) {
+ // If the page contained a client redirect (meta refresh,
+ // document.location), set the referrer appropriately.
+ sanitized_referrer_ = Referrer(
+ redirect_chain_[0], Referrer::SanitizeForRequest(
+ common_params_.url, common_params_.referrer)
+ .policy);
+ } else {
+ sanitized_referrer_ = Referrer::SanitizeForRequest(common_params_.url,
+ common_params_.referrer);
+ }
+
handle_state_ = NavigationRequest::INITIAL;
- std::unique_ptr<NavigationHandleImpl> navigation_handle =
- base::WrapUnique(new NavigationHandleImpl(
- this, redirect_chain, nav_entry_id_, std::move(headers),
- Referrer::SanitizeForRequest(common_params_.url,
- common_params_.referrer)));
+
+ std::unique_ptr<NavigationHandleImpl> navigation_handle = base::WrapUnique(
+ new NavigationHandleImpl(this, nav_entry_id_, std::move(headers)));
if (!frame_tree_node->navigation_request() && !is_for_commit) {
// A callback could have cancelled this request synchronously in which case
@@ -875,6 +953,11 @@ void NavigationRequest::CreateNavigationHandle(bool is_for_commit) {
throttle_runner_ = base::WrapUnique(
new NavigationThrottleRunner(this, navigation_handle_.get()));
+#if defined(OS_ANDROID)
+ navigation_handle_proxy_ =
+ std::make_unique<NavigationHandleProxy>(navigation_handle_.get());
+#endif
+
GetDelegate()->DidStartNavigation(navigation_handle_.get());
}
@@ -885,8 +968,21 @@ void NavigationRequest::ResetForCrossDocumentRestart() {
// 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_);
+
+#if defined(OS_ANDROID)
+ if (navigation_handle_proxy_)
+ navigation_handle_proxy_->DidFinish();
+#endif
+
+ // The below order of resets is necessary to avoid accessing null pointers.
+ // See https://crbug.com/958396.
navigation_handle_.reset();
+#if defined(OS_ANDROID)
+ if (navigation_handle_proxy_)
+ navigation_handle_proxy_.reset();
+#endif
+
// Reset the previously selected RenderFrameHost. This is expected to be null
// at the beginning of a new navigation. See https://crbug.com/936962.
DCHECK(render_frame_host_);
@@ -967,7 +1063,7 @@ void NavigationRequest::OnRequestRedirected(
// Update the navigation handle to point to the new url to ensure
// AwWebContents sees the new URL and thus passes that URL to onPageFinished
// (rather than passing the old URL).
- navigation_handle_->UpdateStateFollowingRedirect(
+ UpdateStateFollowingRedirect(
GURL(redirect_info.new_referrer),
base::Bind(&NavigationRequest::OnRedirectChecksComplete,
base::Unretained(this)));
@@ -1140,12 +1236,14 @@ void NavigationRequest::OnResponseStarted(
TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationRequest", this,
"OnResponseStarted");
state_ = RESPONSE_STARTED;
+ response_ = response;
+ ssl_info_ = response->head.ssl_info;
// Check if the response should be sent to a renderer.
response_should_be_rendered_ =
- !is_download_ && (!response->head.headers.get() ||
- (response->head.headers->response_code() != 204 &&
- response->head.headers->response_code() != 205));
+ !is_download && (!response->head.headers.get() ||
+ (response->head.headers->response_code() != 204 &&
+ response->head.headers->response_code() != 205));
// Response that will not commit should be marked as aborted in the
// NavigationHandle.
@@ -1157,8 +1255,9 @@ void NavigationRequest::OnResponseStarted(
// Update the AppCache params of the commit params.
commit_params_.appcache_host_id =
navigation_handle_->appcache_handle()
- ? navigation_handle_->appcache_handle()->appcache_host_id()
- : blink::mojom::kAppCacheNoHostId;
+ ? base::make_optional(
+ navigation_handle_->appcache_handle()->appcache_host_id())
+ : base::nullopt;
// Update fetch start timing. While NavigationRequest updates fetch start
// timing for redirects, it's not aware of service worker interception so
@@ -1215,7 +1314,6 @@ void NavigationRequest::OnResponseStarted(
if (response_should_be_rendered_) {
render_frame_host_ =
frame_tree_node_->render_manager()->GetFrameHostForNavigation(*this);
- VerifyLoaderAndRenderFrameHostExpectations();
NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL(
render_frame_host_, common_params_.url);
} else {
@@ -1252,11 +1350,8 @@ void NavigationRequest::OnResponseStarted(
common_params_.previews_state, navigation_handle_.get(),
response->head.headers.get());
- // Store the response and the URLLoaderClient endpoints until checks have been
- // processed.
- response_ = response;
+ // Store the URLLoaderClient endpoints until checks have been processed.
url_loader_client_endpoints_ = std::move(url_loader_client_endpoints);
- ssl_info_ = response->head.ssl_info;
subresource_loader_params_ = std::move(subresource_loader_params);
@@ -1295,8 +1390,8 @@ void NavigationRequest::OnResponseStarted(
// know how to display the content. We follow Firefox here and show our
// own error page instead of intercepting the request as a stream or a
// download.
- if (is_download_ && (response->head.headers.get() &&
- (response->head.headers->response_code() / 100 != 2))) {
+ if (is_download && (response->head.headers.get() &&
+ (response->head.headers->response_code() / 100 != 2))) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_INVALID_RESPONSE),
false /* skip_throttles */, base::nullopt /* error_page_content */,
@@ -1418,15 +1513,8 @@ void NavigationRequest::OnRequestFailedInternal(
// Sanity check that we haven't changed the RenderFrameHost picked for the
// error page in OnRequestFailedInternal when running the WillFailRequest
// checks.
- // TODO(https://crbug.com/936962): Replace this by a CHECK when the bug is
- // fixed.
- DCHECK(!render_frame_host_ || render_frame_host_ == render_frame_host);
- if (render_frame_host_ && render_frame_host_ != render_frame_host)
- base::debug::DumpWithoutCrashing();
+ CHECK(!render_frame_host_ || render_frame_host_ == render_frame_host);
render_frame_host_ = render_frame_host;
- VerifyLoaderAndRenderFrameHostExpectations();
-
- DCHECK(render_frame_host_);
// The check for WebUI should be performed only if error page isolation is
// enabled for this failed navigation. It is possible for subframe error page
@@ -1653,8 +1741,9 @@ void NavigationRequest::OnStartChecksComplete(
frame_tree_node_->devtools_frame_token()),
std::move(navigation_ui_data),
navigation_handle_->service_worker_handle(),
- navigation_handle_->appcache_handle(), this);
- VerifyLoaderAndRenderFrameHostExpectations();
+ navigation_handle_->appcache_handle(),
+ std::move(prefetched_signed_exchange_cache_), this);
+ DCHECK(!render_frame_host_);
}
void NavigationRequest::OnRedirectChecksComplete(
@@ -1931,6 +2020,13 @@ void NavigationRequest::CommitNavigation() {
render_frame_host_->GetProcess()->GetID(),
render_frame_host_->GetRoutingID(), &service_worker_provider_info);
}
+ if (subresource_loader_params_ &&
+ !subresource_loader_params_->prefetched_signed_exchanges.empty()) {
+ DCHECK(base::FeatureList::IsEnabled(
+ features::kSignedExchangeSubresourcePrefetch));
+ commit_params_.prefetched_signed_exchanges =
+ std::move(subresource_loader_params_->prefetched_signed_exchanges);
+ }
render_frame_host_->CommitNavigation(
this, response_.get(), std::move(url_loader_client_endpoints_),
common_params_, commit_params_, is_view_source_,
@@ -1990,10 +2086,7 @@ void NavigationRequest::RenderProcessHostDestroyed(RenderProcessHost* host) {
void NavigationRequest::UpdateSiteURL(
RenderProcessHost* post_redirect_process) {
- // TODO(alexmos): Using |starting_site_instance_|'s IsolationContext may not
- // be correct for cross-BrowsingInstance redirects.
- GURL new_site_url = SiteInstanceImpl::GetSiteForURL(
- starting_site_instance_->GetIsolationContext(), common_params_.url);
+ GURL new_site_url = GetSiteForCommonParamsURL();
int post_redirect_process_id = post_redirect_process
? post_redirect_process->GetID()
: ChildProcessHost::kInvalidUniqueID;
@@ -2084,6 +2177,17 @@ net::Error NavigationRequest::CheckContentSecurityPolicy(
FrameTreeNode* parent_ftn = frame_tree_node()->parent();
RenderFrameHostImpl* parent =
parent_ftn ? parent_ftn->current_frame_host() : nullptr;
+ if (!parent && frame_tree_node()
+ ->current_frame_host()
+ ->GetRenderViewHost()
+ ->GetDelegate()
+ ->IsPortal()) {
+ parent = frame_tree_node()
+ ->render_manager()
+ ->GetOuterDelegateNode()
+ ->current_frame_host()
+ ->GetParent();
+ }
// TODO(andypaicu,https://crbug.com/837627): the current_frame_host is the
// wrong RenderFrameHost. We should be using the navigation initiator
@@ -2232,18 +2336,6 @@ bool NavigationRequest::IsSameDocument() const {
return FrameMsg_Navigate_Type::IsSameDocument(common_params_.navigation_type);
}
-void NavigationRequest::VerifyLoaderAndRenderFrameHostExpectations() {
- if (!loader_ || !render_frame_host_)
- return;
- FrameMsg_Navigate_Type::Value navigation_type =
- common_params_.navigation_type;
- base::debug::Alias(&navigation_type);
- NavigationState state = state_;
- base::debug::Alias(&state);
- DEBUG_ALIAS_FOR_GURL(url, common_params_.url);
- base::debug::DumpWithoutCrashing();
-}
-
int NavigationRequest::EstimateHistoryOffset() {
if (common_params_.should_replace_current_entry)
return 0;
@@ -2488,8 +2580,7 @@ void NavigationRequest::WillRedirectRequest(
TRACE_EVENT_ASYNC_STEP_INTO1("navigation", "NavigationRequest", this,
"WillRedirectRequest", "url",
common_params_.url.possibly_invalid_spec());
- navigation_handle_->UpdateStateFollowingRedirect(new_referrer_url,
- std::move(callback));
+ UpdateStateFollowingRedirect(new_referrer_url, std::move(callback));
UpdateSiteURL(post_redirect_process);
if (IsSelfReferentialURL()) {
@@ -2566,4 +2657,123 @@ bool NavigationRequest::IsSelfReferentialURL() {
return false;
}
+void NavigationRequest::DidCommitNavigation(
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
+ bool navigation_entry_committed,
+ bool did_replace_entry,
+ const GURL& previous_url,
+ NavigationType navigation_type) {
+ common_params_.url = params.url;
+ did_replace_entry_ = did_replace_entry;
+ should_update_history_ = params.should_update_history;
+ previous_url_ = previous_url;
+ base_url_ = params.base_url;
+ navigation_type_ = navigation_type;
+
+ // If an error page reloads, net_error_code might be 200 but we still want to
+ // count it as an error page.
+ if (params.base_url.spec() == kUnreachableWebDataURL ||
+ navigation_handle_->GetNetErrorCode() != net::OK) {
+ TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle",
+ navigation_handle_.get(),
+ "DidCommitNavigation: error page");
+ handle_state_ = DID_COMMIT_ERROR_PAGE;
+ } else {
+ TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle",
+ navigation_handle_.get(),
+ "DidCommitNavigation");
+ handle_state_ = DID_COMMIT;
+ }
+
+ navigation_handle_->StopCommitTimeout();
+
+ // Record metrics for the time it took to commit the navigation if it was to
+ // another document without error.
+ if (!IsSameDocument() && handle_state_ != DID_COMMIT_ERROR_PAGE) {
+ ui::PageTransition transition = common_params_.transition;
+ base::Optional<bool> is_background =
+ render_frame_host_->GetProcess()->IsProcessBackgrounded();
+ const base::TimeTicks& ready_to_commit_time =
+ navigation_handle_->ready_to_commit_time();
+
+ RecordStartToCommitMetrics(common_params_.navigation_start, transition,
+ ready_to_commit_time, is_background,
+ navigation_handle_->is_same_process_,
+ frame_tree_node_->IsMainFrame());
+ }
+
+ DCHECK(!frame_tree_node_->IsMainFrame() || navigation_entry_committed)
+ << "Only subframe navigations can get here without changing the "
+ << "NavigationEntry";
+ 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.
+ if (handle_state_ != DID_COMMIT_ERROR_PAGE &&
+ !frame_tree_node()->IsMainFrame()) {
+ // The last committed load in collapsed frames will be an error page with
+ // |kUnreachableWebDataURL|. Same-document navigation should not be
+ // possible.
+ DCHECK(!IsSameDocument() || !frame_tree_node()->is_collapsed());
+ frame_tree_node()->SetCollapsed(false);
+ }
+}
+
+GURL NavigationRequest::GetSiteForCommonParamsURL() const {
+ // TODO(alexmos): Using |starting_site_instance_|'s IsolationContext may not
+ // be correct for cross-BrowsingInstance redirects.
+ return SiteInstanceImpl::GetSiteForURL(
+ starting_site_instance_->GetIsolationContext(), common_params_.url);
+}
+
+// TODO(zetamoo): Try to merge this function inside its callers.
+void NavigationRequest::UpdateStateFollowingRedirect(
+ const GURL& new_referrer_url,
+ ThrottleChecksFinishedCallback callback) {
+ // The navigation should not redirect to a "renderer debug" url. It should be
+ // blocked in NavigationRequest::OnRequestRedirected or in
+ // ResourceLoader::OnReceivedRedirect.
+ // Note: the |common_params_.url| below is the post-redirect URL.
+ // See https://crbug.com/728398.
+ CHECK(!IsRendererDebugURL(common_params_.url));
+
+ // Update the navigation parameters.
+ if (!(common_params_.transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT)) {
+ sanitized_referrer_.url = new_referrer_url;
+ sanitized_referrer_ =
+ Referrer::SanitizeForRequest(common_params_.url, sanitized_referrer_);
+ }
+
+ was_redirected_ = true;
+ redirect_chain_.push_back(common_params_.url);
+
+ handle_state_ = PROCESSING_WILL_REDIRECT_REQUEST;
+
+#if defined(OS_ANDROID)
+ navigation_handle_proxy_->DidRedirect();
+#endif
+
+ navigation_handle_->SetCompleteCallback(std::move(callback));
+}
+
+void NavigationRequest::SetNavigationClient(
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ int32_t associated_site_instance_id) {
+ DCHECK(from_begin_navigation_ ||
+ common_params_.is_history_navigation_in_new_child_frame);
+ DCHECK(!request_navigation_client_);
+ if (!navigation_client.is_valid())
+ return;
+
+ request_navigation_client_ = mojom::NavigationClientAssociatedPtr();
+ request_navigation_client_.Bind(std::move(navigation_client));
+
+ // Binds the OnAbort callback
+ HandleInterfaceDisconnection(
+ &request_navigation_client_,
+ base::BindOnce(&NavigationRequest::OnRendererAbortedNavigation,
+ base::Unretained(this)));
+ associated_site_instance_id_ = associated_site_instance_id;
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_request.h b/chromium/content/browser/frame_host/navigation_request.h
index c3c83e31758..d56e176794f 100644
--- a/chromium/content/browser/frame_host/navigation_request.h
+++ b/chromium/content/browser/frame_host/navigation_request.h
@@ -13,24 +13,33 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/strings/string_util.h"
+#include "build/build_config.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigation_throttle_runner.h"
#include "content/browser/initiator_csp_context.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
+#include "content/browser/navigation_subresource_loader_params.h"
#include "content/common/content_export.h"
#include "content/common/frame_message_enums.h"
#include "content/common/navigation_params.h"
#include "content/common/navigation_params.mojom.h"
-#include "content/common/navigation_subresource_loader_params.h"
#include "content/public/browser/navigation_throttle.h"
+#include "content/public/browser/navigation_type.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/common/previews_state.h"
+#if defined(OS_ANDROID)
+#include "base/android/scoped_java_ref.h"
+#include "content/browser/android/navigation_handle_proxy.h"
+#endif
+
namespace network {
class ResourceRequestBody;
struct URLLoaderCompletionStatus;
}
+struct FrameHostMsg_DidCommitProvisionalLoad_Params;
+
namespace content {
class FrameNavigationEntry;
@@ -40,6 +49,7 @@ class NavigationURLLoader;
class NavigationData;
class NavigationUIData;
class NavigatorDelegate;
+class PrefetchedSignedExchangeCache;
class SiteInstanceImpl;
struct SubresourceLoaderParams;
@@ -139,7 +149,9 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate,
bool override_user_agent,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
mojom::NavigationClientAssociatedPtrInfo navigation_client,
- blink::mojom::NavigationInitiatorPtr navigation_initiator);
+ blink::mojom::NavigationInitiatorPtr navigation_initiator,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache);
// Creates a request at commit time. This should only be used for
// renderer-initiated same-document navigations, and navigations whose
@@ -347,6 +359,74 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate,
return throttle_runner_->GetDeferringThrottle();
}
+ // Called when the navigation was committed.
+ // This will update the |handle_state_|.
+ // |navigation_entry_committed| indicates whether the navigation changed which
+ // NavigationEntry is current.
+ // |did_replace_entry| is true if the committed entry has replaced the
+ // existing one. A non-user initiated redirect causes such replacement.
+ void DidCommitNavigation(
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
+ bool navigation_entry_committed,
+ bool did_replace_entry,
+ const GURL& previous_url,
+ NavigationType navigation_type);
+
+ NavigationType navigation_type() const {
+ DCHECK_GE(handle_state_, DID_COMMIT);
+ return navigation_type_;
+ }
+
+ const GURL& base_url() { return base_url_; }
+
+ bool did_replace_entry() const {
+ DCHECK(handle_state_ == DID_COMMIT ||
+ handle_state_ == DID_COMMIT_ERROR_PAGE);
+ return did_replace_entry_;
+ }
+
+ bool should_update_history() const {
+ DCHECK(handle_state_ == DID_COMMIT ||
+ handle_state_ == DID_COMMIT_ERROR_PAGE);
+ return should_update_history_;
+ }
+
+ bool subframe_entry_committed() const {
+ DCHECK(!frame_tree_node_->IsMainFrame());
+ DCHECK(handle_state_ == DID_COMMIT ||
+ handle_state_ == DID_COMMIT_ERROR_PAGE);
+ return subframe_entry_committed_;
+ }
+
+ const GURL& previous_url() const {
+ DCHECK(handle_state_ == DID_COMMIT ||
+ handle_state_ == DID_COMMIT_ERROR_PAGE);
+ return previous_url_;
+ }
+
+
+#if defined(OS_ANDROID)
+ // Returns a reference to |navigation_handle_| Java counterpart. It is used
+ // by Java WebContentsObservers.
+ base::android::ScopedJavaGlobalRef<jobject> java_navigation_handle() {
+ return navigation_handle_proxy_->java_navigation_handle();
+ }
+#endif
+
+ bool was_redirected() { return was_redirected_; }
+
+ std::vector<GURL>& redirect_chain() { return redirect_chain_; }
+
+ Referrer& sanitized_referrer() { return sanitized_referrer_; }
+
+ // This should be a private method. The only valid reason to be used
+ // outside of the class constructor is in the case of an initial history
+ // navigation in a subframe. This allows a browser-initiated NavigationRequest
+ // to be canceled by the renderer.
+ void SetNavigationClient(
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ int32_t associated_site_instance_id);
+
private:
// TODO(clamy): Transform NavigationHandleImplTest into NavigationRequestTest
// once NavigationHandleImpl has become a wrapper around NavigationRequest.
@@ -495,13 +575,6 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate,
// Inform the RenderProcessHost to no longer expect a navigation.
void ResetExpectedProcess();
- // https://crbug.com/936962 happens when a |render_frame_host_| has been
- // selected and the |loader_| calls OnRequestFailed(). This shouldn't be
- // possible, because |render_frame_host_| and |loader_| can't be non-null at
- // the same time.
- // TODO(https://crbug.com/936962): Remove this when the bug is fixed.
- void VerifyLoaderAndRenderFrameHostExpectations();
-
// Compute the history offset of the new document compared to the current one.
// See navigation_history_offset_ for more details.
int EstimateHistoryOffset();
@@ -576,8 +649,20 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate,
// RenderProcessHostObserver implementation.
void RenderProcessHostDestroyed(RenderProcessHost* host) override;
+ void RecordNavigationMetrics() const;
+
+ // Helper function that computes the site URL for |common_params_.url|.
+ // Note: |site_url_| should only be updated with the result of this function.
+ GURL GetSiteForCommonParamsURL() const;
+
+ // Updates the state of the navigation handle after encountering a server
+ // redirect.
+ void UpdateStateFollowingRedirect(const GURL& new_referrer_url,
+ ThrottleChecksFinishedCallback callback);
+
FrameTreeNode* frame_tree_node_;
+ // Invariant: At least one of |loader_| or |render_frame_host_| is null.
RenderFrameHostImpl* render_frame_host_ = nullptr;
// Initialized on creation of the NavigationRequest. Sent to the renderer when
@@ -612,6 +697,12 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate,
std::unique_ptr<NavigationHandleImpl> navigation_handle_;
std::unique_ptr<NavigationURLLoader> loader_;
+#if defined(OS_ANDROID)
+ // For each C++ NavigationHandle, there is a Java counterpart. It is the JNI
+ // bridge in between the two.
+ std::unique_ptr<NavigationHandleProxy> navigation_handle_proxy_;
+#endif
+
// These next items are used in browser-initiated navigations to store
// information from the NavigationEntryImpl that is required after request
// creation time.
@@ -670,7 +761,8 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate,
base::Closure on_start_checks_complete_closure_;
// Used in the network service world to pass the subressource loader params
- // to the renderer. Used by AppCache and ServiceWorker.
+ // to the renderer. Used by AppCache and ServiceWorker, and
+ // SignedExchangeSubresourcePrefetch.
base::Optional<SubresourceLoaderParams> subresource_loader_params_;
// See comment on accessor.
@@ -708,6 +800,48 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate,
// responsible for notifying them about the various navigation events.
std::unique_ptr<NavigationThrottleRunner> throttle_runner_;
+ // Indicates whether the navigation changed which NavigationEntry is current.
+ bool subframe_entry_committed_ = false;
+
+ // True if the committed entry has replaced the existing one.
+ // A non-user initiated redirect causes such replacement.
+ bool did_replace_entry_ = false;
+
+ // Set to false if we want to update the session history but not update the
+ // browser history. E.g., on unreachable urls.
+ bool should_update_history_ = false;
+
+ // The previous main frame URL that the user was on. This may be empty if
+ // there was no last committed entry.
+ GURL previous_url_;
+
+ // The base URL for the page's document when the frame was committed.
+ GURL base_url_;
+
+ // The type of navigation that just occurred. Note that not all types of
+ // navigations in the enum are valid here, since some of them don't actually
+ // cause a "commit" and won't generate this notification.
+ NavigationType navigation_type_ = NAVIGATION_TYPE_UNKNOWN;
+
+ // The chain of redirects, including client-side redirect and the current URL.
+ // TODO(zetamoo): Try to improve redirect tracking during navigation.
+ std::vector<GURL> redirect_chain_;
+
+ // TODO(zetamoo): Try to remove this by always sanitizing the referrer in
+ // common_params_.
+ Referrer sanitized_referrer_;
+
+ bool was_redirected_ = false;
+
+ // Used when SignedExchangeSubresourcePrefetch is enabled to hold the
+ // prefetched signed exchanges. This is shared with the navigation initiator's
+ // RenderFrameHostImpl. This also means that only the navigations that were
+ // directly initiated by the frame that made the prefetches could use the
+ // prefetched resources, which is a different behavior from regular prefetches
+ // (where all prefetched resources are stored and shared in http cache).
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache_;
+
base::WeakPtrFactory<NavigationRequest> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(NavigationRequest);
diff --git a/chromium/content/browser/frame_host/navigator.cc b/chromium/content/browser/frame_host/navigator.cc
index 7cce6d26021..b1106e0bc99 100644
--- a/chromium/content/browser/frame_host/navigator.cc
+++ b/chromium/content/browser/frame_host/navigator.cc
@@ -5,6 +5,7 @@
#include "content/browser/frame_host/navigator.h"
#include "base/time/time.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
#include "content/public/browser/stream_handle.h"
namespace content {
@@ -19,7 +20,8 @@ NavigationController* Navigator::GetController() {
bool Navigator::StartHistoryNavigationInNewSubframe(
RenderFrameHostImpl* render_frame_host,
- const GURL& default_url) {
+ const GURL& default_url,
+ mojom::NavigationClientAssociatedPtrInfo* navigation_client) {
return false;
}
@@ -33,6 +35,8 @@ void Navigator::OnBeginNavigation(
mojom::BeginNavigationParamsPtr begin_params,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
mojom::NavigationClientAssociatedPtrInfo navigation_client,
- blink::mojom::NavigationInitiatorPtr navigation_initiator) {}
+ blink::mojom::NavigationInitiatorPtr navigation_initiator,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache) {}
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator.h b/chromium/content/browser/frame_host/navigator.h
index dae4b8d56ae..abc1a579838 100644
--- a/chromium/content/browser/frame_host/navigator.h
+++ b/chromium/content/browser/frame_host/navigator.h
@@ -18,7 +18,6 @@
class GURL;
struct FrameHostMsg_DidCommitProvisionalLoad_Params;
-struct FrameHostMsg_DidFailProvisionalLoadWithError_Params;
namespace base {
class TimeTicks;
@@ -32,6 +31,7 @@ namespace content {
class FrameNavigationEntry;
class FrameTreeNode;
+class PrefetchedSignedExchangeCache;
class RenderFrameHostImpl;
struct CommonNavigationParams;
@@ -55,7 +55,10 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
// The RenderFrameHostImpl has failed a provisional load.
virtual void DidFailProvisionalLoadWithError(
RenderFrameHostImpl* render_frame_host,
- const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {}
+ const GURL& url,
+ int error_code,
+ const base::string16& error_description,
+ bool showing_repost_interstitial) {}
// The RenderFrameHostImpl has failed to load the document.
virtual void DidFailLoadWithError(RenderFrameHostImpl* render_frame_host,
@@ -85,7 +88,8 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
// cases that we use a different URL from history than the frame's src.
virtual bool StartHistoryNavigationInNewSubframe(
RenderFrameHostImpl* render_frame_host,
- const GURL& default_url);
+ const GURL& default_url,
+ mojom::NavigationClientAssociatedPtrInfo* navigation_client);
// Navigation requests -------------------------------------------------------
@@ -149,7 +153,9 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
mojom::BeginNavigationParamsPtr begin_params,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
mojom::NavigationClientAssociatedPtrInfo navigation_client,
- blink::mojom::NavigationInitiatorPtr navigation_initiator);
+ blink::mojom::NavigationInitiatorPtr navigation_initiator,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache);
// Used to restart a navigation that was thought to be same-document in
// cross-document mode.
diff --git a/chromium/content/browser/frame_host/navigator_impl.cc b/chromium/content/browser/frame_host/navigator_impl.cc
index b16bcd8a1d6..249c92d1e41 100644
--- a/chromium/content/browser/frame_host/navigator_impl.cc
+++ b/chromium/content/browser/frame_host/navigator_impl.cc
@@ -21,6 +21,7 @@
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/frame_host/navigator_delegate.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
@@ -107,18 +108,20 @@ NavigationController* NavigatorImpl::GetController() {
void NavigatorImpl::DidFailProvisionalLoadWithError(
RenderFrameHostImpl* render_frame_host,
- const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
- VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec()
- << ", error_code: " << params.error_code
- << ", error_description: " << params.error_description
- << ", showing_repost_interstitial: "
- << params.showing_repost_interstitial
+ const GURL& url,
+ int error_code,
+ const base::string16& error_description,
+ bool showing_repost_interstitial) {
+ VLOG(1) << "Failed Provisional Load: " << url.possibly_invalid_spec()
+ << ", error_code: " << error_code
+ << ", error_description: " << error_description
+ << ", showing_repost_interstitial: " << showing_repost_interstitial
<< ", frame_id: " << render_frame_host->GetRoutingID();
- GURL validated_url(params.url);
+ GURL validated_url(url);
RenderProcessHost* render_process_host = render_frame_host->GetProcess();
render_process_host->FilterURL(false, &validated_url);
- if (net::ERR_ABORTED == params.error_code) {
+ if (net::ERR_ABORTED == error_code) {
// EVIL HACK ALERT! Ignore failed loads when we're showing interstitials.
// This means that the interstitial won't be torn down properly, which is
// bad. But if we have an interstitial, go back to another tab type, and
@@ -168,9 +171,10 @@ void NavigatorImpl::DidFailLoadWithError(
bool NavigatorImpl::StartHistoryNavigationInNewSubframe(
RenderFrameHostImpl* render_frame_host,
- const GURL& default_url) {
- return controller_->StartHistoryNavigationInNewSubframe(render_frame_host,
- default_url);
+ const GURL& default_url,
+ mojom::NavigationClientAssociatedPtrInfo* navigation_client) {
+ return controller_->StartHistoryNavigationInNewSubframe(
+ render_frame_host, default_url, navigation_client);
}
void NavigatorImpl::DidNavigate(
@@ -280,9 +284,9 @@ void NavigatorImpl::DidNavigate(
if (details.type != NAVIGATION_TYPE_NAV_IGNORE && delegate_) {
DCHECK_EQ(!render_frame_host->GetParent(),
did_navigate ? details.is_main_frame : false);
- navigation_request->navigation_handle()->DidCommitNavigation(
- params, did_navigate, details.did_replace_entry, details.previous_url,
- details.type);
+ navigation_request->DidCommitNavigation(params, did_navigate,
+ details.did_replace_entry,
+ details.previous_url, details.type);
navigation_request.reset();
}
@@ -336,7 +340,7 @@ void NavigatorImpl::Navigate(std::unique_ptr<NavigationRequest> request,
bool should_dispatch_beforeunload =
!FrameMsg_Navigate_Type::IsSameDocument(
request->common_params().navigation_type) &&
- !request->commit_params().is_history_navigation_in_new_child &&
+ !request->common_params().is_history_navigation_in_new_child_frame &&
frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(
false /* check_subframes_only */);
@@ -460,7 +464,7 @@ void NavigatorImpl::RequestOpenURL(
GetContentClient()->browser()->OverrideNavigationParams(
current_site_instance, &params.transition, &params.is_renderer_initiated,
- &params.referrer);
+ &params.referrer, &params.initiator_origin);
if (delegate_)
delegate_->OpenURL(params);
@@ -519,12 +523,13 @@ void NavigatorImpl::NavigateFromFrameProxy(
is_renderer_initiated = false;
}
+ base::Optional<url::Origin> final_initiator_origin = initiator_origin;
GetContentClient()->browser()->OverrideNavigationParams(
current_site_instance, &page_transition, &is_renderer_initiated,
- &referrer_to_use);
+ &referrer_to_use, &final_initiator_origin);
controller_->NavigateFromFrameProxy(
- render_frame_host, url, initiator_origin, is_renderer_initiated,
+ render_frame_host, url, final_initiator_origin, is_renderer_initiated,
source_site_instance, referrer_to_use, page_transition,
should_replace_current_entry, download_policy, method, post_body,
extra_headers, std::move(blob_url_loader_factory));
@@ -583,20 +588,34 @@ void NavigatorImpl::OnBeginNavigation(
mojom::BeginNavigationParamsPtr begin_params,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
mojom::NavigationClientAssociatedPtrInfo navigation_client,
- blink::mojom::NavigationInitiatorPtr navigation_initiator) {
+ blink::mojom::NavigationInitiatorPtr navigation_initiator,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache) {
// TODO(clamy): the url sent by the renderer should be validated with
// FilterURL.
// This is a renderer-initiated navigation.
DCHECK(frame_tree_node);
+ if (common_params.is_history_navigation_in_new_child_frame) {
+ // Try to find a FrameNavigationEntry that matches this frame instead, based
+ // on the frame's unique name. If this can't be found, fall back to the
+ // default path below.
+ if (frame_tree_node->navigator()->StartHistoryNavigationInNewSubframe(
+ frame_tree_node->current_frame_host(), common_params.url,
+ &navigation_client)) {
+ return;
+ }
+ }
+
NavigationRequest* ongoing_navigation_request =
frame_tree_node->navigation_request();
// Client redirects during the initial history navigation of a child frame
// should take precedence over the history navigation (despite being renderer-
// initiated). See https://crbug.com/348447 and https://crbug.com/691168.
- if (ongoing_navigation_request && ongoing_navigation_request->commit_params()
- .is_history_navigation_in_new_child) {
+ if (ongoing_navigation_request &&
+ ongoing_navigation_request->common_params()
+ .is_history_navigation_in_new_child_frame) {
// Preemptively clear this local pointer before deleting the request.
ongoing_navigation_request = nullptr;
frame_tree_node->ResetNavigationRequest(false, true);
@@ -647,7 +666,8 @@ void NavigatorImpl::OnBeginNavigation(
std::move(begin_params), controller_->GetLastCommittedEntryIndex(),
controller_->GetEntryCount(), override_user_agent,
std::move(blob_url_loader_factory), std::move(navigation_client),
- std::move(navigation_initiator)));
+ std::move(navigation_initiator),
+ std::move(prefetched_signed_exchange_cache)));
NavigationRequest* navigation_request = frame_tree_node->navigation_request();
// This frame has already run beforeunload before it sent this IPC. See if
diff --git a/chromium/content/browser/frame_host/navigator_impl.h b/chromium/content/browser/frame_host/navigator_impl.h
index 6e6daea9d95..7c0db61d766 100644
--- a/chromium/content/browser/frame_host/navigator_impl.h
+++ b/chromium/content/browser/frame_host/navigator_impl.h
@@ -42,8 +42,10 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
NavigationController* GetController() override;
void DidFailProvisionalLoadWithError(
RenderFrameHostImpl* render_frame_host,
- const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params)
- override;
+ const GURL& url,
+ int error_code,
+ const base::string16& error_description,
+ bool showing_repost_interstitial) override;
void DidFailLoadWithError(RenderFrameHostImpl* render_frame_host,
const GURL& url,
int error_code,
@@ -54,7 +56,8 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
bool was_within_same_document) override;
bool StartHistoryNavigationInNewSubframe(
RenderFrameHostImpl* render_frame_host,
- const GURL& default_url) override;
+ const GURL& default_url,
+ mojom::NavigationClientAssociatedPtrInfo* navigation_client) override;
void Navigate(std::unique_ptr<NavigationRequest> request,
ReloadType reload_type,
RestoreType restore_type) override;
@@ -95,7 +98,9 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
mojom::BeginNavigationParamsPtr begin_params,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
mojom::NavigationClientAssociatedPtrInfo navigation_client,
- blink::mojom::NavigationInitiatorPtr navigation_initiator) override;
+ blink::mojom::NavigationInitiatorPtr navigation_initiator,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache) override;
void RestartNavigationAsCrossDocument(
std::unique_ptr<NavigationRequest> navigation_request) override;
void OnAbortNavigation(FrameTreeNode* frame_tree_node) override;
diff --git a/chromium/content/browser/frame_host/origin_policy_throttle.cc b/chromium/content/browser/frame_host/origin_policy_throttle.cc
index 93eb5b6ba0d..68d6799acd6 100644
--- a/chromium/content/browser/frame_host/origin_policy_throttle.cc
+++ b/chromium/content/browser/frame_host/origin_policy_throttle.cc
@@ -11,9 +11,11 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/no_destructor.h"
+#include "base/strings/strcat.h"
#include "build/buildflag.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/navigation_request.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/browser/navigation_handle.h"
@@ -30,21 +32,15 @@
namespace {
// Constants derived from the spec, https://github.com/WICG/origin-policy
-static const char* kDefaultPolicy = "0";
-static const char* kDeletePolicy = "0";
-static const char* kWellKnown = "/.well-known/origin-policy/";
-static const char* kReportTo = "report-to";
-static const char* kPolicy = "policy";
+static constexpr const char* kDeletePolicy = "0";
+static constexpr const char* kReportTo = "report-to";
+static constexpr const char* kPolicy = "policy";
// Marker for (temporarily) exempted origins.
// TODO(vogelheim): Make sure this is outside the value space for policy
// names. A name with a comma in it shouldn't be allowed, but
// I don't think we presently check this anywhere.
-static const char* kExemptedOriginPolicy = "exception,";
-
-// Maximum policy size (implementation-defined limit in bytes).
-// (Limit copied from network::SimpleURLLoader::kMaxBoundedStringDownloadSize.)
-static const size_t kMaxPolicySize = 1024 * 1024;
+static constexpr const char* kExemptedOriginPolicyVersion = "exception,";
} // namespace
namespace content {
@@ -56,9 +52,7 @@ void OriginPolicyAddExceptionFor(const GURL& url) {
}
// static
-bool OriginPolicyThrottle::ShouldRequestOriginPolicy(
- const GURL& url,
- std::string* request_version) {
+bool OriginPolicyThrottle::ShouldRequestOriginPolicy(const GURL& url) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
bool origin_policy_enabled =
base::FeatureList::IsEnabled(features::kOriginPolicy) ||
@@ -70,13 +64,6 @@ bool OriginPolicyThrottle::ShouldRequestOriginPolicy(
if (!url.SchemeIs(url::kHttpsScheme))
return false;
- if (request_version) {
- const KnownVersionMap& versions = GetKnownVersions();
- const auto iter = versions.find(url::Origin::Create(url));
- bool has_version = iter != versions.end();
- bool use_default = !has_version || iter->second == kExemptedOriginPolicy;
- *request_version = use_default ? std::string(kDefaultPolicy) : iter->second;
- }
return true;
}
@@ -95,14 +82,13 @@ OriginPolicyThrottle::MaybeCreateThrottleFor(NavigationHandle* handle) {
// TODO(vogelheim): Rewrite & hoist up this DCHECK to ensure that ..HasHeader
// and ShouldRequestOriginPolicy are always equal on entry to the method.
// This depends on https://crbug.com/881234 being fixed.
- DCHECK(OriginPolicyThrottle::ShouldRequestOriginPolicy(handle->GetURL(),
- nullptr));
+ DCHECK(OriginPolicyThrottle::ShouldRequestOriginPolicy(handle->GetURL()));
return base::WrapUnique(new OriginPolicyThrottle(handle));
}
// static
void OriginPolicyThrottle::AddExceptionFor(const GURL& url) {
- GetKnownVersions()[url::Origin::Create(url)] = kExemptedOriginPolicy;
+ GetKnownVersions()[url::Origin::Create(url)] = kExemptedOriginPolicyVersion;
}
OriginPolicyThrottle::~OriginPolicyThrottle() {}
@@ -128,6 +114,10 @@ OriginPolicyThrottle::WillProcessResponse() {
if (!navigation_handle()->GetResponseHeaders())
return NavigationThrottle::PROCEED;
+ // TODO(andypaicu):
+ // This entire logic needs to be moved to OriginPolicyManager with the
+ // store migration.
+
// This determines whether and which policy version applies and fetches it.
//
// Inputs are the kSecOriginPolicy HTTP header, and the version
@@ -157,7 +147,7 @@ OriginPolicyThrottle::WillProcessResponse() {
}
// Process policy exceptions.
- if (iter != versions.end() && iter->second == kExemptedOriginPolicy) {
+ if (iter != versions.end() && iter->second == kExemptedOriginPolicyVersion) {
return NavigationThrottle::PROCEED;
}
@@ -166,20 +156,39 @@ OriginPolicyThrottle::WillProcessResponse() {
return NavigationThrottle::PROCEED;
}
- if (!header_found)
- response_version = iter->second;
- else if (iter == versions.end())
+ std::string header;
+ navigation_handle()->GetResponseHeaders()->GetNormalizedHeader(
+ net::HttpRequestHeaders::kSecOriginPolicy, &header);
+
+ if (!header_found) {
+ // TODO(andypaicu):
+ // This is an absolute hack that will go away when we move the in-memory
+ // store to the network service OriginPolicyManager. Until then, if we have
+ // a cached policy version and we receive a request with no header set, we
+ // build this artificial header to let OriginPolicyManager know where to
+ // retrieve the policy from.
+ header = base::StrCat({"policy=", iter->second});
+ } else if (iter == versions.end()) {
versions.insert(std::make_pair(origin, response_version));
- else
+ } else {
iter->second = response_version;
+ }
+
+ network::OriginPolicyManager::RetrieveOriginPolicyCallback
+ origin_policy_manager_done = base::BindOnce(
+ &OriginPolicyThrottle::OnOriginPolicyManagerRetrieveDone,
+ base::Unretained(this));
+ SiteInstance* site_instance = navigation_handle()->GetStartingSiteInstance();
+ StoragePartitionImpl* storage_partition =
+ static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
+ site_instance->GetBrowserContext(), site_instance));
+
+ network::mojom::OriginPolicyManager* origin_policy_manager =
+ storage_partition->GetOriginPolicyManagerForBrowserProcess();
+
+ origin_policy_manager->RetrieveOriginPolicy(
+ origin, header, std::move(origin_policy_manager_done));
- FetchCallback done =
- base::BindOnce(&OriginPolicyThrottle::OnTheGloriousPolicyHasArrived,
- base::Unretained(this));
- RedirectCallback redirect = base::BindRepeating(
- &OriginPolicyThrottle::OnRedirect, base::Unretained(this));
- FetchPolicy(GetPolicyURL(response_version), std::move(done),
- std::move(redirect));
return NavigationThrottle::DEFER;
}
@@ -230,12 +239,13 @@ OriginPolicyThrottle::GetRequestedPolicyAndReportGroupFromHeaderString(
net::HttpUtil::NameValuePairsIterator iter(header.cbegin(), header.cend(),
',');
while (iter.GetNext()) {
- std::string token_value = net::HttpUtil::TrimLWS(iter.value()).as_string();
+ std::string token_value =
+ net::HttpUtil::TrimLWS(iter.value_piece()).as_string();
bool is_token = net::HttpUtil::IsToken(token_value);
- if (iter.name() == kPolicy) {
+ if (iter.name_piece() == kPolicy) {
valid &= is_token && policy.empty();
policy = token_value;
- } else if (iter.name() == kReportTo) {
+ } else if (iter.name_piece() == kReportTo) {
valid &= is_token && report_to.empty();
report_to = token_value;
}
@@ -251,115 +261,19 @@ const url::Origin OriginPolicyThrottle::GetRequestOrigin() const {
return url::Origin::Create(navigation_handle()->GetURL());
}
-const GURL OriginPolicyThrottle::GetPolicyURL(
- const std::string& version) const {
- return GURL(GetRequestOrigin().Serialize() + kWellKnown + version);
-}
-
-void OriginPolicyThrottle::FetchPolicy(const GURL& url,
- FetchCallback done,
- RedirectCallback redirect) {
- // 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 and configure the SimpleURLLoader for the policy.
- std::unique_ptr<network::ResourceRequest> policy_request =
- std::make_unique<network::ResourceRequest>();
- policy_request->url = url;
- policy_request->request_initiator = url::Origin::Create(url);
- policy_request->load_flags = net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_AUTH_DATA;
- url_loader_ = network::SimpleURLLoader::Create(std::move(policy_request),
- traffic_annotation);
- url_loader_->SetOnRedirectCallback(std::move(redirect));
-
- // Obtain the URLLoaderFactory from the NavigationHandle.
- SiteInstance* site_instance = navigation_handle()->GetStartingSiteInstance();
- StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
- site_instance->GetBrowserContext(), site_instance);
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
- storage_partition->GetURLLoaderFactoryForBrowserProcess();
-
- network::mojom::URLLoaderFactory* factory =
- url_loader_factory_for_testing_ ? url_loader_factory_for_testing_.get()
- : url_loader_factory.get();
-
- // Start the download, and pass the callback for when we're finished.
- url_loader_->DownloadToString(factory, std::move(done), kMaxPolicySize);
-}
-
-void OriginPolicyThrottle::InjectPolicyForTesting(
- const std::string& policy_content) {
- OnTheGloriousPolicyHasArrived(std::make_unique<std::string>(policy_content));
-}
-
-void OriginPolicyThrottle::SetURLLoaderFactoryForTesting(
- std::unique_ptr<network::mojom::URLLoaderFactory>
- url_loader_factory_for_testing) {
- url_loader_factory_for_testing_ = std::move(url_loader_factory_for_testing);
-}
-
-void OriginPolicyThrottle::OnTheGloriousPolicyHasArrived(
- std::unique_ptr<std::string> policy_content) {
- // Release resources associated with the loading.
- url_loader_.reset();
-
- // Fail hard if the policy could not be loaded.
- if (!policy_content) {
- CancelNavigation(OriginPolicyErrorReason::kCannotLoadPolicy);
- return;
- }
-
- // TODO(vogelheim): Determine whether we need to parse or sanity check
- // the policy content at this point.
-
- static_cast<NavigationHandleImpl*>(navigation_handle())
- ->navigation_request()
- ->SetOriginPolicy(*policy_content);
- Resume();
-}
-
-void OriginPolicyThrottle::OnRedirect(
- const net::RedirectInfo& redirect_info,
- const network::ResourceResponseHead& response_head,
- std::vector<std::string>* to_be_removed_headers) {
- // Fail hard if the policy response follows a redirect.
- url_loader_.reset(); // Cancel the request while it's ongoing.
- CancelNavigation(OriginPolicyErrorReason::kPolicyShouldNotRedirect);
-}
-
-void OriginPolicyThrottle::CancelNavigation(OriginPolicyErrorReason reason) {
+void OriginPolicyThrottle::CancelNavigation(OriginPolicyErrorReason reason,
+ const GURL& policy_url) {
base::Optional<std::string> error_page =
GetContentClient()->browser()->GetOriginPolicyErrorPage(
reason, navigation_handle());
CancelDeferredNavigation(NavigationThrottle::ThrottleCheckResult(
NavigationThrottle::CANCEL, net::ERR_BLOCKED_BY_CLIENT, error_page));
- Report(reason);
+ Report(reason, policy_url);
}
#if BUILDFLAG(ENABLE_REPORTING)
-void OriginPolicyThrottle::Report(OriginPolicyErrorReason reason) {
+void OriginPolicyThrottle::Report(OriginPolicyErrorReason reason,
+ const GURL& policy_url) {
const PolicyVersionAndReportTo header_values =
GetRequestedPolicyAndReportGroupFromHeader();
if (header_values.report_to.empty())
@@ -386,9 +300,7 @@ void OriginPolicyThrottle::Report(OriginPolicyErrorReason reason) {
}
base::DictionaryValue report_body;
- report_body.SetKey(
- "origin_policy_url",
- base::Value(GetPolicyURL(header_values.policy_version).spec()));
+ report_body.SetKey("origin_policy_url", base::Value(policy_url.spec()));
report_body.SetKey("policy", base::Value(origin_policy_header));
report_body.SetKey("policy_error_reason", base::Value(reason_str));
@@ -401,7 +313,34 @@ void OriginPolicyThrottle::Report(OriginPolicyErrorReason reason) {
std::move(report_body));
}
#else
-void OriginPolicyThrottle::Report(OriginPolicyErrorReason reason) {}
+void OriginPolicyThrottle::Report(OriginPolicyErrorReason reason,
+ const GURL& policy_url) {}
#endif // BUILDFLAG(ENABLE_REPORTING)
+bool OriginPolicyThrottle::IsExemptedForTesting(const url::Origin& origin) {
+ KnownVersionMap& versions = GetKnownVersions();
+ auto iter = versions.find(origin);
+ if (iter != versions.end())
+ return iter->second == kExemptedOriginPolicyVersion;
+
+ return false;
+}
+
+void OriginPolicyThrottle::OnOriginPolicyManagerRetrieveDone(
+ const network::mojom::OriginPolicyPtr origin_policy) {
+ if (origin_policy->state != network::mojom::OriginPolicyState::kLoaded) {
+ CancelNavigation(OriginPolicyErrorReason::kCannotLoadPolicy,
+ origin_policy->policy_url);
+ return;
+ }
+
+ DCHECK(origin_policy->contents);
+ // TODO(vogelheim): Determine whether we need to parse or sanity check
+ // the policy content at this point.
+ static_cast<NavigationHandleImpl*>(navigation_handle())
+ ->navigation_request()
+ ->SetOriginPolicy(origin_policy->contents->raw_policy);
+ 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
index 82fed28eb31..1b984824b86 100644
--- a/chromium/content/browser/frame_host/origin_policy_throttle.h
+++ b/chromium/content/browser/frame_host/origin_policy_throttle.h
@@ -13,32 +13,28 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "content/public/browser/navigation_throttle.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/origin_policy_manager.mojom.h"
class GURL;
namespace url {
class Origin;
}
-namespace net {
-struct RedirectInfo;
-} // namespace net
-namespace network {
-struct ResourceResponseHead;
-class SimpleURLLoader;
-} // namespace network
namespace content {
class NavigationHandle;
enum class OriginPolicyErrorReason;
+// Constant derived from the spec, https://github.com/WICG/origin-policy
+static constexpr const char* kDefaultOriginPolicyVersion = "0";
+
// 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.
+// a policy should be requested, and 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.
@@ -50,10 +46,8 @@ class CONTENT_EXPORT OriginPolicyThrottle : public NavigationThrottle {
};
// 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);
+ // support). Returns whether the policy header should be sent.
+ static bool ShouldRequestOriginPolicy(const GURL& url);
// Create a throttle (if the request contains the appropriate header.
// The throttle will handle fetching of the policy and updating the
@@ -76,23 +70,15 @@ class CONTENT_EXPORT OriginPolicyThrottle : public NavigationThrottle {
using KnownVersionMap = std::map<url::Origin, std::string>;
static KnownVersionMap& GetKnownVersionsForTesting();
- void InjectPolicyForTesting(const std::string& policy_content);
-
- void SetURLLoaderFactoryForTesting(
- std::unique_ptr<network::mojom::URLLoaderFactory>
- url_loader_factory_for_testing);
-
+ // TODO(andypaicu): Remove this when we move the store to the network
+ // service layer.
static PolicyVersionAndReportTo
GetRequestedPolicyAndReportGroupFromHeaderStringForTesting(
const std::string& header);
- private:
- using FetchCallback = base::OnceCallback<void(std::unique_ptr<std::string>)>;
- using RedirectCallback =
- base::RepeatingCallback<void(const net::RedirectInfo&,
- const network::ResourceResponseHead&,
- std::vector<std::string>*)>;
+ static bool IsExemptedForTesting(const url::Origin& origin);
+ private:
explicit OriginPolicyThrottle(NavigationHandle* handle);
static KnownVersionMap& GetKnownVersions();
@@ -103,25 +89,13 @@ class CONTENT_EXPORT OriginPolicyThrottle : public NavigationThrottle {
GetRequestedPolicyAndReportGroupFromHeaderString(const std::string& header);
const url::Origin GetRequestOrigin() const;
- const GURL GetPolicyURL(const std::string& version) const;
- void FetchPolicy(const GURL& url,
- FetchCallback done,
- RedirectCallback redirect);
- void OnTheGloriousPolicyHasArrived(
- std::unique_ptr<std::string> policy_content);
- void OnRedirect(const net::RedirectInfo& redirect_info,
- const network::ResourceResponseHead& response_head,
- std::vector<std::string>* to_be_removed_headers);
- void CancelNavigation(OriginPolicyErrorReason reason);
-
- void Report(OriginPolicyErrorReason reason);
-
- // We may need the SimpleURLLoader to download the policy. The loader must
- // be kept alive while the load is ongoing.
- std::unique_ptr<network::SimpleURLLoader> url_loader_;
-
- std::unique_ptr<network::mojom::URLLoaderFactory>
- url_loader_factory_for_testing_;
+
+ void CancelNavigation(OriginPolicyErrorReason reason, const GURL& policy_url);
+
+ void Report(OriginPolicyErrorReason reason, const GURL& policy_url);
+
+ void OnOriginPolicyManagerRetrieveDone(
+ const network::mojom::OriginPolicyPtr origin_policy);
DISALLOW_COPY_AND_ASSIGN(OriginPolicyThrottle);
};
diff --git a/chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc b/chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc
index a7d968ab13b..6e1cc946956 100644
--- a/chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc
+++ b/chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc
@@ -4,19 +4,29 @@
#include "content/browser/frame_host/origin_policy_throttle.h"
+#include <utility>
+
#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/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_features.h"
#include "content/public/test/mock_navigation_handle.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_renderer_host.h"
#include "net/http/http_util.h"
#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace {
+constexpr const char kExampleManifestString[] = "{}";
+}
+
namespace content {
class OriginPolicyThrottleTest : public RenderViewHostTestHarness,
@@ -43,7 +53,7 @@ class OriginPolicyThrottleTest : public RenderViewHostTestHarness,
void CreateHandleFor(const GURL& url) {
net::HttpRequestHeaders headers;
- if (OriginPolicyThrottle::ShouldRequestOriginPolicy(url, nullptr))
+ if (OriginPolicyThrottle::ShouldRequestOriginPolicy(url))
headers.SetHeader(net::HttpRequestHeaders::kSecOriginPolicy, "0");
nav_handle_ = std::make_unique<MockNavigationHandle>(web_contents());
@@ -56,6 +66,38 @@ class OriginPolicyThrottleTest : public RenderViewHostTestHarness,
base::test::ScopedFeatureList features_;
};
+class TestOriginPolicyManager : public network::mojom::OriginPolicyManager {
+ public:
+ void RetrieveOriginPolicy(const url::Origin& origin,
+ const std::string& header_value,
+ RetrieveOriginPolicyCallback callback) override {
+ auto result = network::mojom::OriginPolicy::New();
+ result->state = network::mojom::OriginPolicyState::kLoaded;
+ result->contents = network::mojom::OriginPolicyContents::New();
+ result->contents->raw_policy = kExampleManifestString;
+ result->policy_url = origin.GetURL();
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&TestOriginPolicyManager::RunCallback,
+ base::Unretained(this), std::move(callback),
+ std::move(result)));
+ }
+ void RunCallback(RetrieveOriginPolicyCallback callback,
+ network::mojom::OriginPolicyPtr result) {
+ std::move(callback).Run(std::move(result));
+ }
+ network::mojom::OriginPolicyManagerPtr GetPtr() {
+ network::mojom::OriginPolicyManagerPtr ptr;
+ auto request = mojo::MakeRequest(&ptr);
+ binding_ =
+ std::make_unique<mojo::Binding<network::mojom::OriginPolicyManager>>(
+ this, std::move(request));
+
+ return ptr;
+ }
+ std::unique_ptr<mojo::Binding<network::mojom::OriginPolicyManager>> binding_;
+};
+
INSTANTIATE_TEST_SUITE_P(OriginPolicyThrottleTests,
OriginPolicyThrottleTest,
testing::Bool());
@@ -72,30 +114,12 @@ TEST_P(OriginPolicyThrottleTest, ShouldRequestOriginPolicy) {
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));
+ EXPECT_EQ(
+ enabled() && test_case.expect,
+ OriginPolicyThrottle::ShouldRequestOriginPolicy(GURL(test_case.url)));
}
}
-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, "0");
-
- 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(),
@@ -123,32 +147,39 @@ TEST_P(OriginPolicyThrottleTest, RunRequestEndToEnd) {
// is deferred.
const char* raw_headers =
"HTTP/1.1 200 OK\nSec-Origin-Policy: policy=policy-1\n\n";
- scoped_refptr<net::HttpResponseHeaders> headers =
- new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(raw_headers, strlen(raw_headers)));
+ auto headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(raw_headers));
+
+ // We set a test origin policy manager as during unit tests we can't reach
+ // the network service to retrieve a valid origin policy manager.
+ TestOriginPolicyManager test_origin_policy_manager;
NavigationHandleImpl* nav_handle =
static_cast<NavigationHandleImpl*>(navigation->GetNavigationHandle());
+ SiteInstance* site_instance = nav_handle->GetStartingSiteInstance();
+ static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetStoragePartition(site_instance->GetBrowserContext(),
+ site_instance))
+ ->SetOriginPolicyManagerForBrowserProcessForTesting(
+ test_origin_policy_manager.GetPtr());
+
nav_handle->set_response_headers_for_testing(headers);
navigation->ReadyToCommit();
EXPECT_TRUE(navigation->IsDeferred());
-
- // Set TestURLLoaderFactory because we could not make actual network requests
- // in this unit tests, but this test would make.
OriginPolicyThrottle* policy_throttle = static_cast<OriginPolicyThrottle*>(
nav_handle->GetDeferringThrottleForTesting());
EXPECT_TRUE(policy_throttle);
- policy_throttle->SetURLLoaderFactoryForTesting(
- std::make_unique<network::TestURLLoaderFactory>());
- // 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 = "{}";
- policy_throttle->InjectPolicyForTesting(policy);
+ // Wait until the navigation has been allowed to proceed.
+ navigation->Wait();
// At the end of the navigation, the navigation handle should have a copy
// of the origin policy.
- EXPECT_EQ(policy,
+ EXPECT_EQ(kExampleManifestString,
nav_handle->navigation_request()->common_params().origin_policy);
+ static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetStoragePartition(site_instance->GetBrowserContext(),
+ site_instance))
+ ->ResetOriginPolicyManagerForBrowserProcessForTesting();
}
TEST_P(OriginPolicyThrottleTest, AddException) {
@@ -159,13 +190,9 @@ TEST_P(OriginPolicyThrottleTest, AddException) {
OriginPolicyThrottle::GetKnownVersionsForTesting()[url::Origin::Create(url)] =
"abcd";
- std::string version;
- OriginPolicyThrottle::ShouldRequestOriginPolicy(url, &version);
- EXPECT_EQ(version, "abcd");
-
OriginPolicyThrottle::AddExceptionFor(url);
- OriginPolicyThrottle::ShouldRequestOriginPolicy(url, &version);
- EXPECT_EQ(version, "0");
+ EXPECT_TRUE(
+ OriginPolicyThrottle::IsExemptedForTesting(url::Origin::Create(url)));
}
TEST_P(OriginPolicyThrottleTest, AddExceptionEndToEnd) {
@@ -186,9 +213,8 @@ TEST_P(OriginPolicyThrottleTest, AddExceptionEndToEnd) {
// Fake a response with a policy header.
const char* raw_headers =
"HTTP/1.1 200 OK\nSec-Origin-Policy: policy=policy-1\n\n";
- scoped_refptr<net::HttpResponseHeaders> headers =
- new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(raw_headers, strlen(raw_headers)));
+ auto headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(raw_headers));
NavigationHandleImpl* nav_handle =
static_cast<NavigationHandleImpl*>(navigation->GetNavigationHandle());
nav_handle->set_response_headers_for_testing(headers);
@@ -198,10 +224,8 @@ TEST_P(OriginPolicyThrottleTest, AddExceptionEndToEnd) {
EXPECT_FALSE(navigation->IsDeferred());
// Also check that the header policy did not overwrite the exemption:
- std::string version;
- OriginPolicyThrottle::ShouldRequestOriginPolicy(
- GURL("https://example.org/bla"), &version);
- EXPECT_EQ(version, "0");
+ EXPECT_TRUE(OriginPolicyThrottle::IsExemptedForTesting(
+ url::Origin::Create(GURL("https://example.org/bla"))));
}
TEST(OriginPolicyThrottleTest, ParseHeaders) {
diff --git a/chromium/content/browser/frame_host/popup_menu_helper_mac.mm b/chromium/content/browser/frame_host/popup_menu_helper_mac.mm
index 85fab55ba45..097604da271 100644
--- a/chromium/content/browser/frame_host/popup_menu_helper_mac.mm
+++ b/chromium/content/browser/frame_host/popup_menu_helper_mac.mm
@@ -12,7 +12,7 @@
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
-#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
+#import "content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h"
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
#include "content/browser/renderer_host/webmenurunner_mac.h"
#import "ui/base/cocoa/base_view.h"
diff --git a/chromium/content/browser/frame_host/render_frame_host_delegate.cc b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
index 4373a41d886..b70f80a418e 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
@@ -27,7 +27,7 @@ const GURL& RenderFrameHostDelegate::GetMainFrameLastCommittedURL() {
}
bool RenderFrameHostDelegate::DidAddMessageToConsole(
- int32_t level,
+ blink::mojom::ConsoleMessageLevel log_level,
const base::string16& message,
int32_t line_no,
const base::string16& source_id) {
@@ -95,10 +95,6 @@ RenderFrameHostDelegate::GetGeolocationContext() {
return nullptr;
}
-device::mojom::WakeLock* RenderFrameHostDelegate::GetRendererWakeLock() {
- return nullptr;
-}
-
#if defined(OS_ANDROID)
void RenderFrameHostDelegate::GetNFC(device::mojom::NFCRequest request) {}
#endif
@@ -147,4 +143,9 @@ ukm::SourceId RenderFrameHostDelegate::GetUkmSourceIdForLastCommittedSource()
return ukm::kInvalidSourceId;
}
+RenderFrameHostImpl* RenderFrameHostDelegate::GetMainFrameForInnerDelegate(
+ FrameTreeNode* frame_tree_node) {
+ return nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_delegate.h b/chromium/content/browser/frame_host/render_frame_host_delegate.h
index c54ff3c8195..11763c79b26 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.h
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.h
@@ -29,6 +29,7 @@
#include "services/device/public/mojom/wake_lock.mojom.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/blink/public/common/mediastream/media_stream_request.h"
+#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
#include "ui/base/window_open_disposition.h"
#if defined(OS_WIN)
@@ -111,10 +112,11 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
virtual const GURL& GetMainFrameLastCommittedURL();
// A message was added to to the console.
- virtual bool DidAddMessageToConsole(int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id);
+ virtual bool DidAddMessageToConsole(
+ blink::mojom::ConsoleMessageLevel log_level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id);
// Called when a RenderFrame for |render_frame_host| is created in the
// renderer process. Use |RenderFrameDeleted| to listen for when this
@@ -249,9 +251,6 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// Gets the GeolocationContext associated with this delegate.
virtual device::mojom::GeolocationContext* GetGeolocationContext();
- // Gets the WakeLock that serves wake lock requests from the renderer.
- virtual device::mojom::WakeLock* GetRendererWakeLock();
-
#if defined(OS_ANDROID)
// Gets an NFC implementation within the context of this delegate.
virtual void GetNFC(device::mojom::NFCRequest request);
@@ -437,6 +436,12 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
virtual void AudioContextPlaybackStopped(RenderFrameHost* host,
int context_id) {}
+ // Returns the main frame of the inner delegate that is attached to this
+ // delegate using |frame_tree_node|. Returns nullptr if no such inner delegate
+ // exists.
+ virtual RenderFrameHostImpl* GetMainFrameForInnerDelegate(
+ FrameTreeNode* frame_tree_node);
+
protected:
virtual ~RenderFrameHostDelegate() {}
};
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 fdac7116419..bd596fdc462 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.cc
@@ -13,6 +13,7 @@
#include "base/command_line.h"
#include "base/containers/queue.h"
#include "base/debug/alias.h"
+#include "base/debug/dump_without_crashing.h"
#include "base/hash/hash.h"
#include "base/lazy_instance.h"
#include "base/memory/ptr_util.h"
@@ -68,12 +69,15 @@
#include "content/browser/interface_provider_filtering.h"
#include "content/browser/keyboard_lock/keyboard_lock_service_impl.h"
#include "content/browser/loader/prefetch_url_loader_service.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/log_console_message.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "content/browser/media/media_interface_proxy.h"
#include "content/browser/media/session/media_session_service_impl.h"
#include "content/browser/media/webaudio/audio_context_manager_impl.h"
+#include "content/browser/native_file_system/native_file_system_manager_impl.h"
+#include "content/browser/navigation_subresource_loader_params.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"
@@ -101,8 +105,8 @@
#include "content/browser/speech/speech_recognition_dispatcher_host.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/wake_lock/wake_lock_service_impl.h"
+#include "content/browser/webauth/authenticator_environment_impl.h"
#include "content/browser/webauth/authenticator_impl.h"
-#include "content/browser/webauth/scoped_virtual_authenticator_environment.h"
#include "content/browser/websockets/websocket_manager.h"
#include "content/browser/webui/url_data_manager_backend.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
@@ -118,7 +122,6 @@
#include "content/common/input/input_handler.mojom.h"
#include "content/common/inter_process_time_ticks_converter.h"
#include "content/common/navigation_params.h"
-#include "content/common/navigation_subresource_loader_params.h"
#include "content/common/render_message_filter.mojom.h"
#include "content/common/renderer.mojom.h"
#include "content/common/swapped_out_messages.h"
@@ -137,6 +140,7 @@
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/browser/site_isolation_policy.h"
+#include "content/public/browser/sms_service.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/stream_handle.h"
#include "content/public/browser/webvr_service_provider.h"
@@ -187,6 +191,7 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
#include "third_party/blink/public/common/messaging/transferable_message.h"
+#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
#include "third_party/blink/public/mojom/frame/frame_host_test_interface.mojom.h"
#include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom.h"
#include "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom.h"
@@ -423,11 +428,43 @@ void LogRendererKillCrashKeys(const GURL& site_url) {
}
base::Optional<url::Origin> GetOriginForURLLoaderFactory(
- GURL target_url,
- SiteInstanceImpl* site_instance) {
+ NavigationRequest* navigation_request) {
+ // Return a safe unique origin when there is no |navigation_request| (e.g.
+ // when RFHI::CommitNavigation is called via RFHI::NavigateToInterstitialURL).
+ if (!navigation_request)
+ return url::Origin();
+
+ // GetOriginForURLLoaderFactory should only be called at the ready-to-commit
+ // time, when the RFHI and process to commit the navigation are already known.
+ DCHECK_LE(NavigationRequest::RESPONSE_STARTED, navigation_request->state());
+ RenderFrameHostImpl* target_frame = navigation_request->render_frame_host();
+
+ // Check if this is loadDataWithBaseUrl (which needs special treatment).
+ const CommonNavigationParams& common_params =
+ navigation_request->common_params();
+ if (common_params.url.SchemeIs(url::kDataScheme) &&
+ !common_params.base_url_for_data_url.is_empty()) {
+ // A (potentially attacker-controlled) renderer process should not be able
+ // to use loadDataWithBaseUrl code path to initiate fetches on behalf of a
+ // victim origin (fetches controlled by attacker-provided
+ // |common_params.url| data: URL in a victim's origin from the
+ // attacker-provided |common_params.base_url_for_data_url|). Browser
+ // process should verify that |common_params.base_url_for_data_url| is empty
+ // for all renderer-initiated navigations (e.g. see
+ // VerifyBeginNavigationCommonParams), but as a defense-in-depth this is
+ // also asserted below.
+ CHECK(navigation_request->browser_initiated());
+
+ // loadDataWithBaseUrl submits a data: |common_params.url| (which has a
+ // unique origin), but commits that URL as if it came from
+ // |common_params.base_url_for_data_url|. See also
+ // https://crbug.com/976253.
+ return url::Origin::Create(common_params.base_url_for_data_url);
+ }
+
// TODO(lukasza, nasko): https://crbug.com/888079: Use exact origin, instead
// of falling back to site URL for about:blank and about:srcdoc.
- if (target_url.SchemeIs(url::kAboutScheme)) {
+ if (common_params.url.SchemeIs(url::kAboutScheme)) {
// |site_instance|'s site URL cannot be used as
// |request_initiator_site_lock| unless the site requires a dedicated
// process. Otherwise b.com may share a process associated with a.com, in
@@ -435,19 +472,19 @@ base::Optional<url::Origin> GetOriginForURLLoaderFactory(
// "http://nonisolated.invalid" in the future) and in that scenario
// |request_initiator| for requests from b.com should NOT be locked to
// a.com.
+ SiteInstanceImpl* site_instance = target_frame->GetSiteInstance();
if (!SiteInstanceImpl::ShouldLockToOrigin(
site_instance->GetIsolationContext(), site_instance->GetSiteURL()))
return base::nullopt;
-
return SiteInstanceImpl::GetRequestInitiatorSiteLock(
site_instance->GetSiteURL());
}
// In cases not covered above, URLLoaderFactory should be associated with the
- // origin of |target_url|. This works fine for all URLs, including data: URLs
- // (which should use an opaque origin for their subresource requests) and
- // blob: URLs (which embed their origin inside the |target_url|).
- return url::Origin::Create(target_url);
+ // origin of |common_params.url|. This works fine for all URLs, including
+ // data: URLs (which should use an opaque origin for their subresource
+ // requests) and blob: URLs (which embed their origin inside the URL).
+ return url::Origin::Create(common_params.url);
}
std::unique_ptr<blink::URLLoaderFactoryBundleInfo> CloneFactoryBundle(
@@ -456,6 +493,9 @@ std::unique_ptr<blink::URLLoaderFactoryBundleInfo> CloneFactoryBundle(
bundle->Clone().release()));
}
+// TODO(crbug.com/977040): Remove when no longer needed.
+const uint32_t kMaxCookieSameSiteDeprecationUrls = 20;
+
} // namespace
class RenderFrameHostImpl::DroppedInterfaceRequestLogger
@@ -766,7 +806,6 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
frame_tree_(frame_tree),
frame_tree_node_(frame_tree_node),
parent_(nullptr),
- render_widget_host_(nullptr),
routing_id_(routing_id),
is_waiting_for_swapout_ack_(false),
render_frame_created_(false),
@@ -805,6 +844,7 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
g_routing_id_frame_map.Get().emplace(
RenderFrameHostID(GetProcess()->GetID(), routing_id_), this);
site_instance_->AddObserver(this);
+ process_->AddObserver(this);
GetSiteInstance()->IncrementActiveFrameCount();
if (frame_tree_node_->parent()) {
@@ -834,12 +874,29 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
mojom::WidgetPtr widget;
GetRemoteInterfaces()->GetInterface(&widget);
- // TODO(avi): Once RenderViewHostImpl has-a RenderWidgetHostImpl, the main
- // render frame should probably start owning the RenderWidgetHostImpl,
- // so this logic checking for an already existing RWHI should be removed.
- // https://crbug.com/545684
- render_widget_host_ =
- RenderWidgetHostImpl::FromID(GetProcess()->GetID(), widget_routing_id);
+ if (!parent_) {
+ // For main frames, the RenderWidgetHost is owned by the RenderViewHost.
+ // TODO(https://crbug.com/545684): Once RenderViewHostImpl has-a
+ // RenderWidgetHostImpl, the main render frame should probably start
+ // owning the RenderWidgetHostImpl itself.
+ DCHECK(GetLocalRenderWidgetHost());
+ DCHECK_EQ(GetLocalRenderWidgetHost()->GetRoutingID(), widget_routing_id);
+ DCHECK(!GetLocalRenderWidgetHost()->owned_by_render_frame_host());
+
+ // Make the RenderWidgetHostImpl able to call the mojo Widget interface
+ // (implemented by the RenderWidgetImpl).
+ GetLocalRenderWidgetHost()->SetWidget(std::move(widget));
+ } else {
+ // For subframes, the RenderFrameHost directly creates and owns its
+ // RenderWidgetHost.
+ DCHECK_EQ(nullptr, GetLocalRenderWidgetHost());
+ DCHECK_EQ(nullptr, RenderWidgetHostImpl::FromID(GetProcess()->GetID(),
+ widget_routing_id));
+ owned_render_widget_host_ = RenderWidgetHostFactory::Create(
+ frame_tree_->render_widget_delegate(), GetProcess(),
+ widget_routing_id, std::move(widget), hidden);
+ owned_render_widget_host_->set_owned_by_render_frame_host(true);
+ }
mojom::WidgetInputHandlerAssociatedPtr widget_handler;
mojom::WidgetInputHandlerHostRequest host_request;
@@ -849,22 +906,12 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
frame_input_handler_->GetWidgetInputHandler(
mojo::MakeRequest(&widget_handler), std::move(host));
}
- if (!render_widget_host_) {
- DCHECK(frame_tree_node->parent());
- render_widget_host_ = RenderWidgetHostFactory::Create(
- frame_tree_->render_widget_delegate(), GetProcess(),
- widget_routing_id, std::move(widget), hidden);
- render_widget_host_->set_owned_by_render_frame_host(true);
- } else {
- DCHECK(!render_widget_host_->owned_by_render_frame_host());
- render_widget_host_->SetWidget(std::move(widget));
- }
if (!frame_tree_node_->parent())
- render_widget_host_->SetIntersectsViewport(true);
- render_widget_host_->SetFrameDepth(frame_tree_node_->depth());
- render_widget_host_->SetWidgetInputHandler(std::move(widget_handler),
- std::move(host_request));
- render_widget_host_->input_router()->SetFrameTreeNodeId(
+ GetLocalRenderWidgetHost()->SetIntersectsViewport(true);
+ GetLocalRenderWidgetHost()->SetFrameDepth(frame_tree_node_->depth());
+ GetLocalRenderWidgetHost()->SetWidgetInputHandler(std::move(widget_handler),
+ std::move(host_request));
+ GetLocalRenderWidgetHost()->input_router()->SetFrameTreeNodeId(
frame_tree_node_->frame_tree_node_id());
}
ResetFeaturePolicy();
@@ -910,12 +957,18 @@ RenderFrameHostImpl::~RenderFrameHostImpl() {
g_token_frame_map.Get().erase(*overlay_routing_token_);
site_instance_->RemoveObserver(this);
+ process_->RemoveObserver(this);
const bool was_created = render_frame_created_;
render_frame_created_ = false;
if (delegate_ && was_created)
delegate_->RenderFrameDeleted(this);
+#if !defined(OS_ANDROID)
+ AuthenticatorEnvironmentImpl::GetInstance()->DisableVirtualAuthenticatorFor(
+ this);
+#endif // !defined(OS_ANDROID)
+
// Ensure that the render process host has been notified that all audio
// streams from this frame have terminated. This is required to ensure the
// process host has the correct media stream count, which affects its
@@ -991,11 +1044,11 @@ RenderFrameHostImpl::~RenderFrameHostImpl() {
for (auto& iter : visual_state_callbacks_)
std::move(iter.second).Run(false);
- if (render_widget_host_ &&
- render_widget_host_->owned_by_render_frame_host()) {
- // Shutdown causes the RenderWidgetHost to delete itself.
- render_widget_host_->ShutdownAndDestroyWidget(true);
- }
+ // Note: The RenderWidgetHost of the main frame is owned by the RenderViewHost
+ // instead. In this case the RenderViewHost is responsible for shutting down
+ // its RenderViewHost.
+ if (owned_render_widget_host_)
+ owned_render_widget_host_->ShutdownAndDestroyWidget(false);
// Notify the FrameTree that this RFH is going away, allowing it to shut down
// the corresponding RenderViewHost if it is no longer needed.
@@ -1059,13 +1112,15 @@ void RenderFrameHostImpl::LeaveBackForwardCache() {
void RenderFrameHostImpl::OnPortalActivated(
const base::UnguessableToken& portal_token,
blink::mojom::PortalAssociatedPtrInfo portal,
+ blink::mojom::PortalClientAssociatedRequest portal_client,
blink::TransferableMessage data,
base::OnceCallback<void(bool)> callback) {
GetNavigationControl()->OnPortalActivated(
- portal_token, std::move(portal), std::move(data), std::move(callback));
+ portal_token, std::move(portal), std::move(portal_client),
+ std::move(data), std::move(callback));
}
-void RenderFrameHostImpl::ForwardMessageToPortalHost(
+void RenderFrameHostImpl::ForwardMessageFromHost(
blink::TransferableMessage message,
const url::Origin& source_origin,
const base::Optional<url::Origin>& target_origin) {
@@ -1073,12 +1128,11 @@ void RenderFrameHostImpl::ForwardMessageToPortalHost(
// navigated after the postMessage call, or if the renderer is compromised and
// the check done in PortalHost::ReceiveMessage is bypassed.
if (target_origin) {
- DCHECK(!target_origin->opaque());
if (target_origin != GetLastCommittedOrigin())
return;
}
- GetNavigationControl()->ForwardMessageToPortalHost(
- std::move(message), source_origin, target_origin);
+ GetNavigationControl()->ForwardMessageFromHost(std::move(message),
+ source_origin, target_origin);
}
SiteInstanceImpl* RenderFrameHostImpl::GetSiteInstance() {
@@ -1125,6 +1179,10 @@ const base::Optional<gfx::Size>& RenderFrameHostImpl::GetFrameSize() {
return frame_size_;
}
+size_t RenderFrameHostImpl::GetFrameDepth() {
+ return frame_tree_node()->depth();
+}
+
bool RenderFrameHostImpl::IsCrossProcessSubframe() {
if (!parent_)
return false;
@@ -1231,7 +1289,7 @@ gfx::NativeView RenderFrameHostImpl::GetNativeView() {
void RenderFrameHostImpl::AddMessageToConsole(
blink::mojom::ConsoleMessageLevel level,
const std::string& message) {
- Send(new FrameMsg_AddMessageToConsole(routing_id_, level, message));
+ AddMessageToConsoleImpl(level, message, false /* discard_duplicates */);
}
void RenderFrameHostImpl::ExecuteJavaScript(const base::string16& javascript,
@@ -1332,7 +1390,7 @@ PageVisibilityState RenderFrameHostImpl::GetVisibilityState() {
// https://crbug.com/615867.
RenderFrameHostImpl* frame = this;
while (frame) {
- if (frame->render_widget_host_)
+ if (frame->GetLocalRenderWidgetHost())
break;
frame = frame->GetParent();
}
@@ -1363,21 +1421,6 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
// either the FrameHost interface or to interfaces bound by this frame.
ScopedActiveURL scoped_active_url(this);
- // This message map is for handling internal IPC messages which should not
- // be dispatched to other objects.
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(RenderFrameHostImpl, msg)
- // This message is synthetic and doesn't come from RenderFrame, but from
- // RenderProcessHost.
- IPC_MESSAGE_HANDLER(FrameHostMsg_RenderProcessGone, OnRenderProcessGone)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- // Internal IPCs should not be leaked outside of this object, so return
- // early.
- if (handled)
- return true;
-
if (delegate_->OnMessageReceived(this, msg))
return true;
@@ -1387,16 +1430,10 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
proxy->cross_process_frame_connector()->OnMessageReceived(msg))
return true;
- handled = true;
+ bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderFrameHostImpl, msg)
- IPC_MESSAGE_HANDLER(FrameHostMsg_DidAddMessageToConsole,
- OnDidAddMessageToConsole)
IPC_MESSAGE_HANDLER(FrameHostMsg_Detach, OnDetach)
IPC_MESSAGE_HANDLER(FrameHostMsg_FrameFocused, OnFrameFocused)
- IPC_MESSAGE_HANDLER(FrameHostMsg_DidFailProvisionalLoadWithError,
- OnDidFailProvisionalLoadWithError)
- IPC_MESSAGE_HANDLER(FrameHostMsg_DidFailLoadWithError,
- OnDidFailLoadWithError)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateState, OnUpdateState)
IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL)
IPC_MESSAGE_HANDLER(FrameHostMsg_BeforeUnload_ACK, OnBeforeUnloadACK)
@@ -1463,6 +1500,8 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(FrameHostMsg_RequestOverlayRoutingToken,
OnRequestOverlayRoutingToken)
IPC_MESSAGE_HANDLER(FrameHostMsg_ShowCreatedWindow, OnShowCreatedWindow)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_TransferUserActivationFrom,
+ OnTransferUserActivationFrom)
IPC_END_MESSAGE_MAP()
// No further actions here, since we may have been deleted.
@@ -1559,13 +1598,81 @@ RenderFrameHostImpl::AccessibilityGetNativeViewAccessibleForWindow() {
return nullptr;
}
-bool RenderFrameHostImpl::AccessibilityIsMainFrame() {
+bool RenderFrameHostImpl::AccessibilityIsMainFrame() const {
return frame_tree_node()->IsMainFrame();
}
+void RenderFrameHostImpl::RenderProcessExited(
+ RenderProcessHost* host,
+ const ChildProcessTerminationInfo& info) {
+ if (base::FeatureList::IsEnabled(features::kCrashReporting))
+ MaybeGenerateCrashReport(info.status, info.exit_code);
+
+ // When a frame's process dies, its RenderFrame no longer exists, which means
+ // that its child frames must be cleaned up as well.
+ ResetChildren();
+
+ // Reset state for the current RenderFrameHost once the FrameTreeNode has been
+ // reset.
+ SetRenderFrameCreated(false);
+ InvalidateMojoConnection();
+ document_scoped_interface_provider_binding_.Close();
+ document_interface_broker_content_binding_.Close();
+ document_interface_broker_blink_binding_.Close();
+ SetLastCommittedUrl(GURL());
+
+ // Execute any pending AX tree snapshot callbacks with an empty response,
+ // since we're never going to get a response from this renderer.
+ for (auto& iter : ax_tree_snapshot_callbacks_)
+ std::move(iter.second).Run(ui::AXTreeUpdate());
+
+#if defined(OS_ANDROID)
+ // Execute any pending Samsung smart clip callbacks.
+ for (base::IDMap<std::unique_ptr<ExtractSmartClipDataCallback>>::iterator
+ iter(&smart_clip_callbacks_);
+ !iter.IsAtEnd(); iter.Advance()) {
+ std::move(*iter.GetCurrentValue())
+ .Run(base::string16(), base::string16(), gfx::Rect());
+ }
+ smart_clip_callbacks_.Clear();
+#endif // defined(OS_ANDROID)
+
+ ax_tree_snapshot_callbacks_.clear();
+ visual_state_callbacks_.clear();
+
+ // Ensure that future remote interface requests are associated with the new
+ // process's channel.
+ remote_associated_interfaces_.reset();
+
+ // Any termination disablers in content loaded by the new process will
+ // be sent again.
+ sudden_termination_disabler_types_enabled_ = 0;
+
+ if (unload_state_ != UnloadState::NotRun) {
+ // If the process has died, we don't need to wait for the ACK. Complete the
+ // deletion immediately.
+ unload_state_ = UnloadState::Completed;
+ DCHECK(children_.empty());
+ PendingDeletionCheckCompleted();
+ // |this| is deleted. Don't add any more code at this point in the function.
+ return;
+ }
+
+ // If this was the current pending or speculative RFH dying, cancel and
+ // destroy it.
+ frame_tree_node_->render_manager()->CancelPendingIfNecessary(this);
+
+ // Note: don't add any more code at this point in the function because
+ // |this| may be deleted. Any additional cleanup should happen before
+ // the last block of code here.
+}
+
void RenderFrameHostImpl::RenderProcessGone(SiteInstanceImpl* site_instance) {
DCHECK_EQ(site_instance_.get(), site_instance);
+ if (owned_render_widget_host_)
+ owned_render_widget_host_->RendererExited();
+
// The renderer process is gone, so this frame can no longer be loading.
if (GetNavigationHandle())
GetNavigationHandle()->set_net_error_code(net::ERR_ABORTED);
@@ -1704,9 +1811,10 @@ bool RenderFrameHostImpl::CreateRenderFrame(int previous_routing_id,
frame_tree_node()->has_committed_real_load();
params->widget_params = mojom::CreateFrameWidgetParams::New();
- if (render_widget_host_) {
- params->widget_params->routing_id = render_widget_host_->GetRoutingID();
- params->widget_params->hidden = render_widget_host_->is_hidden();
+ if (GetLocalRenderWidgetHost()) {
+ params->widget_params->routing_id =
+ GetLocalRenderWidgetHost()->GetRoutingID();
+ params->widget_params->hidden = GetLocalRenderWidgetHost()->is_hidden();
} else {
// MSG_ROUTING_NONE will prevent a new RenderWidget from being created in
// the renderer process.
@@ -1721,9 +1829,11 @@ bool RenderFrameHostImpl::CreateRenderFrame(int previous_routing_id,
// TODO(avi): This will need to change to initialize a
// RenderWidgetHostViewAura for the main frame once RenderViewHostImpl has-a
// RenderWidgetHostImpl. https://crbug.com/545684
- if (parent_routing_id != MSG_ROUTING_NONE && render_widget_host_) {
+ if (owned_render_widget_host_) {
+ DCHECK(parent_);
+ DCHECK_NE(parent_routing_id, MSG_ROUTING_NONE);
RenderWidgetHostView* rwhv =
- RenderWidgetHostViewChildFrame::Create(render_widget_host_);
+ RenderWidgetHostViewChildFrame::Create(owned_render_widget_host_.get());
rwhv->Hide();
}
@@ -1751,15 +1861,22 @@ void RenderFrameHostImpl::DeleteRenderFrame(FrameDeleteIntention intent) {
if (render_frame_created_) {
Send(new FrameMsg_Delete(routing_id_, intent));
- // If this subframe has an unload handler (and isn't speculative), ensure
- // that it has a chance to execute by delaying process cleanup. This will
- // prevent the process from shutting down immediately in the case where this
- // is the last active frame in the process. See https://crbug.com/852204.
- if (!frame_tree_node_->IsMainFrame() && IsCurrent() &&
- GetSuddenTerminationDisablerState(blink::kUnloadHandler)) {
- RenderProcessHostImpl* process =
- static_cast<RenderProcessHostImpl*>(GetProcess());
- process->DelayProcessShutdownForUnload(subframe_unload_timeout_);
+ if (!frame_tree_node_->IsMainFrame() && IsCurrent()) {
+ // If this subframe has an unload handler (and isn't speculative), ensure
+ // that it has a chance to execute by delaying process cleanup. This will
+ // prevent the process from shutting down immediately in the case where
+ // this is the last active frame in the process. See
+ // https://crbug.com/852204.
+ if (GetSuddenTerminationDisablerState(blink::kUnloadHandler)) {
+ RenderProcessHostImpl* process =
+ static_cast<RenderProcessHostImpl*>(GetProcess());
+ process->DelayProcessShutdownForUnload(subframe_unload_timeout_);
+ }
+
+ // If the subframe takes too long to unload, force its removal from the
+ // tree. See https://crbug.com/950625.
+ subframe_unload_timer_.Start(FROM_HERE, subframe_unload_timeout_, this,
+ &RenderFrameHostImpl::OnUnloadTimeout);
}
}
@@ -1789,10 +1906,10 @@ void RenderFrameHostImpl::SetRenderFrameCreated(bool created) {
}
}
- if (created && render_widget_host_) {
+ if (created && GetLocalRenderWidgetHost()) {
mojom::WidgetPtr widget;
GetRemoteInterfaces()->GetInterface(&widget);
- render_widget_host_->SetWidget(std::move(widget));
+ GetLocalRenderWidgetHost()->SetWidget(std::move(widget));
if (frame_input_handler_) {
mojom::WidgetInputHandlerAssociatedPtr widget_handler;
@@ -1801,16 +1918,17 @@ void RenderFrameHostImpl::SetRenderFrameCreated(bool created) {
mojo::MakeRequest(&host);
frame_input_handler_->GetWidgetInputHandler(
mojo::MakeRequest(&widget_handler), std::move(host));
- render_widget_host_->SetWidgetInputHandler(std::move(widget_handler),
- std::move(host_request));
+ GetLocalRenderWidgetHost()->SetWidgetInputHandler(
+ std::move(widget_handler), std::move(host_request));
}
- render_widget_host_->input_router()->SetFrameTreeNodeId(
+ GetLocalRenderWidgetHost()->input_router()->SetFrameTreeNodeId(
frame_tree_node_->frame_tree_node_id());
viz::mojom::InputTargetClientPtr input_target_client;
remote_interfaces_->GetInterface(&input_target_client);
input_target_client_ = input_target_client.get();
- render_widget_host_->SetInputTargetClient(std::move(input_target_client));
- render_widget_host_->InitForFrame();
+ GetLocalRenderWidgetHost()->SetInputTargetClient(
+ std::move(input_target_client));
+ GetLocalRenderWidgetHost()->InitForFrame();
}
if (enabled_bindings_ && created) {
@@ -1832,7 +1950,8 @@ void RenderFrameHostImpl::Init() {
std::move(pending_navigate_->begin_navigation_params),
std::move(pending_navigate_->blob_url_loader_factory),
std::move(pending_navigate_->navigation_client),
- std::move(pending_navigate_->navigation_initiator));
+ std::move(pending_navigate_->navigation_initiator),
+ EnsurePrefetchedSignedExchangeCache());
pending_navigate_.reset();
}
}
@@ -1847,21 +1966,17 @@ void RenderFrameHostImpl::OnAudibleStateChanged(bool is_audible) {
is_audible_ = is_audible;
}
-void RenderFrameHostImpl::OnDidAddMessageToConsole(
- int32_t level,
+void RenderFrameHostImpl::DidAddMessageToConsole(
+ blink::mojom::ConsoleMessageLevel log_level,
const base::string16& message,
int32_t line_no,
const base::string16& source_id) {
- if (level < logging::LOG_VERBOSE || level > logging::LOG_FATAL) {
- bad_message::ReceivedBadMessage(
- GetProcess(), bad_message::RFH_DID_ADD_CONSOLE_MESSAGE_BAD_SEVERITY);
+ if (delegate_->DidAddMessageToConsole(log_level, message, line_no,
+ source_id)) {
return;
}
- if (delegate_->DidAddMessageToConsole(level, message, line_no, source_id))
- return;
-
- // Pass through log level only on builtin components pages to limit console
+ // Pass through log severity only on builtin components pages to limit console
// spew.
const bool is_builtin_component =
HasWebUIScheme(delegate_->GetMainFrameLastCommittedURL()) ||
@@ -1870,7 +1985,7 @@ void RenderFrameHostImpl::OnDidAddMessageToConsole(
const bool is_off_the_record =
GetSiteInstance()->GetBrowserContext()->IsOffTheRecord();
- LogConsoleMessage(level, message, line_no, is_builtin_component,
+ LogConsoleMessage(log_level, message, line_no, is_builtin_component,
is_off_the_record, source_id);
}
@@ -2079,6 +2194,8 @@ void RenderFrameHostImpl::OnDetach() {
// descendant frames to execute unload handlers. Start executing those
// handlers now.
StartPendingDeletionOnSubtree();
+ frame_tree_node_->frame_tree()->FrameUnloading(frame_tree_node_);
+
// Some children with no unload handler may be eligible for immediate
// deletion. Cut the dead branches now. This is a performance optimization.
PendingDeletionCheckCompletedOnSubtree(); // Can delete |this|.
@@ -2100,16 +2217,6 @@ void RenderFrameHostImpl::OnOpenURL(const FrameHostMsg_OpenURL_Params& params) {
return;
}
- if (params.is_history_navigation_in_new_child) {
- // Try to find a FrameNavigationEntry that matches this frame instead, based
- // on the frame's unique name. If this can't be found, fall back to the
- // default params using RequestOpenURL below.
- if (frame_tree_node_->navigator()->StartHistoryNavigationInNewSubframe(
- this, validated_url)) {
- return;
- }
- }
-
TRACE_EVENT1("navigation", "RenderFrameHostImpl::OpenURL", "url",
validated_url.possibly_invalid_spec());
@@ -2136,15 +2243,26 @@ void RenderFrameHostImpl::DocumentOnLoadCompleted() {
void RenderFrameHostImpl::UpdateActiveSchedulerTrackedFeatures(
uint64_t features_mask) {
- scheduler_tracked_features_ = features_mask;
+ TRACE_EVENT0("toplevel", "UpdateActiveSchedulerTrackedFeatures");
+ renderer_reported_scheduler_tracked_features_ = features_mask;
}
-void RenderFrameHostImpl::OnDidFailProvisionalLoadWithError(
- const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
+void RenderFrameHostImpl::OnSchedulerTrackedFeatureUsed(
+ blink::scheduler::WebSchedulerTrackedFeature feature) {
+ TRACE_EVENT0("toplevel", "OnSchedulerTrackedFeatureUsed");
+ browser_reported_scheduler_tracked_features_ |=
+ 1 << static_cast<uint64_t>(feature);
+}
+
+void RenderFrameHostImpl::DidFailProvisionalLoadWithError(
+ const GURL& url,
+ int error_code,
+ const base::string16& error_description,
+ bool showing_repost_interstitial) {
TRACE_EVENT2("navigation",
- "RenderFrameHostImpl::OnDidFailProvisionalLoadWithError",
+ "RenderFrameHostImpl::DidFailProvisionalLoadWithError",
"frame_tree_node", frame_tree_node_->frame_tree_node_id(),
- "error", params.error_code);
+ "error", error_code);
// TODO(clamy): Kill the renderer with RFH_FAIL_PROVISIONAL_LOAD_NO_HANDLE and
// return early if navigation_handle_ is null, once we prevent that case from
// happening in practice. See https://crbug.com/605289.
@@ -2152,18 +2270,19 @@ void RenderFrameHostImpl::OnDidFailProvisionalLoadWithError(
// Update the error code in the NavigationHandle of the navigation.
if (GetNavigationHandle()) {
GetNavigationHandle()->set_net_error_code(
- static_cast<net::Error>(params.error_code));
+ static_cast<net::Error>(error_code));
}
- frame_tree_node_->navigator()->DidFailProvisionalLoadWithError(this, params);
+ frame_tree_node_->navigator()->DidFailProvisionalLoadWithError(
+ this, url, error_code, error_description, showing_repost_interstitial);
}
-void RenderFrameHostImpl::OnDidFailLoadWithError(
+void RenderFrameHostImpl::DidFailLoadWithError(
const GURL& url,
int error_code,
const base::string16& error_description) {
TRACE_EVENT2("navigation",
- "RenderFrameHostImpl::OnDidFailProvisionalLoadWithError",
+ "RenderFrameHostImpl::DidFailProvisionalLoadWithError",
"frame_tree_node", frame_tree_node_->frame_tree_node_id(),
"error", error_code);
@@ -2269,8 +2388,8 @@ void RenderFrameHostImpl::OnUpdateState(const PageState& state) {
RenderWidgetHostImpl* RenderFrameHostImpl::GetRenderWidgetHost() {
RenderFrameHostImpl* frame = this;
while (frame) {
- if (frame->render_widget_host_)
- return frame->render_widget_host_;
+ if (frame->GetLocalRenderWidgetHost())
+ return frame->GetLocalRenderWidgetHost();
frame = frame->GetParent();
}
@@ -2362,6 +2481,9 @@ void RenderFrameHostImpl::SwapOut(
web_ui()->RenderFrameHostSwappingOut();
web_bluetooth_services_.clear();
+#if !defined(OS_ANDROID)
+ serial_service_.reset();
+#endif
}
void RenderFrameHostImpl::DetachFromProxy() {
@@ -2371,9 +2493,11 @@ void RenderFrameHostImpl::DetachFromProxy() {
// Start pending deletion on this frame and its children.
DeleteRenderFrame(FrameDeleteIntention::kNotMainFrame);
StartPendingDeletionOnSubtree();
+ frame_tree_node_->frame_tree()->FrameUnloading(frame_tree_node_);
+
// Some children with no unload handler may be eligible for immediate
// deletion. Cut the dead branches now. This is a performance optimization.
- PendingDeletionCheckCompletedOnSubtree();
+ PendingDeletionCheckCompletedOnSubtree(); // May delete |this|.
}
void RenderFrameHostImpl::OnBeforeUnloadACK(
@@ -2541,78 +2665,6 @@ void RenderFrameHostImpl::OnSwapOutACK() {
PendingDeletionCheckCompleted(); // Can delete |this|.
}
-void RenderFrameHostImpl::OnRenderProcessGone(int status, int exit_code) {
- base::TerminationStatus termination_status =
- static_cast<base::TerminationStatus>(status);
-
- if (frame_tree_node_->IsMainFrame()) {
- // Keep the termination status so we can get at it later when we
- // need to know why it died.
- render_view_host_->render_view_termination_status_ = termination_status;
- }
-
- if (base::FeatureList::IsEnabled(features::kCrashReporting))
- MaybeGenerateCrashReport(termination_status, exit_code);
-
- // When a frame's process dies, its RenderFrame no longer exists, which means
- // that its child frames must be cleaned up as well.
- ResetChildren();
-
- // Reset state for the current RenderFrameHost once the FrameTreeNode has been
- // reset.
- SetRenderFrameCreated(false);
- InvalidateMojoConnection();
- document_scoped_interface_provider_binding_.Close();
- document_interface_broker_content_binding_.Close();
- document_interface_broker_blink_binding_.Close();
- SetLastCommittedUrl(GURL());
-
- // Execute any pending AX tree snapshot callbacks with an empty response,
- // since we're never going to get a response from this renderer.
- for (auto& iter : ax_tree_snapshot_callbacks_)
- std::move(iter.second).Run(ui::AXTreeUpdate());
-
-#if defined(OS_ANDROID)
- // Execute any pending Samsung smart clip callbacks.
- for (base::IDMap<std::unique_ptr<ExtractSmartClipDataCallback>>::iterator
- iter(&smart_clip_callbacks_);
- !iter.IsAtEnd(); iter.Advance()) {
- std::move(*iter.GetCurrentValue())
- .Run(base::string16(), base::string16(), gfx::Rect());
- }
- smart_clip_callbacks_.Clear();
-#endif // defined(OS_ANDROID)
-
- ax_tree_snapshot_callbacks_.clear();
- visual_state_callbacks_.clear();
-
- // Ensure that future remote interface requests are associated with the new
- // process's channel.
- remote_associated_interfaces_.reset();
-
- // Any termination disablers in content loaded by the new process will
- // be sent again.
- sudden_termination_disabler_types_enabled_ = 0;
-
- if (unload_state_ != UnloadState::NotRun) {
- // If the process has died, we don't need to wait for the ACK. Complete the
- // deletion immediately.
- unload_state_ = UnloadState::Completed;
- DCHECK(children_.empty());
- PendingDeletionCheckCompleted();
- // |this| is deleted. Don't add any more code at this point in the function.
- return;
- }
-
- // If this was the current pending or speculative RFH dying, cancel and
- // destroy it.
- frame_tree_node_->render_manager()->CancelPendingIfNecessary(this);
-
- // Note: don't add any more code at this point in the function because
- // |this| may be deleted. Any additional cleanup should happen before
- // the last block of code here.
-}
-
void RenderFrameHostImpl::OnSwappedOut() {
DCHECK(is_waiting_for_swapout_ack_);
@@ -2932,6 +2984,10 @@ void RenderFrameHostImpl::UpdateSubresourceLoaderFactories() {
std::move(subresource_loader_factories));
}
+blink::FrameOwnerElementType RenderFrameHostImpl::GetFrameOwnerElementType() {
+ return frame_tree_node_->frame_owner_element_type();
+}
+
void RenderFrameHostImpl::OnDidAccessInitialDocument() {
delegate_->DidAccessInitialDocument();
}
@@ -3226,10 +3282,8 @@ void RenderFrameHostImpl::OnAccessibilityEvents(
}
}
- if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs)) {
- if (browser_accessibility_manager_)
- browser_accessibility_manager_->OnAccessibilityEvents(details);
- }
+ if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs))
+ SendAccessibilityEventsToManager(details);
delegate_->AccessibilityEventReceived(details);
@@ -3256,6 +3310,15 @@ void RenderFrameHostImpl::OnAccessibilityEvents(
Send(new AccessibilityMsg_EventBundle_ACK(routing_id_, ack_token));
}
+void RenderFrameHostImpl::SendAccessibilityEventsToManager(
+ const AXEventNotificationDetails& details) {
+ if (browser_accessibility_manager_ &&
+ !browser_accessibility_manager_->OnAccessibilityEvents(details)) {
+ // OnAccessibilityEvents returns false in IPC error conditions
+ AccessibilityFatalError();
+ }
+}
+
void RenderFrameHostImpl::OnAccessibilityLocationChanges(
const std::vector<AccessibilityHostMsg_LocationChangeParams>& params) {
if (accessibility_reset_token_)
@@ -3455,8 +3518,6 @@ void RenderFrameHostImpl::OnDidStopLoading() {
// of this RenderFrameHost is being tracked.
if (is_active())
frame_tree_node_->DidStopLoading();
-
- UpdateFrameFrozenState();
}
void RenderFrameHostImpl::OnDidChangeLoadProgress(double load_progress) {
@@ -3505,6 +3566,11 @@ void RenderFrameHostImpl::OnSetHasReceivedUserGestureBeforeNavigation(
}
void RenderFrameHostImpl::OnSetNeedsOcclusionTracking(bool needs_tracking) {
+ // Don't process the IPC if this RFH is pending deletion. See also
+ // https://crbug.com/972566.
+ if (!is_active())
+ return;
+
RenderFrameProxyHost* proxy =
frame_tree_node()->render_manager()->GetProxyToParent();
if (!proxy) {
@@ -3529,7 +3595,7 @@ void RenderFrameHostImpl::OnScrollRectToVisibleInParentFrame(
void RenderFrameHostImpl::OnBubbleLogicalScrollInParentFrame(
blink::WebScrollDirection direction,
- blink::WebScrollGranularity granularity) {
+ ui::input_types::ScrollGranularity granularity) {
if (!is_active())
return;
@@ -3649,6 +3715,16 @@ void RenderFrameHostImpl::OnShowCreatedWindow(int pending_widget_routing_id,
disposition, initial_rect, user_gesture);
}
+void RenderFrameHostImpl::OnTransferUserActivationFrom(
+ int32_t source_routing_id) {
+ RenderFrameHostImpl* source_rfh =
+ RenderFrameHostImpl::FromID(GetProcess()->GetID(), source_routing_id);
+ if (source_rfh &&
+ source_rfh->frame_tree_node()->HasTransientUserActivation()) {
+ frame_tree_node()->TransferUserActivationFrom(source_rfh);
+ }
+}
+
void RenderFrameHostImpl::CreateNewWindow(
mojom::CreateNewWindowParamsPtr params,
CreateNewWindowCallback callback) {
@@ -3840,15 +3916,18 @@ void RenderFrameHostImpl::CreateNewWindow(
void RenderFrameHostImpl::CreatePortal(
blink::mojom::PortalAssociatedRequest request,
+ blink::mojom::PortalClientAssociatedPtrInfo client,
CreatePortalCallback callback) {
+ // We don't support attaching a portal inside a nested browsing context.
if (frame_tree_node()->parent()) {
mojo::ReportBadMessage(
"RFHI::CreatePortal called in a nested browsing context");
return;
}
- Portal* portal = Portal::Create(this, std::move(request));
+ Portal* portal = Portal::Create(this, std::move(request), std::move(client));
RenderFrameProxyHost* proxy_host = portal->CreateProxyAndAttachPortal();
- std::move(callback).Run(proxy_host->GetRoutingID(), portal->portal_token());
+ std::move(callback).Run(proxy_host->GetRoutingID(), portal->portal_token(),
+ portal->GetDevToolsFrameToken());
}
void RenderFrameHostImpl::AdoptPortal(
@@ -3864,7 +3943,8 @@ void RenderFrameHostImpl::AdoptPortal(
return;
}
RenderFrameProxyHost* proxy_host = portal->CreateProxyAndAttachPortal();
- std::move(callback).Run(proxy_host->GetRoutingID());
+ std::move(callback).Run(proxy_host->GetRoutingID(),
+ portal->GetDevToolsFrameToken());
}
void RenderFrameHostImpl::IssueKeepAliveHandle(
@@ -3948,7 +4028,7 @@ void RenderFrameHostImpl::BeginNavigation(
frame_tree_node()->navigator()->OnBeginNavigation(
frame_tree_node(), validated_params, std::move(begin_params),
std::move(blob_url_loader_factory), std::move(navigation_client),
- std::move(navigation_initiator));
+ std::move(navigation_initiator), EnsurePrefetchedSignedExchangeCache());
}
void RenderFrameHostImpl::SubresourceResponseStarted(
@@ -3976,6 +4056,8 @@ void RenderFrameHostImpl::ResourceLoadComplete(
}
void RenderFrameHostImpl::RegisterMojoInterfaces() {
+ auto* command_line = base::CommandLine::ForCurrentProcess();
+
#if !defined(OS_ANDROID)
// The default (no-op) implementation of InstalledAppProvider. On Android, the
// real implementation is provided in Java.
@@ -4000,9 +4082,6 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
}
}
- registry_->AddInterface<device::mojom::WakeLock>(base::Bind(
- &RenderFrameHostImpl::BindWakeLockRequest, base::Unretained(this)));
-
#if defined(OS_ANDROID)
if (base::FeatureList::IsEnabled(features::kWebNfc)) {
registry_->AddInterface<device::mojom::NFC>(base::Bind(
@@ -4095,8 +4174,12 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
base::Unretained(sensor_provider_proxy_.get())));
#if !defined(OS_ANDROID)
- registry_->AddInterface(base::BindRepeating(
- &RenderFrameHostImpl::BindSerialServiceRequest, base::Unretained(this)));
+ if (command_line->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures)) {
+ registry_->AddInterface(
+ base::BindRepeating(&RenderFrameHostImpl::BindSerialServiceRequest,
+ base::Unretained(this)));
+ }
#endif // !defined(OS_ANDROID)
// Only save decode stats when BrowserContext provides a VideoPerfHistory.
@@ -4125,8 +4208,7 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
base::Unretained(this)),
std::move(save_stats_cb)));
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- cc::switches::kEnableGpuBenchmarking)) {
+ if (command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking)) {
registry_->AddInterface(
base::Bind(&InputInjectorImpl::Create, weak_ptr_factory_.GetWeakPtr()));
}
@@ -4141,7 +4223,7 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
file_system_manager_.reset(new FileSystemManagerImpl(
- GetProcess()->GetID(), routing_id_,
+ GetProcess()->GetID(),
GetProcess()->GetStoragePartition()->GetFileSystemContext(),
ChromeBlobStorageContext::GetFor(GetProcess()->GetBrowserContext())));
registry_->AddInterface(
@@ -4163,6 +4245,36 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
registry_->AddInterface(base::BindRepeating(
&PictureInPictureServiceImpl::Create, base::Unretained(this)));
+
+ if (base::FeatureList::IsEnabled(blink::features::kNativeFileSystemAPI)) {
+ registry_->AddInterface(base::BindRepeating(
+ [](RenderFrameHostImpl* frame,
+ blink::mojom::NativeFileSystemManagerRequest request) {
+ scoped_refptr<NativeFileSystemManagerImpl> manager =
+ static_cast<StoragePartitionImpl*>(
+ frame->GetProcess()->GetStoragePartition())
+ ->GetNativeFileSystemManager();
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(
+ &NativeFileSystemManagerImpl::BindRequest, std::move(manager),
+ NativeFileSystemManagerImpl::BindingContext(
+ frame->GetLastCommittedOrigin(),
+ frame->GetProcess()->GetID(), frame->GetRoutingID()),
+ std::move(request)));
+ },
+ base::Unretained(this)));
+ }
+
+ registry_->AddInterface(base::BindRepeating(
+ &RenderFrameHostImpl::BindIdleManagerRequest, base::Unretained(this)));
+
+ if (base::FeatureList::IsEnabled(features::kSmsReceiver) &&
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures)) {
+ registry_->AddInterface(base::BindRepeating(
+ &RenderFrameHostImpl::BindSmsManagerRequest, base::Unretained(this)));
+ }
}
void RenderFrameHostImpl::ResetWaitingState() {
@@ -4228,7 +4340,8 @@ void RenderFrameHostImpl::NavigateToInterstitialURL(const GURL& data_url) {
FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, download_policy, false,
GURL(), GURL(), PREVIEWS_OFF, base::TimeTicks::Now(), "GET", nullptr,
base::Optional<SourceLocation>(), false /* started_from_context_menu */,
- false /* has_user_gesture */, InitiatorCSPInfo(), std::string());
+ false /* has_user_gesture */, InitiatorCSPInfo(), std::vector<int>(),
+ std::string(), false /* is_history_navigation_in_new_child_frame */);
CommitNavigation(nullptr /* navigation_request */, nullptr /* response */,
network::mojom::URLLoaderClientEndpointsPtr(), common_params,
CommitNavigationParams(), false, base::nullopt,
@@ -4473,6 +4586,8 @@ void RenderFrameHostImpl::StartPendingDeletionOnSubtree() {
? UnloadState::InProgress
: UnloadState::Completed;
}
+
+ node->frame_tree()->FrameUnloading(node);
}
}
}
@@ -4510,6 +4625,11 @@ void RenderFrameHostImpl::ResetNavigationsForPendingDeletion() {
frame_tree_node_->render_manager()->CleanUpNavigation();
}
+void RenderFrameHostImpl::OnUnloadTimeout() {
+ DCHECK_NE(unload_state_, UnloadState::NotRun);
+ parent_->RemoveChild(frame_tree_node_);
+}
+
void RenderFrameHostImpl::UpdateOpener() {
TRACE_EVENT1("navigation", "RenderFrameHostImpl::UpdateOpener",
"frame_tree_node", frame_tree_node_->frame_tree_node_id());
@@ -4592,6 +4712,33 @@ void RenderFrameHostImpl::CommitNavigation(
FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type) ||
!IsURLHandledByNetworkStack(common_params.url));
+ // If this is an attempt to commit a URL in an incompatible process, capture a
+ // crash dump to diagnose why it is occurring.
+ // TODO(creis): Remove this check after we've gathered enough information to
+ // debug issues with browser-side security checks. https://crbug.com/931895.
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ const GURL& lock_url = GetSiteInstance()->lock_url();
+ if (lock_url != GURL(kUnreachableWebDataURL) &&
+ common_params.url.IsStandard() &&
+ !policy->CanAccessDataForOrigin(GetProcess()->GetID(),
+ common_params.url)) {
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString("lock_url",
+ base::debug::CrashKeySize::Size64),
+ lock_url.spec());
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString("commit_origin",
+ base::debug::CrashKeySize::Size64),
+ common_params.url.GetOrigin().spec());
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString("is_main_frame",
+ base::debug::CrashKeySize::Size32),
+ frame_tree_node_->IsMainFrame() ? "true" : "false");
+ NOTREACHED() << "Commiting in incompatible process for URL: " << lock_url
+ << " lock vs " << common_params.url.GetOrigin();
+ base::debug::DumpWithoutCrashing();
+ }
+
const bool is_first_navigation = !has_committed_any_navigation_;
has_committed_any_navigation_ = true;
@@ -4628,9 +4775,20 @@ void RenderFrameHostImpl::CommitNavigation(
if (subresource_loader_params &&
subresource_loader_params->appcache_loader_factory_info.is_valid()) {
// If the caller has supplied a factory for AppCache, use it.
- subresource_loader_factories->appcache_factory_info() =
+
+ auto factory_ptr_info =
std::move(subresource_loader_params->appcache_loader_factory_info);
+#if defined(OS_ANDROID)
+ GetContentClient()
+ ->browser()
+ ->WillCreateURLLoaderFactoryForAppCacheSubresource(
+ GetProcess()->GetID(), &factory_ptr_info);
+#endif
+
+ subresource_loader_factories->appcache_factory_info() =
+ std::move(factory_ptr_info);
+
// Inject test intermediary if needed.
if (!GetCreateNetworkFactoryCallbackForRenderFrame().is_null()) {
network::mojom::URLLoaderFactoryPtrInfo original_factory =
@@ -4681,8 +4839,7 @@ void RenderFrameHostImpl::CommitNavigation(
recreate_default_url_loader_factory_after_network_service_crash_ = true;
bool bypass_redirect_checks =
CreateNetworkServiceDefaultFactoryAndObserve(
- GetOriginForURLLoaderFactory(common_params.url,
- GetSiteInstance()),
+ GetOriginForURLLoaderFactory(navigation_request),
mojo::MakeRequest(&default_factory_info));
subresource_loader_factories->set_bypass_redirect_checks(
bypass_redirect_checks);
@@ -4747,7 +4904,7 @@ void RenderFrameHostImpl::CommitNavigation(
GetContentClient()->browser()->WillCreateURLLoaderFactory(
browser_context, this, GetProcess()->GetID(),
false /* is_navigation */, false /* is_download */,
- GetOriginForURLLoaderFactory(common_params.url, GetSiteInstance())
+ GetOriginForURLLoaderFactory(navigation_request)
.value_or(url::Origin()),
&factory_request, nullptr /* header_client */,
nullptr /* bypass_redirect_checks */);
@@ -4829,7 +4986,8 @@ void RenderFrameHostImpl::CommitNavigation(
storage_partition->GetPrefetchURLLoaderService(),
mojo::MakeRequest(&prefetch_loader_factory),
frame_tree_node_->frame_tree_node_id(),
- std::move(factory_bundle_for_prefetch)));
+ std::move(factory_bundle_for_prefetch),
+ EnsurePrefetchedSignedExchangeCache()));
}
mojom::NavigationClient* navigation_client = nullptr;
@@ -4977,6 +5135,9 @@ void RenderFrameHostImpl::SetUpMojoIfNeeded() {
associated_registry_->AddInterface(
base::BindRepeating(make_binding, base::Unretained(this)));
+ associated_registry_->AddInterface(base::BindRepeating(
+ &Portal::BindPortalHostRequest, base::Unretained(this)));
+
RegisterMojoInterfaces();
mojom::FrameFactoryPtr frame_factory;
BindInterface(GetProcess(), &frame_factory);
@@ -5185,7 +5346,13 @@ bool RenderFrameHostImpl::CanCommitURL(const GURL& url) {
if (!GetContentClient()->browser()->CanCommitURL(GetProcess(), url))
return false;
- // TODO(nasko): Consider checking the |url| against CanAccessDataForOrigin.
+ // TODO(nasko): This check should be updated to apply to all URLs, not just
+ // standard ones.
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ if (url.IsStandard() &&
+ !policy->CanAccessDataForOrigin(GetProcess()->GetID(), url)) {
+ return false;
+ }
return true;
}
@@ -5281,9 +5448,7 @@ void RenderFrameHostImpl::UpdateAXTreeData() {
detail.updates[0].has_tree_data = true;
AXContentTreeDataToAXTreeData(&detail.updates[0].tree_data);
- if (browser_accessibility_manager_)
- browser_accessibility_manager_->OnAccessibilityEvents(detail);
-
+ SendAccessibilityEventsToManager(detail);
delegate_->AccessibilityEventReceived(detail);
}
@@ -5767,14 +5932,6 @@ void RenderFrameHostImpl::OnMediaInterfaceFactoryConnectionError() {
media_interface_proxy_.reset();
}
-void RenderFrameHostImpl::BindWakeLockRequest(
- device::mojom::WakeLockRequest request) {
- device::mojom::WakeLock* renderer_wake_lock =
- delegate_ ? delegate_->GetRendererWakeLock() : nullptr;
- if (renderer_wake_lock)
- renderer_wake_lock->AddClient(std::move(request));
-}
-
#if defined(OS_ANDROID)
void RenderFrameHostImpl::BindNFCRequest(device::mojom::NFCRequest request) {
if (delegate_)
@@ -5813,12 +5970,35 @@ void RenderFrameHostImpl::BindPresentationServiceRequest(
presentation_service_->Bind(std::move(request));
}
+void RenderFrameHostImpl::BindIdleManagerRequest(
+ blink::mojom::IdleManagerRequest request) {
+ if (!IsFeatureEnabled(blink::mojom::FeaturePolicyFeature::kIdleDetection)) {
+ mojo::ReportBadMessage("Feature policy blocks access to IdleDetection.");
+ return;
+ }
+ static_cast<StoragePartitionImpl*>(GetProcess()->GetStoragePartition())
+ ->GetIdleManager()
+ ->CreateService(std::move(request));
+}
+
blink::mojom::FileChooserPtr RenderFrameHostImpl::BindFileChooserForTesting() {
blink::mojom::FileChooserPtr chooser;
FileChooserImpl::Create(this, mojo::MakeRequest(&chooser));
return chooser;
}
+void RenderFrameHostImpl::BindSmsManagerRequest(
+ blink::mojom::SmsManagerRequest request) {
+ if (GetParent()) {
+ mojo::ReportBadMessage("Must be in top-level browser context.");
+ return;
+ }
+ SmsService* sms_service = GetProcess()->GetBrowserContext()->GetSmsService();
+ if (sms_service) {
+ sms_service->Bind(std::move(request), GetLastCommittedOrigin());
+ }
+}
+
void RenderFrameHostImpl::GetInterface(
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
@@ -5861,11 +6041,6 @@ void RenderFrameHostImpl::GetAuthenticator(
blink::mojom::AuthenticatorRequest request) {
#if !defined(OS_ANDROID)
if (base::FeatureList::IsEnabled(features::kWebAuth)) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableWebAuthTestingAPI)) {
- ScopedVirtualAuthenticatorEnvironment::GetInstance();
- }
-
BindAuthenticatorRequest(std::move(request));
}
#else
@@ -5885,14 +6060,31 @@ void RenderFrameHostImpl::GetVirtualAuthenticatorManager(
if (base::FeatureList::IsEnabled(features::kWebAuth)) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWebAuthTestingAPI)) {
- auto* environment_singleton =
- ScopedVirtualAuthenticatorEnvironment::GetInstance();
- environment_singleton->AddBinding(std::move(request));
+ auto* environment_singleton = AuthenticatorEnvironmentImpl::GetInstance();
+ environment_singleton->EnableVirtualAuthenticatorFor(this);
+ environment_singleton->AddVirtualAuthenticatorBinding(this,
+ std::move(request));
}
}
#endif // !defined(OS_ANDROID)
}
+void RenderFrameHostImpl::RegisterAppCacheHost(
+ blink::mojom::AppCacheHostRequest host_request,
+ blink::mojom::AppCacheFrontendPtr frontend,
+ const base::UnguessableToken& host_id) {
+ auto* appcache_service_impl = static_cast<AppCacheServiceImpl*>(
+ GetProcess()->GetStoragePartition()->GetAppCacheService());
+
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&AppCacheServiceImpl::RegisterHostForFrame,
+ appcache_service_impl->AsWeakPtr(),
+ std::move(host_request), frontend.PassInterface(), host_id,
+ routing_id_, GetProcess()->GetID(),
+ mojo::GetBadMessageCallback()));
+}
+
std::unique_ptr<NavigationRequest>
RenderFrameHostImpl::CreateNavigationRequestForCommit(
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
@@ -6128,6 +6320,69 @@ bool RenderFrameHostImpl::ValidateDidCommitParams(
VLOG(1) << "Blocked URL " << validated_params->url.spec();
LogRendererKillCrashKeys(GetSiteInstance()->GetSiteURL());
+ // Temporary instrumentation to debug the root cause of renderer process
+ // terminations. See https://crbug.com/931895.
+ auto bool_to_crash_key = [](bool b) { return b ? "true" : "false"; };
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString("is_same_document",
+ base::debug::CrashKeySize::Size32),
+ bool_to_crash_key(is_same_document_navigation));
+
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString("is_main_frame",
+ base::debug::CrashKeySize::Size32),
+ bool_to_crash_key(frame_tree_node_->IsMainFrame()));
+
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString("is_cross_process_subframe",
+ base::debug::CrashKeySize::Size32),
+ bool_to_crash_key(IsCrossProcessSubframe()));
+
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString("site_lock",
+ base::debug::CrashKeySize::Size256),
+ GetSiteInstance()->lock_url().spec());
+
+ if (navigation_request && navigation_request->navigation_handle()) {
+ NavigationHandleImpl* handle = navigation_request->navigation_handle();
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString(
+ "is_renderer_initiated", base::debug::CrashKeySize::Size32),
+ bool_to_crash_key(handle->IsRendererInitiated()));
+
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString(
+ "is_server_redirect", base::debug::CrashKeySize::Size32),
+ bool_to_crash_key(handle->WasServerRedirect()));
+
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString(
+ "is_form_submission", base::debug::CrashKeySize::Size32),
+ bool_to_crash_key(handle->IsFormSubmission()));
+
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString(
+ "is_error_page", base::debug::CrashKeySize::Size32),
+ bool_to_crash_key(handle->IsErrorPage()));
+
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString(
+ "net_error_code", base::debug::CrashKeySize::Size32),
+ base::NumberToString(navigation_request->net_error()));
+
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString(
+ "initiator_origin", base::debug::CrashKeySize::Size64),
+ handle->GetInitiatorOrigin()
+ ? handle->GetInitiatorOrigin()->GetDebugString()
+ : "none");
+
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString(
+ "starting_site_instance", base::debug::CrashKeySize::Size64),
+ handle->GetStartingSiteInstance()->GetSiteURL().spec());
+ }
+
// Kills the process.
bad_message::ReceivedBadMessage(process,
bad_message::RFH_CAN_COMMIT_URL_BLOCKED);
@@ -6259,13 +6514,57 @@ bool RenderFrameHostImpl::DidCommitNavigationInternal(
!GetParent());
// Check that the committing navigation token matches the navigation request.
- std::unique_ptr<NavigationRequest> invalid_request = nullptr;
if (navigation_request &&
navigation_request->commit_params().navigation_token !=
validated_params->navigation_token) {
navigation_request.reset();
- // TODO(clamy): We should kill the renderer in all cases where we expect to
- // have a NavigationRequest matching the commit URL.
+ }
+
+ if (!navigation_request) {
+ // A matching NavigationRequest should have been found, unless in a few very
+ // specific cases. Check if this is one of those cases.
+ bool is_commit_allowed_to_proceed = false;
+
+ // 1) This was a renderer-initiated navigation to a URL that doesn't need
+ // to be handled by the network stack (eg. about:blank).
+ is_commit_allowed_to_proceed |=
+ !IsURLHandledByNetworkStack(validated_params->url);
+
+ // 2) This was a same-document navigation.
+ // TODO(clamy): We should enforce having a request on browser-initiated
+ // same-document navigations.
+ is_commit_allowed_to_proceed |= is_same_document_navigation;
+
+ // 3) This was a navigation to a subframe in an MHTML archive.
+ is_commit_allowed_to_proceed |=
+ GetParent() && frame_tree_node_->frame_tree()
+ ->root()
+ ->current_frame_host()
+ ->is_mhtml_document();
+
+ // 4) Transient interstitial page commits will not have a matching
+ // NavigationRequest.
+ // TODO(clamy): Enforce having a NavigationRequest for data URLs when
+ // committed interstitials have launched or interstitials create
+ // NavigationRequests.
+ is_commit_allowed_to_proceed |= !!delegate_->GetAsInterstitialPage();
+
+ // 5) Error pages implementations in Chrome can commit twice.
+ // TODO(clamy): Fix this.
+ is_commit_allowed_to_proceed |= validated_params->url_is_unreachable;
+
+ // 6) Special case for DOMSerializerBrowsertests which are implemented
+ // entirely renderer-side and unlike normal RenderView based tests load
+ // file URLs instead of data URLs.
+ // TODO(clamy): Rework the tests to remove this exception.
+ is_commit_allowed_to_proceed |= validated_params->url.SchemeIsFile();
+
+ if (!is_commit_allowed_to_proceed) {
+ bad_message::ReceivedBadMessage(
+ GetProcess(),
+ bad_message::RFH_NO_MATCHING_NAVIGATION_REQUEST_ON_COMMIT);
+ return false;
+ }
}
if (!ValidateDidCommitParams(navigation_request.get(), validated_params,
@@ -6273,36 +6572,12 @@ bool RenderFrameHostImpl::DidCommitNavigationInternal(
return false;
}
+ // TODO(clamy): We should stop having a special case for same-document
+ // navigation and just put them in the general map of NavigationRequests.
if (navigation_request &&
- navigation_request->common_params().url != validated_params->url) {
- // At this point we know that the right/matching |navigation_request| has
- // already been found based on token matching performed or the commit
- // originated from a NavigationClient owned by the NavigationRequest. OTOH,
- // we cannot use its NavigationHandle, because it has a mismatched URL
- // (which would cause DCHECKs - for example in
- // NavigationHandleImpl::DidCommitNavigation).
- //
- // Because of the above, if the URL does not match what the NavigationHandle
- // expects, we want to treat the commit as a new navigation.
- //
- // The URL mismatch can happen when loading a Data navigation with
- // LoadDataWithBaseURL.
- // TODO(csharrison): Data navigations loaded with LoadDataWithBaseURL get
- // reset here, because the NavigationHandle tracks the URL but the
- // params.url tracks the data. The trick of saving the old entry ids for
- // these navigations should go away when this is properly handled. See
- // https://crbug.com/588317.
- //
- // Other cases are where URL mismatch can happen is when committing an error
- // page - for example this can happen during CSP/frame-ancestors checks (see
- // https://crbug.com/759184).
- //
- // TODO(clamy): We should support the URL filtering without deleting the
- // request.
-
- // Note: the NavigationRequest is not reset here, as this could potentially
- // lead to the deletion of the pending NavigationEntry.
- invalid_request = std::move(navigation_request);
+ navigation_request->common_params().url != validated_params->url &&
+ is_same_document_navigation) {
+ same_document_navigation_request_ = std::move(navigation_request);
}
// Set is loading to true now if it has not been set yet. This happens for
@@ -6323,21 +6598,8 @@ bool RenderFrameHostImpl::DidCommitNavigationInternal(
// one in order to properly issue DidFinishNavigation calls to
// WebContentsObservers.
if (!navigation_request) {
- // First check if there was a request for this navigation that cannot be
- // used due to URL mismatch. If that's the case and it corresponds to a
- // navigation to the pending NavigationEntry, the new request should be
- // associated with the pending NavigationEntry as well so that the pending
- // NavigationEntry is properly committed.
- NavigationEntryImpl* entry_for_navigation = nullptr;
- if (invalid_request && NavigationRequestWasIntendedForPendingEntry(
- invalid_request.get(), *validated_params,
- is_same_document_navigation)) {
- entry_for_navigation = NavigationEntryImpl::FromNavigationEntry(
- frame_tree_node()->navigator()->GetController()->GetPendingEntry());
- }
-
navigation_request = CreateNavigationRequestForCommit(
- *validated_params, is_same_document_navigation, entry_for_navigation);
+ *validated_params, is_same_document_navigation, nullptr);
}
DCHECK(navigation_request);
@@ -6369,13 +6631,12 @@ bool RenderFrameHostImpl::DidCommitNavigationInternal(
std::move(navigation_request),
is_same_document_navigation);
- // TODO(clamy): We should stop having a special case for same-document
- // navigation and just put them in the general map of NavigationRequests.
- if (is_same_document_navigation && invalid_request)
- same_document_navigation_request_ = std::move(invalid_request);
-
- if (!is_same_document_navigation)
- scheduler_tracked_features_ = 0;
+ if (!is_same_document_navigation) {
+ cookie_no_samesite_deprecation_url_hashes_.clear();
+ cookie_samesite_none_insecure_deprecation_url_hashes_.clear();
+ renderer_reported_scheduler_tracked_features_ = 0;
+ browser_reported_scheduler_tracked_features_ = 0;
+ }
return true;
}
@@ -6559,7 +6820,7 @@ void RenderFrameHostImpl::SendCommitFailedNavigation(
}
}
-// Called when the renderer navigates. For every frame loaded, we'll get this
+// Called when the renderer navigates. For every frame loaded, we'll get this
// notification containing parameters identifying the navigation.
void RenderFrameHostImpl::DidCommitNavigation(
std::unique_ptr<NavigationRequest> committing_navigation_request,
@@ -6688,6 +6949,10 @@ void RenderFrameHostImpl::DidCommitNavigation(
RenderWidgetHostImpl::From(GetView()->GetRenderWidgetHost())
->DidNavigate(validated_params->content_source_id);
}
+
+ // TODO(arthursonzogni): This can be removed when RenderDocument will be
+ // implemented. See https://crbug.com/936696.
+ EnsureDescendantsAreUnloading();
}
mojom::FrameNavigationControl::CommitNavigationCallback
@@ -6727,21 +6992,14 @@ RenderFrameHostImpl::BuildNavigationClientCommitFailedNavigationCallback(
}
void RenderFrameHostImpl::UpdateFrameFrozenState() {
- if (!base::FeatureList::IsEnabled(features::kFreezeFramesOnVisibility))
- return;
-
- // If the document is in the loading state keep it still loading.
- if (is_loading_)
- return;
-
- // TODO(dtapuska): Adjust these based on feature policies when
- // they are available.
- // Feature policies don't support parameterized values yet.
- // crbug.com/924568, crbug.com/907125
- if (visibility_ == blink::mojom::FrameVisibility::kNotRendered) {
+ if (!IsFeatureEnabled(
+ blink::mojom::FeaturePolicyFeature::kExecutionWhileNotRendered) &&
+ visibility_ == blink::mojom::FrameVisibility::kNotRendered) {
frame_->SetLifecycleState(blink::mojom::FrameLifecycleState::kFrozen);
- } else if (visibility_ ==
- blink::mojom::FrameVisibility::kRenderedOutOfViewport) {
+ } else if (!IsFeatureEnabled(blink::mojom::FeaturePolicyFeature::
+ kExecutionWhileOutOfViewport) &&
+ visibility_ ==
+ blink::mojom::FrameVisibility::kRenderedOutOfViewport) {
frame_->SetLifecycleState(
blink::mojom::FrameLifecycleState::kFrozenAutoResumeMedia);
} else {
@@ -6772,4 +7030,122 @@ bool RenderFrameHostImpl::IsTestRenderFrameHost() const {
return false;
}
+scoped_refptr<PrefetchedSignedExchangeCache>
+RenderFrameHostImpl::EnsurePrefetchedSignedExchangeCache() {
+ if (!base::FeatureList::IsEnabled(
+ features::kSignedExchangeSubresourcePrefetch)) {
+ return nullptr;
+ }
+ if (!prefetched_signed_exchange_cache_) {
+ prefetched_signed_exchange_cache_ =
+ base::MakeRefCounted<PrefetchedSignedExchangeCache>();
+ }
+ return prefetched_signed_exchange_cache_;
+}
+
+RenderWidgetHostImpl* RenderFrameHostImpl::GetLocalRenderWidgetHost() const {
+ if (!parent_)
+ return render_view_host_->GetWidget();
+ else
+ return owned_render_widget_host_.get();
+}
+
+void RenderFrameHostImpl::EnsureDescendantsAreUnloading() {
+ std::vector<RenderFrameHostImpl*> parents_to_be_checked = {this};
+ std::vector<RenderFrameHostImpl*> rfhs_to_be_checked;
+ while (!parents_to_be_checked.empty()) {
+ RenderFrameHostImpl* document = parents_to_be_checked.back();
+ parents_to_be_checked.pop_back();
+
+ for (auto& subframe : document->children_) {
+ RenderFrameHostImpl* child = subframe->current_frame_host();
+ // Every child is expected to be pending deletion. If it isn't the
+ // case, their FrameTreeNode is immediately removed from the tree.
+ if (child->unload_state_ == UnloadState::NotRun)
+ rfhs_to_be_checked.push_back(child);
+ else
+ parents_to_be_checked.push_back(child);
+ }
+ }
+ for (RenderFrameHostImpl* document : rfhs_to_be_checked)
+ document->parent_->RemoveChild(document->frame_tree_node());
+}
+
+void RenderFrameHostImpl::AddUniqueMessageToConsole(
+ blink::mojom::ConsoleMessageLevel level,
+ const std::string& message) {
+ AddMessageToConsoleImpl(level, message, true /* discard_duplicates */);
+}
+
+void RenderFrameHostImpl::AddMessageToConsoleImpl(
+ blink::mojom::ConsoleMessageLevel level,
+ const std::string& message,
+ bool discard_duplicates) {
+ Send(new FrameMsg_AddMessageToConsole(routing_id_, level, message,
+ discard_duplicates));
+}
+
+void RenderFrameHostImpl::AddSameSiteCookieDeprecationMessage(
+ const std::string& cookie_url,
+ net::CanonicalCookie::CookieInclusionStatus status) {
+ std::string deprecation_message;
+ if (status == net::CanonicalCookie::CookieInclusionStatus::
+ EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX) {
+ if (!ShouldAddCookieSameSiteDeprecationMessage(
+ cookie_url, &cookie_no_samesite_deprecation_url_hashes_)) {
+ return;
+ }
+ deprecation_message =
+ "[Deprecation] A cookie associated with a cross-site resource at " +
+ cookie_url +
+ " was set without the `SameSite` attribute. "
+ "A future release of Chrome will only deliver cookies with "
+ "cross-site requests if they are set with `SameSite=None`. You "
+ "can review cookies in developer tools under "
+ "Application>Storage>Cookies and see more details at "
+ "https://www.chromestatus.com/feature/5088147346030592.";
+ }
+ if (status == net::CanonicalCookie::CookieInclusionStatus::
+ EXCLUDE_SAMESITE_NONE_INSECURE) {
+ if (!ShouldAddCookieSameSiteDeprecationMessage(
+ cookie_url,
+ &cookie_samesite_none_insecure_deprecation_url_hashes_)) {
+ return;
+ }
+ deprecation_message =
+ "[Deprecation] A cookie associated with a resource at " + cookie_url +
+ " was set with `SameSite=None` but without `Secure`. "
+ "A future release of Chrome will only deliver cookies marked "
+ "`SameSite=None` if they are also marked `Secure`. You "
+ "can review cookies in developer tools under "
+ "Application>Storage>Cookies and see more details at "
+ "https://www.chromestatus.com/feature/5633521622188032.";
+ }
+
+ if (deprecation_message.empty())
+ return;
+
+ AddUniqueMessageToConsole(blink::mojom::ConsoleMessageLevel::kWarning,
+ deprecation_message);
+}
+
+bool RenderFrameHostImpl::ShouldAddCookieSameSiteDeprecationMessage(
+ const std::string& cookie_url,
+ base::circular_deque<size_t>* already_seen_url_hashes) {
+ DCHECK_LE(already_seen_url_hashes->size(), kMaxCookieSameSiteDeprecationUrls);
+ size_t cookie_url_hash = base::FastHash(cookie_url);
+ if (std::find(already_seen_url_hashes->begin(),
+ already_seen_url_hashes->end(),
+ cookie_url_hash) != already_seen_url_hashes->end()) {
+ return false;
+ }
+
+ // Put most recent ones at the front because we are likely to have multiple
+ // consecutive cookies with the same URL.
+ if (already_seen_url_hashes->size() == kMaxCookieSameSiteDeprecationUrls)
+ already_seen_url_hashes->pop_back();
+ already_seen_url_hashes->push_front(cookie_url_hash);
+ return true;
+}
+
} // 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 1da0a57d6bc..30f1fad5253 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.h
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.h
@@ -18,6 +18,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
+#include "base/containers/circular_deque.h"
#include "base/containers/flat_set.h"
#include "base/containers/id_map.h"
#include "base/gtest_prod_util.h"
@@ -51,12 +52,14 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host_observer.h"
#include "content/public/common/javascript_dialog_type.h"
#include "content/public/common/previews_state.h"
#include "content/public/common/transferrable_url_loader.mojom.h"
#include "media/mojo/interfaces/interface_factory.mojom.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/system/data_pipe.h"
+#include "net/cookies/canonical_cookie.h"
#include "net/http/http_response_headers.h"
#include "services/device/public/mojom/wake_lock_context.mojom.h"
#include "services/service_manager/public/cpp/binder_registry.h"
@@ -65,17 +68,19 @@
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
#include "third_party/blink/public/common/frame/user_activation_update_type.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "third_party/blink/public/mojom/commit_result/commit_result.mojom.h"
#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h"
#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
#include "third_party/blink/public/mojom/frame/navigation_initiator.mojom.h"
+#include "third_party/blink/public/mojom/idle/idle_manager.mojom.h"
#include "third_party/blink/public/mojom/presentation/presentation.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
+#include "third_party/blink/public/mojom/sms/sms_manager.mojom-forward.h"
#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
#include "third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom.h"
-#include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
#include "third_party/blink/public/platform/web_focus_type.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
#include "third_party/blink/public/platform/web_scroll_types.h"
@@ -99,8 +104,6 @@ class GURL;
struct AccessibilityHostMsg_EventBundleParams;
struct AccessibilityHostMsg_FindInPageResultParams;
struct AccessibilityHostMsg_LocationChangeParams;
-struct FrameHostMsg_DidCommitProvisionalLoad_Params;
-struct FrameHostMsg_DidFailProvisionalLoadWithError_Params;
struct FrameHostMsg_OpenURL_Params;
struct FrameMsg_TextTrackSettings_Params;
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
@@ -141,6 +144,7 @@ class NavigationEntryImpl;
class NavigationHandleImpl;
class NavigationRequest;
class PermissionServiceContext;
+class PrefetchedSignedExchangeCache;
class PresentationServiceImpl;
class RenderFrameHostDelegate;
class RenderFrameHostImpl;
@@ -175,6 +179,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
public base::SupportsUserData,
public mojom::FrameHost,
public BrowserAccessibilityDelegate,
+ public RenderProcessHostObserver,
public SiteInstanceImpl::Observer,
public service_manager::mojom::InterfaceProvider,
public blink::mojom::DocumentInterfaceBroker,
@@ -220,6 +225,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
const std::string& GetFrameName() override;
bool IsFrameDisplayNone() override;
const base::Optional<gfx::Size>& GetFrameSize() override;
+ size_t GetFrameDepth() override;
bool IsCrossProcessSubframe() override;
const GURL& GetLastCommittedURL() override;
const url::Origin& GetLastCommittedOrigin() override;
@@ -276,6 +282,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
void PrepareForInnerWebContentsAttach(
PrepareForInnerWebContentsAttachCallback callback) override;
void UpdateSubresourceLoaderFactories() override;
+ blink::FrameOwnerElementType GetFrameOwnerElementType() override;
+ void SendAccessibilityEventsToManager(
+ const AXEventNotificationDetails& details);
// IPC::Sender
bool Send(IPC::Message* msg) override;
@@ -296,7 +305,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override;
gfx::NativeViewAccessible AccessibilityGetNativeViewAccessibleForWindow()
override;
- bool AccessibilityIsMainFrame() override;
+ bool AccessibilityIsMainFrame() const override;
+
+ // RenderProcessHostObserver implementation.
+ void RenderProcessExited(RenderProcessHost* host,
+ const ChildProcessTerminationInfo& info) override;
// SiteInstanceImpl::Observer
void RenderProcessGone(SiteInstanceImpl* site_instance) override;
@@ -384,7 +397,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
RenderViewHostImpl* render_view_host() { return render_view_host_; }
RenderFrameHostDelegate* delegate() { return delegate_; }
- FrameTreeNode* frame_tree_node() { return frame_tree_node_; }
+ FrameTreeNode* frame_tree_node() const { return frame_tree_node_; }
// Methods to add/remove/reset/query child FrameTreeNodes of this frame.
// See class-level comment for FrameTreeNode for how the frame tree is
@@ -432,7 +445,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
// distinguished by owning a RenderWidgetHost, which manages input events
// and painting for this frame and its contiguous local subtree in the
// renderer process.
- bool is_local_root() const { return !!render_widget_host_; }
+ bool is_local_root() const { return !!GetLocalRenderWidgetHost(); }
// Returns the RenderWidgetHostImpl attached to this frame or the nearest
// ancestor frame, which could potentially be the root. For most input
@@ -868,17 +881,18 @@ class CONTENT_EXPORT RenderFrameHostImpl
// identified by |portal_token| with the interface |portal|. The activation
// can optionally include a message |data| dispatched with the
// PortalActivateEvent.
- void OnPortalActivated(const base::UnguessableToken& portal_token,
- blink::mojom::PortalAssociatedPtrInfo portal,
- blink::TransferableMessage data,
- base::OnceCallback<void(bool)> callback);
+ void OnPortalActivated(
+ const base::UnguessableToken& portal_token,
+ blink::mojom::PortalAssociatedPtrInfo portal,
+ blink::mojom::PortalClientAssociatedRequest portal_client,
+ blink::TransferableMessage data,
+ base::OnceCallback<void(bool)> callback);
// Called on the main frame of a page embedded in a Portal to forward a
- // message to the PortalHost object in the frame.
- void ForwardMessageToPortalHost(
- blink::TransferableMessage message,
- const url::Origin& source_origin,
- const base::Optional<url::Origin>& target_origin);
+ // message from the host of a portal.
+ void ForwardMessageFromHost(blink::TransferableMessage message,
+ const url::Origin& source_origin,
+ const base::Optional<url::Origin>& target_origin);
// mojom::FrameHost:
void VisibilityChanged(blink::mojom::FrameVisibility) override;
@@ -916,12 +930,34 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Scheduler-relevant features this frame is using, for use in metrics.
// See comments at |scheduler_tracked_features_|.
- // NOTE: It now always returns 0 for subframes.
- // TODO(altimin): Support subframes here as well.
uint64_t scheduler_tracked_features() const {
- return scheduler_tracked_features_;
+ return renderer_reported_scheduler_tracked_features_ |
+ browser_reported_scheduler_tracked_features_;
}
+ // Returns a PrefetchedSignedExchangeCache which is attached to |this| iff
+ // SignedExchangeSubresourcePrefetch feature is enabled.
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ EnsurePrefetchedSignedExchangeCache();
+
+ // Adds |message| to the DevTools console only if it is unique (i.e. has not
+ // been added to the console previously from this frame).
+ virtual void AddUniqueMessageToConsole(
+ blink::mojom::ConsoleMessageLevel level,
+ const std::string& message);
+
+ // Add cookie SameSite deprecation messages to the DevTools console.
+ // TODO(crbug.com/977040): Remove when no longer needed.
+ void AddSameSiteCookieDeprecationMessage(
+ const std::string& cookie_url,
+ net::CanonicalCookie::CookieInclusionStatus status);
+
+ // Notify the scheduler that this frame used a feature which impacts the
+ // scheduling policy (e.g. whether the frame can be frozen or put into the
+ // back-forward cache).
+ void OnSchedulerTrackedFeatureUsed(
+ blink::scheduler::WebSchedulerTrackedFeature feature);
+
protected:
friend class RenderFrameHostFactory;
@@ -1046,29 +1082,27 @@ class CONTENT_EXPORT RenderFrameHostImpl
NavigationCommitInIframePendingDeletionAB);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
NavigationCommitInIframePendingDeletionABC);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ CommittedOriginIncompatibleWithOriginLock);
+ FRIEND_TEST_ALL_PREFIXES(
+ SitePerProcessBrowserTest,
+ IsDetachedSubframeObservableDuringUnloadHandlerSameProcess);
+ FRIEND_TEST_ALL_PREFIXES(
+ SitePerProcessBrowserTest,
+ IsDetachedSubframeObservableDuringUnloadHandlerCrossProcess);
class DroppedInterfaceRequestLogger;
// IPC Message handlers.
- void OnDidAddMessageToConsole(int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id);
void OnDetach();
void OnFrameFocused();
void OnOpenURL(const FrameHostMsg_OpenURL_Params& params);
- void OnDidFailProvisionalLoadWithError(
- const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params);
- void OnDidFailLoadWithError(const GURL& url,
- int error_code,
- const base::string16& error_description);
void OnUpdateState(const PageState& state);
void OnBeforeUnloadACK(
bool proceed,
const base::TimeTicks& renderer_before_unload_start_time,
const base::TimeTicks& renderer_before_unload_end_time);
void OnSwapOutACK();
- void OnRenderProcessGone(int status, int error_code);
void OnContextMenu(const ContextMenuParams& params);
void OnVisualStateResponse(uint64_t id);
void OnRunJavaScriptDialog(const base::string16& message,
@@ -1134,9 +1168,10 @@ class CONTENT_EXPORT RenderFrameHostImpl
const blink::WebScrollIntoViewParams& params);
void OnBubbleLogicalScrollInParentFrame(
blink::WebScrollDirection direction,
- blink::WebScrollGranularity granularity);
+ ui::input_types::ScrollGranularity granularity);
void OnFrameDidCallFocus();
void OnRenderFallbackContentInParentProcess();
+ void OnTransferUserActivationFrom(int32_t source_routing_id);
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
void OnShowPopup(const FrameHostMsg_ShowPopup_Params& params);
@@ -1160,6 +1195,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
void CreateNewWindow(mojom::CreateNewWindowParamsPtr params,
CreateNewWindowCallback callback) override;
void CreatePortal(blink::mojom::PortalAssociatedRequest request,
+ blink::mojom::PortalClientAssociatedPtrInfo client,
CreatePortalCallback callback) override;
void AdoptPortal(const base::UnguessableToken& portal_token,
AdoptPortalCallback callback) override;
@@ -1207,6 +1243,18 @@ class CONTENT_EXPORT RenderFrameHostImpl
void FullscreenStateChanged(bool is_fullscreen) override;
void DocumentOnLoadCompleted() override;
void UpdateActiveSchedulerTrackedFeatures(uint64_t features_mask) override;
+ void DidAddMessageToConsole(blink::mojom::ConsoleMessageLevel log_level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id) override;
+ void DidFailProvisionalLoadWithError(
+ const GURL& url,
+ int error_code,
+ const base::string16& error_description,
+ bool showing_repost_interstitial) override;
+ void DidFailLoadWithError(const GURL& url,
+ int error_code,
+ const base::string16& error_description) override;
#if defined(OS_ANDROID)
void UpdateUserGestureCarryoverInfo() override;
#endif
@@ -1346,6 +1394,10 @@ class CONTENT_EXPORT RenderFrameHostImpl
void BindPresentationServiceRequest(
blink::mojom::PresentationServiceRequest request);
+ void BindIdleManagerRequest(blink::mojom::IdleManagerRequest request);
+
+ void BindSmsManagerRequest(blink::mojom::SmsManagerRequest request);
+
// service_manager::mojom::InterfaceProvider:
void GetInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override;
@@ -1360,6 +1412,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
void GetAuthenticator(blink::mojom::AuthenticatorRequest request) override;
void GetVirtualAuthenticatorManager(
blink::test::mojom::VirtualAuthenticatorManagerRequest request) override;
+ void RegisterAppCacheHost(blink::mojom::AppCacheHostRequest host_request,
+ blink::mojom::AppCacheFrontendPtr frontend,
+ const base::UnguessableToken& host_id) override;
// Allows tests to disable the swapout event timer to simulate bugs that
// happen before it fires (to avoid flakiness).
@@ -1563,6 +1618,10 @@ class CONTENT_EXPORT RenderFrameHostImpl
// - Speculative RenderFrameHost.
void ResetNavigationsForPendingDeletion();
+ // Called on an unloading frame when its unload timeout is reached. This
+ // immediately deletes the RenderFrameHost.
+ void OnUnloadTimeout();
+
// Update the frozen state of the frame applying current inputs (visibility,
// loaded state) to determine the new state.
void UpdateFrameFrozenState();
@@ -1574,6 +1633,35 @@ class CONTENT_EXPORT RenderFrameHostImpl
FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params,
mojom::DidCommitProvisionalLoadInterfaceParamsPtr* interface_params);
+ // If this RenderFrameHost is a local root (i.e., either the main frame or a
+ // subframe in a different process than its parent), this returns the
+ // RenderWidgetHost corresponding to this frame. Otherwise this returns null.
+ // See also GetRenderWidgetHost(), which walks up the tree to find the nearest
+ // local root.
+ // Main frame: RenderWidgetHost is owned by the RenderViewHost.
+ // Subframe: RenderWidgetHost is owned by this RenderFrameHost.
+ RenderWidgetHostImpl* GetLocalRenderWidgetHost() const;
+
+ // Called after a new document commit. Every children of the previous document
+ // are expected to be deleted or at least to be pending deletion waiting for
+ // unload completion. A compromised renderer process or bugs can cause the
+ // renderer to "forget" to start deletion. In this case the browser deletes
+ // them immediately, without waiting for unload completion.
+ // https://crbug.com/950625.
+ void EnsureDescendantsAreUnloading();
+
+ // Implements AddMessageToConsole() and AddUniqueMessageToConsole().
+ void AddMessageToConsoleImpl(blink::mojom::ConsoleMessageLevel level,
+ const std::string& message,
+ bool discard_duplicates);
+
+ // Returns whether a cookie SameSite deprecation message should be sent for
+ // the given cookie url.
+ // TODO(crbug.com/977040): Remove when no longer needed.
+ bool ShouldAddCookieSameSiteDeprecationMessage(
+ const std::string& cookie_url,
+ base::circular_deque<size_t>* already_seen_url_hashes);
+
// 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
@@ -1631,13 +1719,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
std::map<uint64_t, VisualStateCallback> visual_state_callbacks_;
- // RenderFrameHosts that need management of the rendering and input events
- // for their frame subtrees require RenderWidgetHosts. This typically
- // means frames that are rendered in different processes from their parent
- // frames.
+ // Local root subframes directly own their RenderWidgetHost.
+ // Please see comments about the GetLocalRenderWidgetHost() function.
// TODO(kenrb): Later this will also be used on the top-level frame, when
// RenderFrameHost owns its RenderViewHost.
- RenderWidgetHostImpl* render_widget_host_;
+ std::unique_ptr<RenderWidgetHostImpl> owned_render_widget_host_;
const int routing_id_;
@@ -1992,8 +2078,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
std::unique_ptr<KeepAliveHandleFactory> keep_alive_handle_factory_;
base::TimeDelta keep_alive_timeout_;
- base::TimeDelta subframe_unload_timeout_;
-
// For observing Network Service connection errors only. Will trigger
// |OnNetworkServiceConnectionError()| and push updated factories to
// |RenderFrame|.
@@ -2040,6 +2124,13 @@ class CONTENT_EXPORT RenderFrameHostImpl
};
UnloadState unload_state_ = UnloadState::NotRun;
+ // If a subframe failed to finish running its unload handler after
+ // |subframe_unload_timeout_| the RenderFrameHost is deleted.
+ base::TimeDelta subframe_unload_timeout_;
+
+ // Call OnUnloadTimeout() when the unload timer expires.
+ base::OneShotTimer subframe_unload_timer_;
+
// BackForwardCache:
bool is_in_back_forward_cache_ = false;
@@ -2058,8 +2149,27 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Mask of the active features tracked by the scheduler used by this frame.
// This is used only for metrics.
// See blink::SchedulingPolicy::Feature for the meaning.
- // This value should be cleared on document commit.
- uint64_t scheduler_tracked_features_ = 0;
+ // These values should be cleared on document commit.
+ // Both are needed as some features are tracked in the renderer process and
+ // some in the browser process, depending on the design of each individual
+ // feature. They are tracked separately, because when the renderer updates the
+ // set of features, the browser ones should persist.
+ uint64_t renderer_reported_scheduler_tracked_features_ = 0;
+ uint64_t browser_reported_scheduler_tracked_features_ = 0;
+
+ // Holds prefetched signed exchanges for SignedExchangeSubresourcePrefetch.
+ // They will be passed to the next navigation.
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache_;
+
+ // Hold onto hashes of the last |kMaxCookieSameSiteDeprecationUrls| cookie
+ // URLs that we have seen since the last committed navigation, in order to
+ // partially deduplicate the corresponding cookie SameSite deprecation
+ // messages.
+ // TODO(crbug.com/977040): Remove when no longer needed.
+ base::circular_deque<size_t> cookie_no_samesite_deprecation_url_hashes_;
+ base::circular_deque<size_t>
+ cookie_samesite_none_insecure_deprecation_url_hashes_;
// NOTE: This must be the last member.
base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_;
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 1cbee543169..1545a38afbf 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
@@ -8,11 +8,14 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
@@ -27,6 +30,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_client.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"
@@ -34,6 +38,7 @@
#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/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "content/test/did_commit_navigation_interceptor.h"
@@ -723,7 +728,9 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBeforeUnloadBrowserTest,
DOMMessageQueue msg_queue;
GURL new_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
TestNavigationManager navigation_manager(web_contents(), new_url);
- EXPECT_TRUE(ExecuteScript(root, "location.href = '" + new_url.spec() + "';"));
+ // Use ExecuteScriptAsync because a ping may arrive before the script
+ // execution completion notification and confuse our expectations.
+ ExecuteScriptAsync(root, "location.href = '" + new_url.spec() + "';");
dialog_manager()->Wait();
// Answer the dialog and allow the navigation to proceed. Note that at this
@@ -768,8 +775,10 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBeforeUnloadBrowserTest,
DOMMessageQueue msg_queue;
GURL new_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
TestNavigationManager navigation_manager(web_contents(), new_url);
- EXPECT_TRUE(ExecuteScript(root->child_at(0),
- "location.href = '" + new_url.spec() + "';"));
+ // Use ExecuteScriptAsync because a ping may arrive before the script
+ // execution completion notification and confuse our expectations.
+ ExecuteScriptAsync(root->child_at(0),
+ "location.href = '" + new_url.spec() + "';");
navigation_manager.WaitForNavigationFinished();
EXPECT_EQ(new_url,
root->child_at(0)->current_frame_host()->GetLastCommittedURL());
@@ -2325,4 +2334,126 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
// Pass if this didn't crash.
}
+// Verify that adding an <object> tag which resource is blocked by the network
+// stack does not result in terminating the renderer process.
+// See https://crbug.com/955777.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ ObjectTagBlockedResource) {
+ EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL(
+ "/page_with_object_fallback.html")));
+
+ GURL object_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ std::unique_ptr<URLLoaderInterceptor> url_interceptor =
+ URLLoaderInterceptor::SetupRequestFailForURL(object_url,
+ net::ERR_BLOCKED_BY_CLIENT);
+
+ auto* rfh = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+ TestNavigationObserver observer(shell()->web_contents());
+ EXPECT_TRUE(ExecJs(shell()->web_contents(),
+ JsReplace("setUrl($1, true);", object_url)));
+ observer.Wait();
+ EXPECT_EQ(rfh->GetLastCommittedOrigin().Serialize(),
+ EvalJs(shell()->web_contents(), "window.origin"));
+}
+
+// Regression test for crbug.com/953934. It shouldn't crash if we quickly remove
+// an object element in the middle of its failing navigation.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ NoCrashOnRemoveObjectElementWithInvalidData) {
+ base::FilePath test_data_dir;
+ CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir));
+ base::FilePath file_repro_path =
+ test_data_dir.Append(GetTestDataFilePath())
+ .Append(FILE_PATH_LITERAL(
+ "remove_object_element_with_invalid_data.html"));
+ GURL url(file_repro_path.value());
+
+ RenderProcessHostWatcher crash_observer(
+ shell()->web_contents(),
+ RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+
+ // This navigates to a page with an object element that will fail to load.
+ // When document load event hits, it'll attempt to remove that object element.
+ // This might happen while the object element's failed commit is underway.
+ // To make sure we hit these conditions and that we don't exit the test too
+ // soon, let's wait until the document.readyState finalizes. We don't really
+ // care if that succeeds since, in the failing case, the renderer is crashing.
+ NavigateToURL(shell(), url);
+ ignore_result(
+ WaitForRenderFrameReady(shell()->web_contents()->GetMainFrame()));
+
+ EXPECT_TRUE(crash_observer.did_exit_normally());
+}
+
+// Test deduplication of SameSite cookie deprecation messages.
+// TODO(crbug.com/976475): This test is flaky.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ DISABLED_SameSiteCookieDeprecationMessages) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kCookieDeprecationMessages);
+
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ ConsoleObserverDelegate console_observer(web_contents, "*");
+ web_contents->SetDelegate(&console_observer);
+
+ // Test deprecation messages for SameSiteByDefault.
+ // Set a cookie without SameSite on b.com, then access it in a cross-site
+ // context.
+ GURL url =
+ embedded_test_server()->GetURL("b.com", "/set-cookie?nosamesite=1");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ ASSERT_EQ(0u, console_observer.messages().size());
+ url = embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(),b())");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ // Only 1 message even though there are 2 cross-site iframes.
+ EXPECT_EQ(1u, console_observer.messages().size());
+
+ // Test deprecation messages for CookiesWithoutSameSiteMustBeSecure.
+ // Set a cookie with SameSite=None but without Secure.
+ url = embedded_test_server()->GetURL(
+ "c.com", "/set-cookie?samesitenoneinsecure=1;SameSite=None");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ // The 1 message from before, plus the (different) message for setting the
+ // SameSite=None insecure cookie.
+ EXPECT_EQ(2u, console_observer.messages().size());
+ // Another copy of the message appears because we have navigated.
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ EXPECT_EQ(3u, console_observer.messages().size());
+ EXPECT_EQ(console_observer.messages()[1], console_observer.messages()[2]);
+}
+
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ SchedulerTrackedFeatures) {
+ EXPECT_TRUE(
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
+ RenderFrameHostImpl* main_frame = reinterpret_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+ // Simulate getting 0b1 as a feature vector from the renderer.
+ static_cast<mojom::FrameHost*>(main_frame)
+ ->UpdateActiveSchedulerTrackedFeatures(0b1u);
+ DCHECK_EQ(main_frame->scheduler_tracked_features(), 0b1u);
+ // Simulate the browser side reporting a feature usage.
+ main_frame->OnSchedulerTrackedFeatureUsed(
+ static_cast<blink::scheduler::WebSchedulerTrackedFeature>(1));
+ DCHECK_EQ(main_frame->scheduler_tracked_features(), 0b11u);
+ // Simulate a feature vector being updated from the renderer with some
+ // features being activated and some being deactivated.
+ static_cast<mojom::FrameHost*>(main_frame)
+ ->UpdateActiveSchedulerTrackedFeatures(0b100u);
+ DCHECK_EQ(main_frame->scheduler_tracked_features(), 0b110u);
+
+ // Navigate away and expect that no values persist the navigation.
+ // Note that we are still simulating the renderer call, otherwise features
+ // like "document loaded" will show up here.
+ EXPECT_TRUE(
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html")));
+ main_frame = reinterpret_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+ static_cast<mojom::FrameHost*>(main_frame)
+ ->UpdateActiveSchedulerTrackedFeatures(0b0u);
+}
+
} // namespace content
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 8424a63b37a..297b61198dd 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc
@@ -175,23 +175,10 @@ RenderWidgetHostView* RenderFrameHostManager::GetRenderWidgetHostView() const {
return nullptr;
}
-bool RenderFrameHostManager::ForInnerDelegate() {
- return delegate_->GetOuterDelegateFrameTreeNodeId() !=
- FrameTreeNode::kFrameTreeNodeInvalidId;
-}
-
-RenderWidgetHostImpl*
-RenderFrameHostManager::GetOuterRenderWidgetHostForKeyboardInput() {
- if (!ForInnerDelegate() || !frame_tree_node_->IsMainFrame())
- return nullptr;
-
- FrameTreeNode* outer_contents_frame_tree_node =
- FrameTreeNode::GloballyFindByID(
- delegate_->GetOuterDelegateFrameTreeNodeId());
- return outer_contents_frame_tree_node->parent()
- ->current_frame_host()
- ->render_view_host()
- ->GetWidget();
+bool RenderFrameHostManager::IsMainFrameForInnerDelegate() {
+ return frame_tree_node_->IsMainFrame() &&
+ delegate_->GetOuterDelegateFrameTreeNodeId() !=
+ FrameTreeNode::kFrameTreeNodeInvalidId;
}
FrameTreeNode* RenderFrameHostManager::GetOuterDelegateNode() {
@@ -211,6 +198,8 @@ RenderFrameProxyHost* RenderFrameHostManager::GetProxyToParent() {
}
RenderFrameProxyHost* RenderFrameHostManager::GetProxyToOuterDelegate() {
+ // Only the main frame should be able to reach the outer WebContents.
+ DCHECK(frame_tree_node_->IsMainFrame());
int outer_contents_frame_tree_node_id =
delegate_->GetOuterDelegateFrameTreeNodeId();
FrameTreeNode* outer_contents_frame_tree_node =
@@ -226,6 +215,9 @@ RenderFrameProxyHost* RenderFrameHostManager::GetProxyToOuterDelegate() {
}
void RenderFrameHostManager::RemoveOuterDelegateFrame() {
+ // Removing the outer delegate frame will destroy the inner WebContents. This
+ // should only be called on the main frame.
+ DCHECK(frame_tree_node_->IsMainFrame());
FrameTreeNode* outer_delegate_frame_tree_node =
FrameTreeNode::GloballyFindByID(
delegate_->GetOuterDelegateFrameTreeNodeId());
@@ -771,6 +763,37 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
GetNavigatingWebUI()->RenderFrameCreated(navigation_rfh);
}
+ // If this function picked an incompatible process for the URL, capture a
+ // crash dump to diagnose why it is occurring.
+ // TODO(creis): Remove this check after we've gathered enough information to
+ // debug issues with browser-side security checks. https://crbug.com/931895.
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ const GURL& lock_url = navigation_rfh->GetSiteInstance()->lock_url();
+ if (lock_url != GURL(kUnreachableWebDataURL) &&
+ request.common_params().url.IsStandard() &&
+ !policy->CanAccessDataForOrigin(navigation_rfh->GetProcess()->GetID(),
+ request.common_params().url)) {
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString("lock_url",
+ base::debug::CrashKeySize::Size64),
+ lock_url.spec());
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString("commit_origin",
+ base::debug::CrashKeySize::Size64),
+ request.common_params().url.GetOrigin().spec());
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString("is_main_frame",
+ base::debug::CrashKeySize::Size32),
+ frame_tree_node_->IsMainFrame() ? "true" : "false");
+ base::debug::SetCrashKeyString(
+ base::debug::AllocateCrashKeyString("use_current_rfh",
+ base::debug::CrashKeySize::Size32),
+ use_current_rfh ? "true" : "false");
+ NOTREACHED() << "Picked an incompatible process for URL: " << lock_url
+ << " lock vs " << request.common_params().url.GetOrigin();
+ base::debug::DumpWithoutCrashing();
+ }
+
return navigation_rfh;
}
@@ -1207,7 +1230,9 @@ RenderFrameHostManager::GetSiteInstanceForNavigation(
// consolidated into existing processes for that site.
SiteInstanceImpl* new_instance_impl =
static_cast<SiteInstanceImpl*>(new_instance.get());
- if (!frame_tree_node_->IsMainFrame() && !new_instance_impl->HasProcess() &&
+ if (!frame_tree_node_->IsMainFrame() &&
+ !new_instance_impl->IsDefaultSiteInstance() &&
+ !new_instance_impl->HasProcess() &&
new_instance_impl->RequiresDedicatedProcess()) {
// Also give the embedder a chance to override this decision. Certain
// frames have different enough workloads so that it's better to avoid
@@ -1703,6 +1728,7 @@ bool RenderFrameHostManager::IsCurrentlySameSite(RenderFrameHostImpl* candidate,
// |dest_url| should end up in |candidate|'s SiteInstance.
// This is used to keep same-site scripting working for hosted apps.
bool should_compare_effective_urls =
+ candidate->GetSiteInstance()->IsDefaultSiteInstance() ||
GetContentClient()
->browser()
->ShouldCompareEffectiveURLsForSiteInstanceSelection(
@@ -1710,8 +1736,10 @@ bool RenderFrameHostManager::IsCurrentlySameSite(RenderFrameHostImpl* candidate,
frame_tree_node_->IsMainFrame(),
candidate->GetSiteInstance()->original_url(), dest_url);
- bool src_has_effective_url = SiteInstanceImpl::HasEffectiveURL(
- browser_context, candidate->GetSiteInstance()->original_url());
+ bool src_has_effective_url =
+ !candidate->GetSiteInstance()->IsDefaultSiteInstance() &&
+ SiteInstanceImpl::HasEffectiveURL(
+ browser_context, candidate->GetSiteInstance()->original_url());
bool dest_has_effective_url =
SiteInstanceImpl::HasEffectiveURL(browser_context, dest_url);
@@ -1738,10 +1766,8 @@ bool RenderFrameHostManager::IsCurrentlySameSite(RenderFrameHostImpl* candidate,
// original_url() and not the site URL, so that we can do this comparison
// without the effective URL resolution if needed.
if (candidate->last_successful_url().is_empty()) {
- return SiteInstanceImpl::IsSameWebSite(
- candidate->GetSiteInstance()->GetIsolationContext(),
- candidate->GetSiteInstance()->original_url(), dest_url,
- should_compare_effective_urls);
+ return candidate->GetSiteInstance()->IsOriginalUrlSameSite(
+ dest_url, should_compare_effective_urls);
}
// In the common case, we use the RenderFrameHost's last successful URL. Thus,
@@ -1773,10 +1799,8 @@ bool RenderFrameHostManager::IsCurrentlySameSite(RenderFrameHostImpl* candidate,
// against the site URL.
if (candidate->last_successful_url().IsAboutBlank() &&
candidate->GetLastCommittedOrigin().opaque() &&
- SiteInstanceImpl::IsSameWebSite(
- candidate->GetSiteInstance()->GetIsolationContext(),
- candidate->GetSiteInstance()->original_url(), dest_url,
- should_compare_effective_urls)) {
+ candidate->GetSiteInstance()->IsOriginalUrlSameSite(
+ dest_url, should_compare_effective_urls)) {
return true;
}
@@ -1962,16 +1986,16 @@ std::unique_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
return new_render_frame_host;
}
-int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
+void RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
// A RenderFrameProxyHost should never be created in the same SiteInstance as
// the current RFH.
CHECK(instance);
CHECK_NE(instance, render_frame_host_->GetSiteInstance());
- // Return an already existing RenderFrameProxyHost if one exists and is alive.
+ // If a proxy already exists and is alive, nothing needs to be done.
RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
if (proxy && proxy->is_render_frame_proxy_live())
- return proxy->GetRoutingID();
+ return;
// At this point we know that we either have to 1) create a new
// RenderFrameProxyHost or 2) revive an existing, but no longer alive
@@ -1997,13 +2021,11 @@ int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
} else {
proxy->InitRenderFrameProxy();
}
-
- return proxy->GetRoutingID();
}
void RenderFrameHostManager::CreateProxiesForChildFrame(FrameTreeNode* child) {
RenderFrameProxyHost* outer_delegate_proxy =
- ForInnerDelegate() ? GetProxyToOuterDelegate() : nullptr;
+ IsMainFrameForInnerDelegate() ? GetProxyToOuterDelegate() : nullptr;
for (const auto& pair : proxy_hosts_) {
// Do not create proxies for subframes in the outer delegate's process,
// since the outer delegate does not need to interact with them.
@@ -2064,7 +2086,7 @@ void RenderFrameHostManager::SwapOuterDelegateFrame(
void RenderFrameHostManager::SetRWHViewForInnerContents(
RenderWidgetHostView* child_rwhv) {
- DCHECK(ForInnerDelegate() && frame_tree_node_->IsMainFrame());
+ DCHECK(IsMainFrameForInnerDelegate());
GetProxyToOuterDelegate()->SetChildRWHView(child_rwhv, nullptr);
}
@@ -2730,7 +2752,7 @@ void RenderFrameHostManager::SendPageMessage(IPC::Message* msg,
// When sending a PageMessage for an inner WebContents, we don't want to also
// send it to the outer WebContent's frame as well.
RenderFrameProxyHost* outer_delegate_proxy =
- ForInnerDelegate() ? GetProxyToOuterDelegate() : nullptr;
+ IsMainFrameForInnerDelegate() ? GetProxyToOuterDelegate() : nullptr;
for (const auto& pair : proxy_hosts_) {
if (outer_delegate_proxy != pair.second.get()) {
send_msg(pair.second.get(), pair.second->GetRoutingID(), msg,
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 4b1a001158d..e98ed5efe7c 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.h
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.h
@@ -203,32 +203,28 @@ class CONTENT_EXPORT RenderFrameHostManager
// there is no current one.
RenderWidgetHostView* GetRenderWidgetHostView() const;
- // Returns whether this manager belongs to a FrameTreeNode that belongs to an
- // inner WebContents.
- bool ForInnerDelegate();
-
- // Returns the RenderWidgetHost of the outer WebContents (if any) that can be
- // used to fetch the last keyboard event.
- // TODO(lazyboy): This can be removed once input events are sent directly to
- // remote frames.
- RenderWidgetHostImpl* GetOuterRenderWidgetHostForKeyboardInput();
-
- // Return the FrameTreeNode for the frame in the outer WebContents (if any)
- // that contains the inner WebContents.
+ // Returns whether this manager is a main frame and belongs to a FrameTreeNode
+ // that belongs to an inner WebContents.
+ bool IsMainFrameForInnerDelegate();
+
+ // If this is a RenderFrameHostManager for a main frame, this method returns
+ // the FrameTreeNode for the frame in the outer WebContents (if any) that
+ // contains the inner WebContents.
FrameTreeNode* GetOuterDelegateNode();
// Return a proxy for this frame in the parent frame's SiteInstance. Returns
// nullptr if this is a main frame or if such a proxy does not exist (for
- // example, if this frame is same-site with its parent).
+ // example, if this frame is same-site with its parent OR if this frame will
+ // be deleted soon and we are just waiting for the frame's unload handler).
RenderFrameProxyHost* GetProxyToParent();
- // Returns the proxy to inner WebContents in the outer WebContents's
- // SiteInstance. Returns nullptr if this WebContents isn't part of inner/outer
- // relationship.
+ // If this is a RenderFrameHostManager for a main frame, returns the proxy to
+ // inner WebContents in the outer WebContents's SiteInstance. Returns nullptr
+ // if this WebContents isn't part of inner/outer relationship.
RenderFrameProxyHost* GetProxyToOuterDelegate();
- // Removes the FrameTreeNode in the outer WebContents that represents this
- // FrameTreeNode.
+ // If this is a RenderFrameHostManager for a main frame, removes the
+ // FrameTreeNode in the outer WebContents that represents this FrameTreeNode.
// TODO(lazyboy): This does not belong to RenderFrameHostManager, move it to
// somehwere else.
void RemoveOuterDelegateFrame();
@@ -296,9 +292,8 @@ class CONTENT_EXPORT RenderFrameHostManager
std::unique_ptr<RenderFrameHostImpl> CreateRenderFrame(SiteInstance* instance,
bool hidden);
- // Helper method to create and initialize a RenderFrameProxyHost and return
- // its routing id.
- int CreateRenderFrameProxy(SiteInstance* instance);
+ // Helper method to create and initialize a RenderFrameProxyHost.
+ void CreateRenderFrameProxy(SiteInstance* instance);
// Creates proxies for a new child frame at FrameTreeNode |child| in all
// SiteInstances for which the current frame has proxies. This method is
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 251b1008aa7..e7361751461 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
@@ -22,6 +22,7 @@
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/values.h"
@@ -46,6 +47,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "content/public/common/bindings_policy.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/page_state.h"
#include "content/public/common/url_constants.h"
@@ -62,6 +64,7 @@
#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/did_commit_navigation_interceptor.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"
@@ -5692,7 +5695,8 @@ IN_PROC_BROWSER_TEST_F(
EXPECT_EQ(speculative_rph, web_contents->GetMainFrame()->GetProcess());
}
-// ContentBrowserClient that skips assigning a site URL for a given URL.
+// ContentBrowserClient that skips assigning a site URL for all URLs that match
+// a given URL's scheme and host.
class DontAssignSiteContentBrowserClient : public TestContentBrowserClient {
public:
// Any visit to |url_to_skip| will not cause the site to be assigned to the
@@ -5701,7 +5705,8 @@ class DontAssignSiteContentBrowserClient : public TestContentBrowserClient {
: url_to_skip_(url_to_skip) {}
bool ShouldAssignSiteForURL(const GURL& url) override {
- return url != url_to_skip_;
+ return url.host() != url_to_skip_.host() ||
+ url.scheme() != url_to_skip_.scheme();
}
private:
@@ -5758,11 +5763,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_FALSE(instance1->HasWrongProcessForURL(url1));
}
- // TODO(creis): Enable the rest of the test when https://crbug.com/793127 is
- // fixed, since this currently fails with a DCHECK in SiteProcessCountTracker.
-#if 0
- // Go back to the chrome-native:// URL's entry, which should swap to a new
- // SiteInstance with an unused site URL.
+ // Go back to url1's entry, which should swap to a new SiteInstance with an
+ // unused site URL.
TestNavigationObserver observer(web_contents);
web_contents->GetController().GoToOffset(-2);
observer.Wait();
@@ -5785,7 +5787,296 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
policy->CanAccessDataForOrigin(new_process->GetID(), url1));
EXPECT_TRUE(
policy->CanAccessDataForOrigin(new_process->GetID(), url2));
-#endif
+
+ SetBrowserClientForTesting(old_client);
+}
+
+namespace {
+
+// A helper class to run a predefined callback just before processing the
+// DidCommitProvisionalLoad IPC for |deferred_url|.
+class CommitMessageDelayer : public DidCommitNavigationInterceptor {
+ public:
+ using DidCommitCallback = base::OnceCallback<void(RenderFrameHost*)>;
+
+ explicit CommitMessageDelayer(WebContents* web_contents,
+ const GURL& deferred_url,
+ DidCommitCallback deferred_action)
+ : DidCommitNavigationInterceptor(web_contents),
+ deferred_url_(deferred_url),
+ deferred_action_(std::move(deferred_action)) {}
+
+ void Wait() {
+ run_loop_.reset(new base::RunLoop());
+ run_loop_->Run();
+ run_loop_.reset();
+ }
+
+ private:
+ // DidCommitNavigationInterceptor:
+ bool WillProcessDidCommitNavigation(
+ RenderFrameHost* render_frame_host,
+ NavigationRequest* navigation_request,
+ ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
+ mojom::DidCommitProvisionalLoadInterfaceParamsPtr* interface_params)
+ override {
+ if (params->url == deferred_url_) {
+ std::move(deferred_action_).Run(render_frame_host);
+ if (run_loop_)
+ run_loop_->Quit();
+ }
+ return true;
+ }
+
+ std::unique_ptr<base::RunLoop> run_loop_;
+
+ const GURL deferred_url_;
+ DidCommitCallback deferred_action_;
+
+ DISALLOW_COPY_AND_ASSIGN(CommitMessageDelayer);
+};
+
+} // namespace
+
+// Check that when a navigation to a URL that doesn't require assigning a site
+// URL is in progress, another navigation can't reuse the same process in the
+// meantime. Such reuse previously led to a renderer kill when the siteless
+// URL later committed; a real-world example of the siteless URL was
+// chrome-native://newtab. See https://crbug.com/970046.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ NavigationRacesWithCommitInUnassignedSiteInstance) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // Set up a URL for which ShouldAssignSiteForURL will return false. The
+ // corresponding SiteInstance's site will be left unassigned, and its process
+ // won't be locked. The test will navigate to this URL first.
+ GURL siteless_url(
+ embedded_test_server()->GetURL("siteless.com", "/title1.html"));
+ DontAssignSiteContentBrowserClient content_browser_client(siteless_url);
+ ContentBrowserClient* old_client =
+ SetBrowserClientForTesting(&content_browser_client);
+
+ // Prepare for a second navigation to a normal URL. Ensure it's isolated so
+ // that it requires a process lock on all platforms.
+ GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ policy->AddIsolatedOrigins({url::Origin::Create(foo_url)});
+
+ // Create a new shell where the foo.com origin isolation will take effect.
+ Shell* shell = CreateBrowser();
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell->web_contents());
+ FrameTreeNode* root = web_contents->GetFrameTree()->root();
+ RenderProcessHost* foo_process = nullptr;
+ TestNavigationManager foo_manager(web_contents, foo_url);
+ EXPECT_TRUE(SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
+ root->current_frame_host()->GetSiteInstance()->GetIsolationContext(),
+ GURL("http://foo.com")));
+
+ // Set up the work to be done after the renderer is asked to commit
+ // |siteless_url|, but before the corresponding DidCommitProvisionalLoad IPC
+ // is processed. This will start a navigation to |foo_url| and wait for its
+ // response.
+ auto did_commit_callback =
+ base::BindLambdaForTesting([&](RenderFrameHost* rfh) {
+ // The navigation should stay in the initial empty SiteInstance, with
+ // the site still unassigned.
+ EXPECT_FALSE(
+ static_cast<SiteInstanceImpl*>(rfh->GetSiteInstance())->HasSite());
+ EXPECT_FALSE(root->render_manager()->speculative_frame_host());
+
+ shell->LoadURL(foo_url);
+
+ // The foo.com navigation should swap to a new process, since it is not
+ // safe to reuse |siteless_url|'s process before |siteless_url|
+ // commits.
+ EXPECT_TRUE(root->render_manager()->speculative_frame_host());
+ foo_process =
+ root->render_manager()->speculative_frame_host()->GetProcess();
+
+ // Wait for response. This will cause |foo_manager| to spin up a
+ // nested message loop while we're blocked in the current message loop
+ // (within DidCommitNavigationInterceptor). Thus, it's important to
+ // allow nestable tasks in |foo_manager|'s message loop, so that it can
+ // process the response before we unblock the
+ // DidCommitNavigationInterceptor's message loop and finish processing
+ // the commit.
+ foo_manager.AllowNestableTasks();
+ EXPECT_TRUE(foo_manager.WaitForResponse());
+
+ foo_manager.ResumeNavigation();
+ // After returning here, the commit for |siteless_url| will be
+ // processed.
+ });
+
+ CommitMessageDelayer commit_delayer(web_contents,
+ siteless_url /* deferred_url */,
+ std::move(did_commit_callback));
+
+ // Start the first navigation, which does not assign a site URL.
+ base::HistogramTester histograms;
+ shell->LoadURL(siteless_url);
+
+ // The navigation should stay in the initial empty SiteInstance, so there
+ // shouldn't be a speculative RFH at this point.
+ EXPECT_FALSE(root->render_manager()->speculative_frame_host());
+
+ // Wait for the DidCommit IPC for |siteless_url|, and before processing it,
+ // trigger a navigation to |foo_url| and wait for its response.
+ commit_delayer.Wait();
+
+ // Check that the renderer hasn't been killed. At this point, it should've
+ // successfully committed the navigation to |siteless_url|, and it shouldn't
+ // be locked.
+ EXPECT_TRUE(web_contents->GetMainFrame()->IsRenderFrameLive());
+ EXPECT_EQ(siteless_url, web_contents->GetMainFrame()->GetLastCommittedURL());
+ RenderProcessHost* process1 = web_contents->GetMainFrame()->GetProcess();
+ EXPECT_FALSE(web_contents->GetMainFrame()->GetSiteInstance()->HasSite());
+ EXPECT_EQ(GURL(), policy->GetOriginLock(process1->GetID()));
+
+ // Now wait for second navigation to finish and ensure it also succeeds.
+ foo_manager.WaitForNavigationFinished();
+ EXPECT_TRUE(foo_manager.was_successful());
+ EXPECT_TRUE(web_contents->GetMainFrame()->IsRenderFrameLive());
+ EXPECT_EQ(foo_url, web_contents->GetMainFrame()->GetLastCommittedURL());
+
+ // The foo.com navigation should've used a different process, locked to
+ // foo.com.
+ RenderProcessHost* process2 = web_contents->GetMainFrame()->GetProcess();
+ EXPECT_NE(process1, process2);
+ EXPECT_EQ(GURL("http://foo.com"),
+ web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ EXPECT_EQ(GURL("http://foo.com"), policy->GetOriginLock(process2->GetID()));
+
+ // Ensure also that the foo.com process didn't change midway through the
+ // navigation.
+ EXPECT_EQ(foo_process, process2);
+
+ // Ensure we've logged the UMA for disallowing problematic process reuse.
+ // Since IsSuitableHost() is checked multiple times during a particular
+ // navigation, just make sure that this is logged at least once.
+ EXPECT_GE(histograms.GetBucketCount(
+ "SiteIsolation.PendingSitelessNavigationDisallowsProcessReuse",
+ 1 /* has_disqualifying_pending_navigation */),
+ 1);
+
+ SetBrowserClientForTesting(old_client);
+}
+
+// Tests specific to the "default process" mode (which creates strict
+// SiteInstances that can share a default process per BrowsingInstance).
+class RenderFrameHostManagerDefaultProcessTest
+ : public RenderFrameHostManagerTest {
+ public:
+ RenderFrameHostManagerDefaultProcessTest() {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kProcessSharingWithStrictSiteInstances);
+ }
+ ~RenderFrameHostManagerDefaultProcessTest() override {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ RenderFrameHostManagerTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitch(switches::kDisableSiteIsolation);
+
+ if (AreAllSitesIsolatedForTesting()) {
+ LOG(WARNING) << "This test should be run without strict site isolation. "
+ << "It does nothing when --site-per-process is specified.";
+ }
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameHostManagerDefaultProcessTest);
+};
+
+// Ensure that the default process can be used for URLs that don't assign a site
+// to the SiteInstance, when Site Isolation is not enabled.
+// 1. Visit foo.com.
+// 2. Start to navigate to a siteless URL.
+// 3. When the commit is pending, start a navigation to bar.com in a popup.
+// (Using a popup avoids a crash when replacting the speculative RFH, per
+// https://crbug.com/838348.)
+// All navigations should use the default process, and we should not crash.
+// See https://crbug.com/977956.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerDefaultProcessTest,
+ NavigationRacesWithSitelessCommitInDefaultProcess) {
+ // This test is designed to run without strict site isolation.
+ if (AreAllSitesIsolatedForTesting())
+ return;
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+ GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title1.html"));
+
+ // Step 1: Visit foo.com in the default process.
+ EXPECT_TRUE(NavigateToURL(shell(), foo_url));
+ RenderProcessHost* original_process =
+ web_contents->GetMainFrame()->GetProcess();
+ EXPECT_EQ(original_process, web_contents->GetMainFrame()
+ ->GetSiteInstance()
+ ->GetDefaultProcessIfUsable());
+
+ // Set up a URL for which ShouldAssignSiteForURL will return false. The
+ // corresponding SiteInstance's site will be left unassigned, and its process
+ // won't be locked.
+ GURL siteless_url(
+ embedded_test_server()->GetURL("siteless.com", "/title1.html"));
+ DontAssignSiteContentBrowserClient content_browser_client(siteless_url);
+ ContentBrowserClient* old_client =
+ SetBrowserClientForTesting(&content_browser_client);
+
+ // Set up the work to be done after the renderer is asked to commit
+ // |siteless_url|, but before the corresponding DidCommitProvisionalLoad IPC
+ // is processed. This will start a navigation to |bar_url| in a popup and
+ // wait for its response. We use a popup to avoid trampling the speculative
+ // RFH while it is committing (per https://crbug.com/838348).
+ auto did_commit_callback =
+ base::BindLambdaForTesting([&](RenderFrameHost* rfh) {
+ Shell* new_shell = OpenPopup(shell(), GURL(url::kAboutBlankURL), "foo");
+ EXPECT_TRUE(new_shell);
+
+ // Step 3: Navigate to bar.com in the same BrowsingInstance, while the
+ // commit to siteless_url is pending. This used to crash because it
+ // picked the default process, but IsSuitableHost said it was not ok due
+ // to the pending siteless URL commit (in https://crbug.com/977956).
+ TestNavigationManager bar_manager(new_shell->web_contents(), bar_url);
+ EXPECT_TRUE(ExecuteScript(new_shell,
+ base::StringPrintf("location.href = '%s'",
+ bar_url.spec().c_str())));
+
+ // Wait for response. This will cause |bar_manager| to spin up a
+ // nested message loop while we're blocked in the current message loop
+ // (within DidCommitNavigationInterceptor). Thus, it's important to
+ // allow nestable tasks in |bar_manager|'s message loop, so that it can
+ // process the response before we unblock the
+ // DidCommitNavigationInterceptor's message loop and finish processing
+ // the commit.
+ bar_manager.AllowNestableTasks();
+ EXPECT_TRUE(bar_manager.WaitForResponse());
+
+ bar_manager.ResumeNavigation();
+
+ // After returning here, the commit for |siteless_url| will be
+ // processed.
+ });
+
+ // Step 2: Visit siteless_url in the same BrowsingInstance, but wait before
+ // the commit IPC is processed. (See did_commit_callback above for step 3.)
+ CommitMessageDelayer commit_delayer(web_contents,
+ siteless_url /* deferred_url */,
+ std::move(did_commit_callback));
+ EXPECT_TRUE(ExecuteScript(
+ shell(),
+ base::StringPrintf("location.href = '%s'", siteless_url.spec().c_str())));
+
+ // Wait for the DidCommit IPC for |siteless_url|, and before processing it,
+ // trigger a navigation to |foo_url| and wait for its response.
+ commit_delayer.Wait();
+
+ EXPECT_EQ(original_process, web_contents->GetMainFrame()->GetProcess());
SetBrowserClientForTesting(old_client);
}
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 0f9839bd658..230cfb7650d 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -347,7 +347,7 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
// Creates a test RenderViewHost that's swapped out.
void CreateSwappedOutRenderViewHost() {
- const GURL kChromeURL("chrome://foo");
+ const GURL kChromeURL(GetWebUIURL("foo"));
const GURL kDestUrl("http://www.google.com/");
// Navigate our first tab to a chrome url and then to the destination.
@@ -408,7 +408,7 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
CommitNavigationParams commit_params =
entry->ConstructCommitNavigationParams(
*frame_entry, common_params.url, frame_entry->committed_origin(),
- common_params.method, false,
+ common_params.method,
entry->GetSubframeUniqueNames(frame_tree_node),
controller->GetPendingEntryIndex() ==
-1 /* intended_as_new_entry */,
@@ -461,7 +461,7 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
// a regression test for bug 9364.
TEST_F(RenderFrameHostManagerTest, NewTabPageProcesses) {
set_should_create_webui(true);
- const GURL kChromeUrl("chrome://foo");
+ const GURL kChromeUrl(GetWebUIURL("foo"));
const GURL kDestUrl("http://www.google.com/");
// Navigate our first tab to the chrome url and then to the destination,
@@ -523,7 +523,7 @@ TEST_F(RenderFrameHostManagerTest, NewTabPageProcesses) {
// for synchronous messages, which cannot be ignored without leaving the
// renderer in a stuck state. See http://crbug.com/93427.
TEST_F(RenderFrameHostManagerTest, FilterMessagesWhileSwappedOut) {
- const GURL kChromeURL("chrome://foo");
+ const GURL kChromeURL(GetWebUIURL("foo"));
const GURL kDestUrl("http://www.google.com/");
std::vector<FaviconURL> icons;
@@ -575,7 +575,7 @@ TEST_F(RenderFrameHostManagerTest, FilterMessagesWhileSwappedOut) {
// that it only gets FrameHostMsg_UpdateFaviconURL messages for the most
// recently committed navigation for each WebContentsImpl.
TEST_F(RenderFrameHostManagerTest, UpdateFaviconURLWhilePendingSwapOut) {
- const GURL kChromeURL("chrome://foo");
+ const GURL kChromeURL(GetWebUIURL("foo"));
const GURL kDestUrl("http://www.google.com/");
std::vector<FaviconURL> icons;
@@ -738,7 +738,7 @@ class RenderViewHostDestroyer : public WebContentsObserver {
// http://crbug.com/259859.
TEST_F(RenderFrameHostManagerTest,
DetectUseAfterFreeInShutdownRenderViewHostsInSiteInstance) {
- const GURL kChromeURL("chrome://newtab");
+ const GURL kChromeURL(GetWebUIURL("newtab"));
const GURL kUrl1("http://www.google.com");
const GURL kUrl2("http://www.chromium.org");
@@ -770,7 +770,7 @@ TEST_F(RenderFrameHostManagerTest,
// EnableViewSourceMode message is sent on every navigation regardless
// RenderView is being newly created or reused.
TEST_F(RenderFrameHostManagerTest, AlwaysSendEnableViewSourceMode) {
- const GURL kChromeUrl("chrome://foo/");
+ const GURL kChromeUrl(GetWebUIURL("foo"));
const GURL kUrl("http://foo/");
const GURL kViewSourceUrl("view-source:http://foo/");
@@ -964,7 +964,7 @@ TEST_F(RenderFrameHostManagerTest, WebContentVisibilityHiddenBeforeCommit) {
EXPECT_TRUE(manager->current_frame_host()->IsRenderFrameLive());
// Start navigation.
- const GURL kUrl("chrome://foo");
+ const GURL kUrl(GetWebUIURL("foo"));
NavigationEntryImpl entry(
nullptr /* instance */, kUrl, Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
@@ -998,7 +998,7 @@ TEST_F(RenderFrameHostManagerTest, WebUI) {
EXPECT_FALSE(manager->current_frame_host()->web_ui());
EXPECT_TRUE(initial_rfh);
- const GURL kUrl("chrome://foo");
+ const GURL kUrl(GetWebUIURL("foo"));
NavigationEntryImpl entry(
nullptr /* instance */, kUrl, Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
@@ -1054,7 +1054,7 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
EXPECT_TRUE(manager1->current_frame_host()->IsRenderFrameLive());
// Navigate to a WebUI page.
- const GURL kUrl1("chrome://foo");
+ const GURL kUrl1(GetWebUIURL("foo"));
NavigationEntryImpl entry1(
nullptr /* instance */, kUrl1, Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
@@ -1086,7 +1086,7 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
FrameReplicationState(), false);
EXPECT_TRUE(manager2->current_host()->IsRenderViewLive());
- const GURL kUrl2("chrome://foo/bar");
+ const GURL kUrl2(GetWebUIURL("foo/bar"));
NavigationEntryImpl entry2(
nullptr /* instance */, kUrl2, Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_LINK, true /* is_renderer_init */,
@@ -1109,14 +1109,14 @@ TEST_F(RenderFrameHostManagerTest, WebUIWasReused) {
set_should_create_webui(true);
// Navigate to a WebUI page.
- const GURL kUrl1("chrome://foo");
+ const GURL kUrl1(GetWebUIURL("foo"));
contents()->NavigateAndCommit(kUrl1);
WebUIImpl* web_ui = main_test_rfh()->web_ui();
EXPECT_TRUE(web_ui);
// Navigate to another WebUI page which should be same-site and keep the
// current WebUI.
- const GURL kUrl2("chrome://foo/bar");
+ const GURL kUrl2(GetWebUIURL("foo/bar"));
contents()->NavigateAndCommit(kUrl2);
EXPECT_EQ(web_ui, main_test_rfh()->web_ui());
}
@@ -1127,7 +1127,7 @@ TEST_F(RenderFrameHostManagerTest, WebUIWasCleared) {
set_should_create_webui(true);
// Navigate to a WebUI page.
- const GURL kUrl1("chrome://foo");
+ const GURL kUrl1(GetWebUIURL("foo"));
contents()->NavigateAndCommit(kUrl1);
EXPECT_TRUE(main_test_rfh()->web_ui());
@@ -1180,7 +1180,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateAfterMissingSwapOutACK) {
TEST_F(RenderFrameHostManagerTest, CreateSwappedOutOpenerRFHs) {
const GURL kUrl1("http://www.google.com/");
const GURL kUrl2("http://www.chromium.org/");
- const GURL kChromeUrl("chrome://foo");
+ const GURL kChromeUrl(GetWebUIURL("foo"));
// Navigate to an initial URL.
contents()->NavigateAndCommit(kUrl1);
@@ -1447,8 +1447,8 @@ TEST_F(RenderFrameHostManagerTest, CleanUpSwappedOutRVHOnProcessCrash) {
// is in the same process (http://crbug.com/79918).
TEST_F(RenderFrameHostManagerTest, EnableWebUIWithSwappedOutOpener) {
set_should_create_webui(true);
- const GURL kSettingsUrl("chrome://chrome/settings");
- const GURL kPluginUrl("chrome://plugins");
+ const GURL kSettingsUrl(GetWebUIURL("chrome/settings"));
+ const GURL kPluginUrl(GetWebUIURL("plugins"));
// Navigate to an initial WebUI URL.
contents()->NavigateAndCommit(kSettingsUrl);
@@ -2069,7 +2069,7 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
// Start a pending WebUI navigation in the main frame and verify that the
// pending RVH has bindings.
- const GURL kWebUIUrl("chrome://foo");
+ const GURL kWebUIUrl(GetWebUIURL("foo"));
NavigationEntryImpl webui_entry(
nullptr /* instance */, kWebUIUrl, Referrer(),
base::string16() /* title */, ui::PAGE_TRANSITION_TYPED,
@@ -2494,7 +2494,7 @@ TEST_F(RenderFrameHostManagerTest,
TEST_F(RenderFrameHostManagerTest, RestoreNavigationToWebUI) {
set_should_create_webui(true);
- const GURL kInitUrl("chrome://foo/");
+ const GURL kInitUrl(GetWebUIURL("foo"));
scoped_refptr<SiteInstanceImpl> initial_instance =
SiteInstanceImpl::Create(browser_context());
initial_instance->SetSite(kInitUrl);
@@ -2553,7 +2553,7 @@ TEST_F(RenderFrameHostManagerTest, RestoreNavigationToWebUI) {
TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithOneWebUI1) {
set_should_create_webui(true);
NavigationSimulator::NavigateAndCommitFromBrowser(contents(),
- GURL("chrome://foo/"));
+ GetWebUIURL("foo/"));
RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting();
RenderFrameHostImpl* host1 = manager->current_frame_host();
@@ -2615,7 +2615,7 @@ TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithOneWebUI1) {
TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithOneWebUI2) {
set_should_create_webui(true);
NavigationSimulator::NavigateAndCommitFromBrowser(contents(),
- GURL("chrome://foo/"));
+ GetWebUIURL("foo/"));
RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting();
RenderFrameHostImpl* host1 = manager->current_frame_host();
@@ -2674,7 +2674,7 @@ TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithTwoWebUIs1) {
set_should_create_webui(true);
set_webui_type(1);
NavigationSimulator::NavigateAndCommitFromBrowser(contents(),
- GURL("chrome://foo/"));
+ GetWebUIURL("foo"));
RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting();
RenderFrameHostImpl* host1 = manager->current_frame_host();
@@ -2695,7 +2695,7 @@ TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithTwoWebUIs1) {
// Navigation another WebUI page, with a different type.
set_webui_type(2);
- const GURL kUrl("chrome://bar/");
+ const GURL kUrl(GetWebUIURL("bar"));
auto navigation =
NavigationSimulator::CreateBrowserInitiated(kUrl, contents());
navigation->ReadyToCommit();
@@ -2740,7 +2740,7 @@ TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithTwoWebUIs2) {
set_should_create_webui(true);
set_webui_type(1);
NavigationSimulator::NavigateAndCommitFromBrowser(contents(),
- GURL("chrome://foo/"));
+ GetWebUIURL("foo/"));
RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting();
RenderFrameHostImpl* host1 = manager->current_frame_host();
@@ -2761,7 +2761,7 @@ TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithTwoWebUIs2) {
// Navigation another WebUI page, with a different type.
set_webui_type(2);
- const GURL kUrl("chrome://bar/");
+ const GURL kUrl(GetWebUIURL("bar/"));
auto navigation =
NavigationSimulator::CreateBrowserInitiated(kUrl, contents());
navigation->ReadyToCommit();
@@ -2799,19 +2799,6 @@ TEST_F(RenderFrameHostManagerTest, CanCommitOrigin) {
NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl);
- controller().LoadURL(
- kUrlBar, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- main_test_rfh()->PrepareForCommit();
-
- FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.nav_entry_id = 0;
- params.did_create_new_entry = false;
- params.transition = ui::PAGE_TRANSITION_LINK;
- params.should_update_history = false;
- params.gesture = NavigationGestureAuto;
- params.method = "GET";
- params.page_state = PageState::CreateFromURL(kUrlBar);
-
struct TestCase {
const char* const url;
const char* const origin;
@@ -2836,15 +2823,20 @@ TEST_F(RenderFrameHostManagerTest, CanCommitOrigin) {
};
for (const auto& test_case : cases) {
- params.url = GURL(test_case.url);
- params.origin = url::Origin::Create(GURL(test_case.origin));
+ auto navigation = NavigationSimulatorImpl::CreateBrowserInitiated(
+ GURL(test_case.url), contents());
+ navigation->set_origin(url::Origin::Create(GURL(test_case.origin)));
+ navigation->ReadyToCommit();
- int expected_bad_msg_count = process()->bad_msg_count();
+ int expected_bad_msg_count =
+ static_cast<MockRenderProcessHost*>(navigation->GetNavigationHandle()
+ ->GetRenderFrameHost()
+ ->GetProcess())
+ ->bad_msg_count();
if (test_case.mismatch)
expected_bad_msg_count++;
- main_test_rfh()->SendNavigateWithParams(
- &params, false /* was_within_same_document */);
+ navigation->Commit();
EXPECT_EQ(expected_bad_msg_count, process()->bad_msg_count())
<< " url:" << test_case.url
@@ -2864,7 +2856,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateFromDeadRendererToWebUI) {
EXPECT_FALSE(initial_host->IsRenderFrameLive());
// Navigation request.
- const GURL kUrl("chrome://foo");
+ const GURL kUrl(GetWebUIURL("foo"));
NavigationEntryImpl entry(
nullptr /* instance */, kUrl, Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
@@ -2878,8 +2870,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateFromDeadRendererToWebUI) {
base::TimeTicks::Now(), base::TimeTicks::Now());
CommitNavigationParams commit_params = entry.ConstructCommitNavigationParams(
*frame_entry, common_params.url, frame_entry->committed_origin(),
- common_params.method, false,
- entry.GetSubframeUniqueNames(frame_tree_node),
+ common_params.method, entry.GetSubframeUniqueNames(frame_tree_node),
controller().GetPendingEntryIndex() == -1 /* intended_as_new_entry */,
static_cast<NavigationControllerImpl&>(controller())
.GetIndexOfEntry(&entry),
@@ -2930,7 +2921,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateFromDeadRendererToWebUI) {
TEST_F(RenderFrameHostManagerTest, NavigateSameSiteBetweenWebUIs) {
set_should_create_webui(true);
NavigationSimulator::NavigateAndCommitFromBrowser(contents(),
- GURL("chrome://foo"));
+ GetWebUIURL("foo"));
RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting();
RenderFrameHostImpl* host = manager->current_frame_host();
@@ -2939,7 +2930,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateSameSiteBetweenWebUIs) {
EXPECT_TRUE(web_ui);
// Navigation request. No change in the returned WebUI type.
- const GURL kUrl("chrome://foo/bar");
+ const GURL kUrl(GetWebUIURL("foo/bar"));
auto web_ui_navigation =
NavigationSimulator::CreateBrowserInitiated(kUrl, contents());
web_ui_navigation->Start();
@@ -2974,7 +2965,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateCrossSiteBetweenWebUIs) {
set_should_create_webui(true);
set_webui_type(1);
NavigationSimulator::NavigateAndCommitFromBrowser(contents(),
- GURL("chrome://foo"));
+ GetWebUIURL("foo"));
RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting();
RenderFrameHostImpl* host = manager->current_frame_host();
@@ -2987,7 +2978,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateCrossSiteBetweenWebUIs) {
set_webui_type(2);
// Navigation request.
- const GURL kUrl("chrome://bar");
+ const GURL kUrl(GetWebUIURL("bar"));
auto web_ui_navigation =
NavigationSimulator::CreateBrowserInitiated(kUrl, contents());
web_ui_navigation->Start();
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 5cadc6afb65..cf137f07cb6 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.cc
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.cc
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/alias.h"
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/strings/string_util.h"
#include "base/syslog_logging.h"
@@ -38,6 +39,7 @@
#include "content/public/browser/download_manager.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_constants.h"
+#include "content/public/common/content_features.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "mojo/public/cpp/system/message_pipe.h"
@@ -54,6 +56,7 @@
#include "storage/browser/blob/blob_storage_context.h"
#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -196,6 +199,74 @@ class RenderMessageCompletionCallback {
IPC::Message* reply_msg_;
};
+// Send deprecation messages to the console about cookies that would be excluded
+// due to either SameSiteByDefaultCookies or CookiesWithoutSameSiteMustBeSecure.
+// TODO(crbug.com/977040): Remove when no longer needed.
+void SendDeprecationMessagesForSameSiteCookiesOnUI(
+ int render_process_id,
+ int render_frame_id,
+ const GURL& url,
+ net::CookieStatusList deprecated_cookies) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RenderFrameHostImpl* render_frame_host =
+ RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
+ if (!render_frame_host)
+ return;
+
+ // Return early if the frame has already been navigated away from.
+ content::WebContents* web_contents =
+ content::WebContents::FromRenderFrameHost(render_frame_host);
+
+ // |web_contents| will be null on interstitial pages, which means
+ // the frame has been navigated away from and it's safe to return early
+ if (!web_contents)
+ return;
+
+ RenderFrameHostImpl* root_frame_host = render_frame_host;
+ while (root_frame_host->GetParent() != nullptr)
+ root_frame_host = root_frame_host->GetParent();
+ if (root_frame_host != web_contents->GetMainFrame())
+ return;
+
+ bool log_unspecified_treated_as_lax_metric = false;
+ bool log_none_insecure_metric = false;
+
+ bool emit_messages =
+ base::FeatureList::IsEnabled(features::kCookieDeprecationMessages);
+
+ for (const auto& cookie_with_status : deprecated_cookies) {
+ std::string cookie_url = net::cookie_util::CookieOriginToURL(
+ cookie_with_status.cookie.Domain(),
+ cookie_with_status.cookie.IsSecure())
+ .possibly_invalid_spec();
+ if (cookie_with_status.status ==
+ net::CanonicalCookie::CookieInclusionStatus::
+ EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX) {
+ log_unspecified_treated_as_lax_metric = true;
+ }
+ if (cookie_with_status.status ==
+ net::CanonicalCookie::CookieInclusionStatus::
+ EXCLUDE_SAMESITE_NONE_INSECURE) {
+ log_none_insecure_metric = true;
+ }
+
+ if (emit_messages) {
+ root_frame_host->AddSameSiteCookieDeprecationMessage(
+ cookie_url, cookie_with_status.status);
+ }
+ }
+
+ if (log_unspecified_treated_as_lax_metric) {
+ GetContentClient()->browser()->LogWebFeatureForCurrentPage(
+ render_frame_host, blink::mojom::WebFeature::kCookieNoSameSite);
+ }
+ if (log_none_insecure_metric) {
+ GetContentClient()->browser()->LogWebFeatureForCurrentPage(
+ render_frame_host,
+ blink::mojom::WebFeature::kCookieInsecureAndSameSiteNone);
+ }
+}
+
} // namespace
#if BUILDFLAG(ENABLE_PLUGINS)
@@ -328,8 +399,6 @@ bool RenderFrameMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(FrameHostMsg_SaveImageFromDataURL,
OnSaveImageFromDataURL)
IPC_MESSAGE_HANDLER(FrameHostMsg_Are3DAPIsBlocked, OnAre3DAPIsBlocked)
- IPC_MESSAGE_HANDLER_GENERIC(FrameHostMsg_RenderProcessGone,
- OnRenderProcessGone())
#if BUILDFLAG(ENABLE_PLUGINS)
IPC_MESSAGE_HANDLER(FrameHostMsg_GetPluginInfo, OnGetPluginInfo)
IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_OpenChannelToPepperPlugin,
@@ -511,6 +580,32 @@ void RenderFrameMessageFilter::CheckPolicyForCookies(
if (GetContentClient()->browser()->AllowGetCookie(
url, site_for_cookies, cookie_list, resource_context_,
render_process_id_, render_frame_id)) {
+ // Send deprecation messages to the console for cookies that are included,
+ // but would be excluded under SameSiteByDefaultCookies or
+ // CookiesWithoutSameSiteMustBeSecure.
+ net::CookieOptions options;
+ options.set_same_site_cookie_context(
+ net::cookie_util::ComputeSameSiteContextForScriptGet(
+ url, site_for_cookies, base::nullopt));
+ net::CookieStatusList deprecated_cookies;
+ for (const net::CanonicalCookie& cc : cookie_list) {
+ net::CanonicalCookie::CookieInclusionStatus
+ include_but_maybe_would_exclude_status =
+ net::cookie_util::CookieWouldBeExcludedDueToSameSite(cc, options);
+ if (include_but_maybe_would_exclude_status !=
+ net::CanonicalCookie::CookieInclusionStatus::INCLUDE) {
+ deprecated_cookies.push_back(
+ {cc, include_but_maybe_would_exclude_status});
+ }
+ }
+ if (!deprecated_cookies.empty()) {
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&SendDeprecationMessagesForSameSiteCookiesOnUI,
+ render_process_id_, render_frame_id, url,
+ std::move(deprecated_cookies)));
+ }
+
std::move(callback).Run(net::CanonicalCookie::BuildCookieLine(cookie_list));
} else {
std::move(callback).Run(std::string());
@@ -553,15 +648,6 @@ void RenderFrameMessageFilter::OnAre3DAPIsBlocked(int render_frame_id,
top_origin_url, render_process_id_, render_frame_id, requester);
}
-void RenderFrameMessageFilter::OnRenderProcessGone() {
- // FrameHostMessage_RenderProcessGone is a synthetic IPC message used by
- // RenderProcessHostImpl to clean things up after a crash (it's injected
- // downstream of this filter). Allowing it to proceed would enable a renderer
- // to fake its own death; instead, actually kill the renderer.
- bad_message::ReceivedBadMessage(
- this, bad_message::RFMF_RENDERER_FAKED_ITS_OWN_DEATH);
-}
-
void RenderFrameMessageFilter::SetCookie(int32_t render_frame_id,
const GURL& url,
const GURL& site_for_cookies,
@@ -585,9 +671,9 @@ void RenderFrameMessageFilter::SetCookie(int32_t render_frame_id,
}
net::CookieOptions options;
- // TODO(https://crbug.com/925311): Wire initiator in here properly.
- options.set_same_site_cookie_context(net::cookie_util::ComputeSameSiteContext(
- url, site_for_cookies, base::nullopt));
+ options.set_same_site_cookie_context(
+ net::cookie_util::ComputeSameSiteContextForScriptSet(url,
+ site_for_cookies));
std::unique_ptr<net::CanonicalCookie> cookie = net::CanonicalCookie::Create(
url, cookie_line, base::Time::Now(), options);
if (!cookie) {
@@ -602,6 +688,24 @@ void RenderFrameMessageFilter::SetCookie(int32_t render_frame_id,
return;
}
+ // Send deprecation messages to the console for cookies that are included,
+ // but would be excluded under SameSiteByDefaultCookies or
+ // CookiesWithoutSameSiteMustBeSecure.
+ net::CanonicalCookie::CookieInclusionStatus
+ include_but_maybe_would_exclude_status =
+ net::cookie_util::CookieWouldBeExcludedDueToSameSite(*cookie,
+ options);
+ if (include_but_maybe_would_exclude_status !=
+ net::CanonicalCookie::CookieInclusionStatus::INCLUDE) {
+ net::CookieStatusList deprecated_cookies = {
+ {*cookie, include_but_maybe_would_exclude_status}};
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&SendDeprecationMessagesForSameSiteCookiesOnUI,
+ render_process_id_, render_frame_id, url,
+ std::move(deprecated_cookies)));
+ }
+
// If the embedder overrides the cookie store then always use it, even if
// the network service is enabled, instead of the CookieManager associated
// this process' StoragePartition.
@@ -661,8 +765,9 @@ void RenderFrameMessageFilter::GetCookies(int render_frame_id,
net::CookieOptions options;
// TODO(https://crbug.com/925311): Wire initiator in here properly.
- options.set_same_site_cookie_context(net::cookie_util::ComputeSameSiteContext(
- url, site_for_cookies, base::nullopt));
+ options.set_same_site_cookie_context(
+ net::cookie_util::ComputeSameSiteContextForScriptGet(
+ url, site_for_cookies, base::nullopt));
// If the embedder overrides the cookie store then always use it, even if
// the network service is enabled, instead of the CookieManager associated
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 459bfe50cf6..e108cd2e071 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
@@ -285,30 +285,6 @@ IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest,
v.DepictFrameTree(tab->GetFrameTree()->root()));
}
-// FrameHostMsg_RenderProcessGone is a synthetic message that's really an
-// implementation detail of RenderProcessHostImpl's crash recovery. It should be
-// ignored if it arrives over the IPC channel.
-IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest, RenderProcessGone) {
- GURL web_url("http://foo.com/simple_page.html");
- NavigateToURL(shell(), web_url);
- RenderFrameHost* web_rfh = shell()->web_contents()->GetMainFrame();
-
- ASSERT_TRUE(web_rfh->IsRenderFrameLive());
- RenderProcessHostKillWaiter kill_waiter(web_rfh->GetProcess());
- IPC::IpcSecurityTestUtil::PwnMessageReceived(
- web_rfh->GetProcess()->GetChannel(),
- FrameHostMsg_RenderProcessGone(
- web_rfh->GetRoutingID(), base::TERMINATION_STATUS_NORMAL_TERMINATION,
- 0));
-
- // If the message had gone through, we'd have marked the RFH as dead but
- // 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()->IsInitializedAndNotDead());
- ASSERT_FALSE(web_rfh->IsRenderFrameLive());
-}
-
class WaitingCookieStore : public net::CookieMonster {
public:
WaitingCookieStore() : CookieMonster(nullptr, nullptr) {}
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 4072c68b11f..a28f80496b2 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
@@ -70,8 +70,7 @@ RenderFrameProxyHost::RenderFrameProxyHost(SiteInstance* site_instance,
RenderFrameProxyHostID(GetProcess()->GetID(), routing_id_),
this)).second);
CHECK(render_view_host ||
- (frame_tree_node_->render_manager()->ForInnerDelegate() &&
- frame_tree_node_->IsMainFrame()));
+ frame_tree_node_->render_manager()->IsMainFrameForInnerDelegate());
if (render_view_host)
frame_tree_node_->frame_tree()->AddRenderViewHostRef(render_view_host_);
@@ -81,8 +80,7 @@ RenderFrameProxyHost::RenderFrameProxyHost(SiteInstance* site_instance,
->current_frame_host()
->GetSiteInstance() == site_instance;
bool is_proxy_to_outer_delegate =
- frame_tree_node_->IsMainFrame() &&
- frame_tree_node_->render_manager()->ForInnerDelegate();
+ frame_tree_node_->render_manager()->IsMainFrameForInnerDelegate();
// If this is a proxy to parent frame or this proxy is for the inner
// WebContents's FrameTreeNode in outer WebContents's SiteInstance, then we
@@ -100,9 +98,6 @@ RenderFrameProxyHost::RenderFrameProxyHost(SiteInstance* site_instance,
}
RenderFrameProxyHost::~RenderFrameProxyHost() {
- if (!destruction_callback_.is_null())
- std::move(destruction_callback_).Run();
-
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.
@@ -170,6 +165,13 @@ bool RenderFrameProxyHost::OnMessageReceived(const IPC::Message& msg) {
bool RenderFrameProxyHost::InitRenderFrameProxy() {
DCHECK(!render_frame_proxy_created_);
+ // If the current RenderFrameHost is pending deletion, no new proxies should
+ // be created for it, since this frame should no longer be visible from other
+ // processes. We can get here with postMessage while trying to recreate
+ // proxies for the sender.
+ if (!frame_tree_node_->current_frame_host()->is_active())
+ return false;
+
// It is possible to reach this when the process is dead (in particular, when
// creating proxies from CreateProxiesForChildFrame). In that case, don't
// create the proxy. The process shouldn't be resurrected just to create
@@ -260,19 +262,12 @@ void RenderFrameProxyHost::ScrollRectToVisible(
void RenderFrameProxyHost::BubbleLogicalScroll(
blink::WebScrollDirection direction,
- blink::WebScrollGranularity granularity) {
+ ui::input_types::ScrollGranularity granularity) {
Send(new FrameMsg_BubbleLogicalScroll(routing_id_, direction, granularity));
}
-void RenderFrameProxyHost::SetDestructionCallback(
- DestructionCallback destruction_callback) {
- destruction_callback_ = std::move(destruction_callback);
-}
-
void RenderFrameProxyHost::OnDetach() {
- if (frame_tree_node_->render_manager()->ForInnerDelegate()) {
- // Only main frame proxy can detach for inner WebContents.
- DCHECK(frame_tree_node_->IsMainFrame());
+ if (frame_tree_node_->render_manager()->IsMainFrameForInnerDelegate()) {
frame_tree_node_->render_manager()->RemoveOuterDelegateFrame();
return;
}
@@ -320,6 +315,13 @@ void RenderFrameProxyHost::OnOpenURL(
// in the current tab.
DCHECK_EQ(WindowOpenDisposition::CURRENT_TAB, params.disposition);
+ // Augment |download_policy| for situations that were not covered on the
+ // renderer side, e.g. status not available on remote frame, etc.
+ NavigationDownloadPolicy download_policy = params.download_policy;
+ GetContentClient()->browser()->AugmentNavigationDownloadPolicy(
+ frame_tree_node_->navigator()->GetController()->GetWebContents(),
+ current_rfh, params.user_gesture, &download_policy);
+
// TODO(alexmos, creis): Figure out whether |params.user_gesture| needs to be
// passed in as well.
// TODO(lfg, lukasza): Remove |extra_headers| parameter from
@@ -331,7 +333,7 @@ void RenderFrameProxyHost::OnOpenURL(
frame_tree_node_->navigator()->NavigateFromFrameProxy(
current_rfh, validated_url, params.initiator_origin, site_instance_.get(),
params.referrer, ui::PAGE_TRANSITION_LINK,
- params.should_replace_current_entry, params.download_policy,
+ params.should_replace_current_entry, download_policy,
params.uses_post ? "POST" : "GET", params.resource_request_body,
params.extra_headers, std::move(blob_url_loader_factory));
}
@@ -344,6 +346,15 @@ void RenderFrameProxyHost::OnCheckCompleted() {
void RenderFrameProxyHost::OnRouteMessageEvent(
const FrameMsg_PostMessage_Params& params) {
RenderFrameHostImpl* target_rfh = frame_tree_node()->current_frame_host();
+ if (!target_rfh->IsRenderFrameLive()) {
+ // Check if there is an inner delegate involved; if so target its main
+ // frame or otherwise return since there is no point in forwarding the
+ // message.
+ target_rfh = target_rfh->delegate()->GetMainFrameForInnerDelegate(
+ target_rfh->frame_tree_node());
+ if (!target_rfh || !target_rfh->IsRenderFrameLive())
+ return;
+ }
// |targetOrigin| argument of postMessage is already checked by
// blink::LocalDOMWindow::DispatchMessageEventWithOriginCheck (needed for
diff --git a/chromium/content/browser/frame_host/render_frame_proxy_host.h b/chromium/content/browser/frame_host/render_frame_proxy_host.h
index 45588e94f07..2336e450b43 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.h
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.h
@@ -67,8 +67,6 @@ class RenderFrameProxyHost
: public IPC::Listener,
public IPC::Sender {
public:
- using DestructionCallback = base::OnceClosure;
-
static RenderFrameProxyHost* FromID(int process_id, int routing_id);
RenderFrameProxyHost(SiteInstance* site_instance,
@@ -135,7 +133,7 @@ class RenderFrameProxyHost
// Continues to bubble a logical scroll from the frame's process. Bubbling
// continues from the frame owner element in the parent process.
void BubbleLogicalScroll(blink::WebScrollDirection direction,
- blink::WebScrollGranularity granularity);
+ ui::input_types::ScrollGranularity granularity);
void set_render_frame_proxy_created(bool created) {
render_frame_proxy_created_ = created;
@@ -144,9 +142,6 @@ class RenderFrameProxyHost
// Returns if the RenderFrameProxy for this host is alive.
bool is_render_frame_proxy_live() { return render_frame_proxy_created_; }
- // Sets a callback that is run when this is destroyed.
- void SetDestructionCallback(DestructionCallback destruction_callback);
-
private:
// IPC Message handlers.
void OnDetach();
@@ -187,8 +182,6 @@ class RenderFrameProxyHost
// are associated with it.
RenderViewHostImpl* render_view_host_;
- DestructionCallback destruction_callback_;
-
DISALLOW_COPY_AND_ASSIGN(RenderFrameProxyHost);
};
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 6b29e7fc50d..1384d8baf77 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
@@ -33,7 +33,6 @@
#include "content/public/common/use_zoom_for_dsf_policy.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "skia/ext/platform_canvas.h"
-#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/events/base_event_utils.h"
#include "ui/gfx/geometry/dip_util.h"
@@ -158,7 +157,7 @@ void RenderWidgetHostViewGuest::Show() {
// the renderer.
SendSurfaceInfoToEmbedder();
}
- host()->WasShown(false /* record_presentation_time */);
+ host()->WasShown(base::nullopt /* record_tab_switch_time_request */);
}
void RenderWidgetHostViewGuest::Hide() {
@@ -299,15 +298,13 @@ gfx::PointF RenderWidgetHostViewGuest::TransformRootPointToViewCoordSpace(
return transformed_point;
}
-void RenderWidgetHostViewGuest::RenderProcessGone(
- base::TerminationStatus status,
- int error_code) {
+void RenderWidgetHostViewGuest::RenderProcessGone() {
// The |platform_view_| gets destroyed before we get here if this view
// is for an InterstitialPage.
if (platform_view_)
- platform_view_->RenderProcessGone(status, error_code);
+ platform_view_->RenderProcessGone();
- RenderWidgetHostViewChildFrame::RenderProcessGone(status, error_code);
+ RenderWidgetHostViewChildFrame::RenderProcessGone();
}
void RenderWidgetHostViewGuest::Destroy() {
@@ -361,14 +358,6 @@ void RenderWidgetHostViewGuest::OnDidUpdateVisualPropertiesComplete(
void RenderWidgetHostViewGuest::OnAttached() {
RegisterFrameSinkId();
-#if defined(USE_AURA)
- if (features::IsMultiProcessMash()) {
- aura::Env::GetInstance()->ScheduleEmbed(
- GetWindowTreeClientFromRenderer(),
- base::BindOnce(&RenderWidgetHostViewGuest::OnGotEmbedToken,
- weak_ptr_factory_.GetWeakPtr()));
- }
-#endif
SendSurfaceInfoToEmbedder();
}
@@ -798,7 +787,7 @@ void RenderWidgetHostViewGuest::OnHandleInputEvent(
// sure other plugins would behave appropriately (i.e. return 'false').
if (gesture_event.GetType() == blink::WebInputEvent::kGestureScrollUpdate &&
gesture_event.data.scroll_update.inertial_phase ==
- blink::WebGestureEvent::kMomentumPhase) {
+ blink::WebGestureEvent::InertialPhaseState::kMomentum) {
return;
}
host()->ForwardGestureEvent(gesture_event);
@@ -806,16 +795,4 @@ void RenderWidgetHostViewGuest::OnHandleInputEvent(
}
}
-#if defined(USE_AURA)
-void RenderWidgetHostViewGuest::OnGotEmbedToken(
- const base::UnguessableToken& token) {
- if (!guest_)
- return;
-
- guest_->SendMessageToEmbedder(
- std::make_unique<BrowserPluginMsg_SetMusEmbedToken>(
- guest_->browser_plugin_instance_id(), token));
-}
-#endif
-
} // namespace content
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 74655e0ee06..3c568ad946c 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
@@ -24,10 +24,6 @@
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/gfx/native_widget_types.h"
-namespace base {
-class UnguessableToken;
-}
-
namespace content {
class BrowserPluginGuest;
class RenderWidgetHost;
@@ -105,8 +101,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) override;
#endif
- void RenderProcessGone(base::TerminationStatus status,
- int error_code) override;
+ void RenderProcessGone() override;
void Destroy() override;
void SetTooltipText(const base::string16& tooltip_text) override;
void SelectionChanged(const base::string16& text,
@@ -188,10 +183,6 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
void ProcessTouchpadZoomEventAckInRoot(const blink::WebGestureEvent& event,
InputEventAckState ack_result);
-#if defined(USE_AURA)
- void OnGotEmbedToken(const base::UnguessableToken& token);
-#endif
-
// BrowserPluginGuest and RenderWidgetHostViewGuest's lifetimes are not tied
// to one another, therefore we access |guest_| through WeakPtr.
base::WeakPtr<BrowserPluginGuest> guest_;
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc b/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc
index f473c2bc126..d4ee6f500da 100644
--- a/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc
+++ b/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc
@@ -32,11 +32,11 @@ using device::mojom::GeopositionPtr;
using blink::mojom::GeolocationService;
using blink::mojom::GeolocationServicePtr;
-typedef base::Callback<void(PermissionStatus)> PermissionCallback;
-
namespace content {
namespace {
+using PermissionCallback = base::OnceCallback<void(PermissionStatus)>;
+
double kMockLatitude = 1.0;
double kMockLongitude = 10.0;
GURL kMainUrl = GURL("https://www.google.com/maps");
@@ -52,24 +52,24 @@ class TestPermissionManager : public MockPermissionManager {
RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
bool user_gesture,
- const PermissionCallback& callback) override {
+ PermissionCallback callback) override {
EXPECT_EQ(permissions, PermissionType::GEOLOCATION);
EXPECT_TRUE(user_gesture);
- request_callback_.Run(callback);
+ request_callback_.Run(std::move(callback));
return request_id_;
}
void SetRequestId(int request_id) { request_id_ = request_id; }
void SetRequestCallback(
- const base::Callback<void(const PermissionCallback&)>& request_callback) {
- request_callback_ = request_callback;
+ base::RepeatingCallback<void(PermissionCallback)> request_callback) {
+ request_callback_ = std::move(request_callback);
}
private:
int request_id_;
- base::Callback<void(const PermissionCallback&)> request_callback_;
+ base::RepeatingCallback<void(PermissionCallback)> request_callback_;
};
class GeolocationServiceTest : public RenderViewHostImplTestHarness {
@@ -156,7 +156,7 @@ TEST_F(GeolocationServiceTest, PermissionGrantedPolicyViolation) {
CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/false);
permission_manager()->SetRequestCallback(
- base::BindRepeating([](const PermissionCallback& callback) {
+ base::BindRepeating([](PermissionCallback callback) {
ADD_FAILURE() << "Permissions checked unexpectedly.";
}));
GeolocationPtr geolocation;
@@ -180,8 +180,8 @@ TEST_F(GeolocationServiceTest, PermissionGrantedNoPolicyViolation) {
CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
permission_manager()->SetRequestCallback(
- base::BindRepeating([](const PermissionCallback& callback) {
- callback.Run(PermissionStatus::GRANTED);
+ base::BindRepeating([](PermissionCallback callback) {
+ std::move(callback).Run(PermissionStatus::GRANTED);
}));
GeolocationPtr geolocation;
service()->CreateGeolocation(
@@ -207,8 +207,8 @@ TEST_F(GeolocationServiceTest, PermissionGrantedNoPolicyViolation) {
TEST_F(GeolocationServiceTest, PermissionGrantedSync) {
CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
permission_manager()->SetRequestCallback(
- base::BindRepeating([](const PermissionCallback& callback) {
- callback.Run(PermissionStatus::GRANTED);
+ base::BindRepeating([](PermissionCallback callback) {
+ std::move(callback).Run(PermissionStatus::GRANTED);
}));
GeolocationPtr geolocation;
service()->CreateGeolocation(
@@ -234,8 +234,8 @@ TEST_F(GeolocationServiceTest, PermissionGrantedSync) {
TEST_F(GeolocationServiceTest, PermissionDeniedSync) {
CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
permission_manager()->SetRequestCallback(
- base::BindRepeating([](const PermissionCallback& callback) {
- callback.Run(PermissionStatus::DENIED);
+ base::BindRepeating([](PermissionCallback callback) {
+ std::move(callback).Run(PermissionStatus::DENIED);
}));
GeolocationPtr geolocation;
service()->CreateGeolocation(
@@ -257,13 +257,10 @@ TEST_F(GeolocationServiceTest, PermissionGrantedAsync) {
CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
permission_manager()->SetRequestId(42);
permission_manager()->SetRequestCallback(
- base::BindRepeating([](const PermissionCallback& permission_callback) {
+ base::BindRepeating([](PermissionCallback permission_callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(
- [](const PermissionCallback& callback) {
- callback.Run(PermissionStatus::GRANTED);
- },
- permission_callback));
+ FROM_HERE, base::BindOnce(std::move(permission_callback),
+ PermissionStatus::GRANTED));
}));
GeolocationPtr geolocation;
service()->CreateGeolocation(
@@ -290,13 +287,10 @@ TEST_F(GeolocationServiceTest, PermissionDeniedAsync) {
CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
permission_manager()->SetRequestId(42);
permission_manager()->SetRequestCallback(
- base::BindRepeating([](const PermissionCallback& permission_callback) {
+ base::BindRepeating([](PermissionCallback permission_callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(
- [](const PermissionCallback& callback) {
- callback.Run(PermissionStatus::DENIED);
- },
- permission_callback));
+ FROM_HERE, base::BindOnce(std::move(permission_callback),
+ PermissionStatus::DENIED));
}));
GeolocationPtr geolocation;
service()->CreateGeolocation(
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 d19da42b024..23c2d0db07c 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -37,7 +37,6 @@
#include "gpu/ipc/common/gpu_client_ids.h"
#include "gpu/ipc/in_process_command_buffer.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/constants.mojom.h"
-#include "ui/base/ui_base_features.h"
#if defined(OS_MACOSX)
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
@@ -304,9 +303,6 @@ BrowserGpuChannelHostFactory::~BrowserGpuChannelHostFactory() {
void BrowserGpuChannelHostFactory::EstablishGpuChannel(
gpu::GpuChannelEstablishedCallback callback) {
-#if defined(USE_AURA)
- DCHECK(!features::IsMultiProcessMash());
-#endif
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (gpu_channel_.get() && gpu_channel_->IsLost()) {
DCHECK(!pending_request_.get());
diff --git a/chromium/content/browser/gpu/delegate_to_browser_gpu_service_accelerator_factory.cc b/chromium/content/browser/gpu/chromeos/delegate_to_browser_gpu_service_accelerator_factory.cc
index 38705959900..3277721e09c 100644
--- a/chromium/content/browser/gpu/delegate_to_browser_gpu_service_accelerator_factory.cc
+++ b/chromium/content/browser/gpu/chromeos/delegate_to_browser_gpu_service_accelerator_factory.cc
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/public/browser/delegate_to_browser_gpu_service_accelerator_factory.h"
+#include "content/public/browser/chromeos/delegate_to_browser_gpu_service_accelerator_factory.h"
-#include "content/browser/gpu/video_capture_dependencies.h"
+#include "content/browser/gpu/chromeos/video_capture_dependencies.h"
namespace content {
void DelegateToBrowserGpuServiceAcceleratorFactory::CreateJpegDecodeAccelerator(
- media::mojom::MjpegDecodeAcceleratorRequest jda_request) {
+ chromeos_camera::mojom::MjpegDecodeAcceleratorRequest jda_request) {
VideoCaptureDependencies::CreateJpegDecodeAccelerator(std::move(jda_request));
}
diff --git a/chromium/content/browser/gpu/video_capture_dependencies.cc b/chromium/content/browser/gpu/chromeos/video_capture_dependencies.cc
index edb441051e4..22e8d8fc878 100644
--- a/chromium/content/browser/gpu/video_capture_dependencies.cc
+++ b/chromium/content/browser/gpu/chromeos/video_capture_dependencies.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/gpu/video_capture_dependencies.h"
+#include "content/browser/gpu/chromeos/video_capture_dependencies.h"
#include "base/bind.h"
#include "base/task/post_task.h"
@@ -14,7 +14,7 @@ namespace content {
// static
void VideoCaptureDependencies::CreateJpegDecodeAccelerator(
- media::mojom::MjpegDecodeAcceleratorRequest accelerator) {
+ chromeos_camera::mojom::MjpegDecodeAcceleratorRequest accelerator) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
@@ -23,8 +23,8 @@ void VideoCaptureDependencies::CreateJpegDecodeAccelerator(
return;
}
- auto* host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- true /*force_create*/);
+ auto* host =
+ GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED, true /*force_create*/);
if (host) {
host->gpu_service()->CreateJpegDecodeAccelerator(std::move(accelerator));
} else {
@@ -35,7 +35,7 @@ void VideoCaptureDependencies::CreateJpegDecodeAccelerator(
#if defined(OS_CHROMEOS)
// static
void VideoCaptureDependencies::CreateJpegEncodeAccelerator(
- media::mojom::JpegEncodeAcceleratorRequest accelerator) {
+ chromeos_camera::mojom::JpegEncodeAcceleratorRequest accelerator) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
@@ -44,8 +44,8 @@ void VideoCaptureDependencies::CreateJpegEncodeAccelerator(
return;
}
- auto* host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- true /*force_create*/);
+ auto* host =
+ GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED, true /*force_create*/);
if (host) {
host->gpu_service()->CreateJpegEncodeAccelerator(std::move(accelerator));
} else {
diff --git a/chromium/content/browser/gpu/video_capture_dependencies.h b/chromium/content/browser/gpu/chromeos/video_capture_dependencies.h
index 2be659ddfd2..b4a19ab723c 100644
--- a/chromium/content/browser/gpu/video_capture_dependencies.h
+++ b/chromium/content/browser/gpu/chromeos/video_capture_dependencies.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_GPU_VIDEO_CAPTURE_DEPENDENCIES_H_
-#define CONTENT_BROWSER_GPU_VIDEO_CAPTURE_DEPENDENCIES_H_
+#ifndef CONTENT_BROWSER_GPU_CHROMEOS_VIDEO_CAPTURE_DEPENDENCIES_H_
+#define CONTENT_BROWSER_GPU_CHROMEOS_VIDEO_CAPTURE_DEPENDENCIES_H_
#include "content/common/content_export.h"
#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
@@ -14,13 +14,11 @@ namespace content {
class CONTENT_EXPORT VideoCaptureDependencies {
public:
static void CreateJpegDecodeAccelerator(
- media::mojom::MjpegDecodeAcceleratorRequest accelerator);
-#if defined(OS_CHROMEOS)
+ chromeos_camera::mojom::MjpegDecodeAcceleratorRequest accelerator);
static void CreateJpegEncodeAccelerator(
- media::mojom::JpegEncodeAcceleratorRequest accelerator);
-#endif // defined(OS_CHROMEOS)
+ chromeos_camera::mojom::JpegEncodeAcceleratorRequest accelerator);
};
} // namespace content
-#endif // CONTENT_BROWSER_GPU_VIDEO_CAPTURE_DEPENDENCIES_H_
+#endif // CONTENT_BROWSER_GPU_CHROMEOS_VIDEO_CAPTURE_DEPENDENCIES_H_
diff --git a/chromium/content/browser/gpu/compositor_util.cc b/chromium/content/browser/gpu/compositor_util.cc
index 9935c095a62..e850ca4fc01 100644
--- a/chromium/content/browser/gpu/compositor_util.cc
+++ b/chromium/content/browser/gpu/compositor_util.cc
@@ -35,7 +35,6 @@
#include "gpu/config/gpu_switches.h"
#include "gpu/ipc/host/gpu_memory_buffer_support.h"
#include "media/media_buildflags.h"
-#include "ui/base/ui_base_features.h"
#include "ui/gl/gl_switches.h"
namespace content {
@@ -79,8 +78,6 @@ gpu::GpuFeatureStatus SafeGetFeatureStatus(
gpu::GpuFeatureStatus GetGpuCompositingStatus(
const gpu::GpuFeatureInfo& gpu_feature_info,
GpuFeatureInfoType type) {
- if (features::IsMultiProcessMash())
- return gpu::kGpuFeatureStatusEnabled;
gpu::GpuFeatureStatus status = SafeGetFeatureStatus(
gpu_feature_info, gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING);
#if defined(USE_AURA) || defined(OS_MACOSX)
@@ -172,14 +169,18 @@ const GpuFeatureData GetGpuFeatureData(
"Out-of-process accelerated rasterization has been disabled, either "
"via blacklist, about:flags or the command line.",
false, true},
+ {"metal",
+ SafeGetFeatureStatus(gpu_feature_info, gpu::GPU_FEATURE_TYPE_METAL),
+#if defined(OS_MACOSX)
+ !base::FeatureList::IsEnabled(features::kMetal) /* disabled */,
+ "Metal is not enabled by default.",
+#else
+ true /* disabled */, "Metal is only available on macOS.",
+#endif
+ false /* fallback_to_software */, false /* needs_gpu_access */},
{"multiple_raster_threads", gpu::kGpuFeatureStatusEnabled,
NumberOfRendererRasterThreads() == 1, "Raster is using a single thread.",
false, true},
- {"native_gpu_memory_buffers", gpu::kGpuFeatureStatusEnabled,
- !gpu::AreNativeGpuMemoryBuffersEnabled(),
- "Native GpuMemoryBuffers have been disabled, either via about:flags or "
- "command line.",
- true, true},
{"surface_control",
SafeGetFeatureStatus(gpu_feature_info,
gpu::GPU_FEATURE_TYPE_ANDROID_SURFACE_CONTROL),
@@ -278,6 +279,8 @@ std::unique_ptr<base::DictionaryValue> GetFeatureStatusImpl(
if (features::IsVizHitTestingSurfaceLayerEnabled())
status += "_on";
}
+ if (gpu_feature_data.name == "metal")
+ status += "_on";
}
feature_status_dict->SetString(gpu_feature_data.name, status);
}
@@ -436,10 +439,6 @@ bool IsGpuMemoryBufferCompositorResourcesEnabled() {
return false;
}
- // Native GPU memory buffers are required.
- if (!gpu::AreNativeGpuMemoryBuffersEnabled())
- return false;
-
#if defined(OS_MACOSX)
return true;
#else
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.cc b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
index 69e4b935590..13c5feb212c 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
@@ -84,10 +84,10 @@ bool GpuDataManagerImpl::HardwareAccelerationEnabled() const {
return private_->HardwareAccelerationEnabled();
}
-void GpuDataManagerImpl::AppendGpuCommandLine(
- base::CommandLine* command_line) const {
+void GpuDataManagerImpl::AppendGpuCommandLine(base::CommandLine* command_line,
+ GpuProcessKind kind) const {
base::AutoLock auto_lock(lock_);
- private_->AppendGpuCommandLine(command_line);
+ private_->AppendGpuCommandLine(command_line, kind);
}
void GpuDataManagerImpl::RequestGpuSupportedRuntimeVersion() const {
@@ -147,9 +147,10 @@ gpu::GpuFeatureInfo GpuDataManagerImpl::GetGpuFeatureInfoForHardwareGpu()
}
void GpuDataManagerImpl::UpdateGpuPreferences(
- gpu::GpuPreferences* gpu_preferences) const {
+ gpu::GpuPreferences* gpu_preferences,
+ GpuProcessKind kind) const {
base::AutoLock auto_lock(lock_);
- private_->UpdateGpuPreferences(gpu_preferences);
+ private_->UpdateGpuPreferences(gpu_preferences, kind);
}
void GpuDataManagerImpl::AddLogMessage(int level,
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.h b/chromium/content/browser/gpu/gpu_data_manager_impl.h
index 9eae9413860..9c3f898a8b0 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.h
@@ -61,7 +61,8 @@ class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager {
void RemoveObserver(GpuDataManagerObserver* observer) override;
void DisableHardwareAcceleration() override;
bool HardwareAccelerationEnabled() const override;
- void AppendGpuCommandLine(base::CommandLine* command_line) const override;
+ void AppendGpuCommandLine(base::CommandLine* command_line,
+ GpuProcessKind kind) const override;
void RequestGpuSupportedRuntimeVersion() const;
bool GpuProcessStartAllowed() const;
@@ -89,7 +90,8 @@ class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager {
gpu::GpuFeatureInfo GetGpuFeatureInfoForHardwareGpu() const;
// Update GpuPreferences based on blacklisting decisions.
- void UpdateGpuPreferences(gpu::GpuPreferences* gpu_preferences) const;
+ void UpdateGpuPreferences(gpu::GpuPreferences* gpu_preferences,
+ GpuProcessKind kind) const;
void AddLogMessage(int level,
const std::string& header,
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 2b4e87526d8..590db60f0f8 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -80,7 +80,7 @@ int GetGpuBlacklistHistogramValueWin(gpu::GpuFeatureStatus status) {
// Enabled VERSION_XP = 5,
// ...
static const base::win::Version version = base::win::GetVersion();
- if (version == base::win::VERSION_WIN_LAST)
+ if (version == base::win::Version::WIN_LAST)
return -1;
DCHECK_NE(gpu::kGpuFeatureStatusMax, status);
int entry_index = static_cast<int>(version) * gpu::kGpuFeatureStatusMax;
@@ -163,7 +163,7 @@ void UpdateFeatureStats(const gpu::GpuFeatureInfo& gpu_feature_info) {
#if defined(OS_WIN)
int value_win = GetGpuBlacklistHistogramValueWin(value);
if (value_win >= 0) {
- int32_t max_sample = static_cast<int32_t>(base::win::VERSION_WIN_LAST) *
+ int32_t max_sample = static_cast<int32_t>(base::win::Version::WIN_LAST) *
gpu::kGpuFeatureStatusMax;
histogram_pointer = base::LinearHistogram::FactoryGet(
kGpuBlacklistFeatureHistogramNamesWin[i], 1, max_sample,
@@ -290,7 +290,7 @@ GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(GpuDataManagerImpl* owner)
if (command_line->HasSwitch(switches::kSingleProcess) ||
command_line->HasSwitch(switches::kInProcessGPU)) {
- AppendGpuCommandLine(command_line);
+ AppendGpuCommandLine(command_line, GPU_PROCESS_KIND_SANDBOXED);
}
#if defined(OS_MACOSX)
@@ -386,7 +386,7 @@ void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
#if defined(OS_WIN)
complete_gpu_info_already_requested_ = true;
- GpuProcessHost::CallOnIO(GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED_NO_GL,
+ GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_UNSANDBOXED_NO_GL,
true /* force_create */,
base::BindOnce([](GpuProcessHost* host) {
if (!host)
@@ -404,9 +404,8 @@ void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
void GpuDataManagerImplPrivate::RequestGpuSupportedRuntimeVersion() {
#if defined(OS_WIN)
base::OnceClosure task = base::BindOnce([]() {
- GpuProcessHost* host =
- GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED_NO_GL,
- true /* force_create */);
+ GpuProcessHost* host = GpuProcessHost::Get(
+ GPU_PROCESS_KIND_UNSANDBOXED_NO_GL, true /* force_create */);
if (!host)
return;
host->gpu_service()->GetGpuSupportedRuntimeVersion(
@@ -440,7 +439,7 @@ gpu::GpuFeatureStatus GpuDataManagerImplPrivate::GetFeatureStatus(
void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate(
GpuDataManager::VideoMemoryUsageStatsCallback callback) const {
GpuProcessHost::CallOnIO(
- GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
+ GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
base::BindOnce(&RequestVideoMemoryUsageStats, std::move(callback)));
}
@@ -561,13 +560,15 @@ gpu::GpuFeatureInfo GpuDataManagerImplPrivate::GetGpuFeatureInfoForHardwareGpu()
}
void GpuDataManagerImplPrivate::AppendGpuCommandLine(
- base::CommandLine* command_line) const {
+ base::CommandLine* command_line,
+ GpuProcessKind kind) const {
DCHECK(command_line);
const base::CommandLine* browser_command_line =
base::CommandLine::ForCurrentProcess();
gpu::GpuPreferences gpu_prefs = GetGpuPreferencesFromCommandLine();
- UpdateGpuPreferences(&gpu_prefs);
+ UpdateGpuPreferences(&gpu_prefs, kind);
+
command_line->AppendSwitchASCII(switches::kGpuPreferences,
gpu_prefs.ToSwitchValue());
@@ -598,7 +599,8 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
}
void GpuDataManagerImplPrivate::UpdateGpuPreferences(
- gpu::GpuPreferences* gpu_preferences) const {
+ gpu::GpuPreferences* gpu_preferences,
+ GpuProcessKind kind) const {
DCHECK(gpu_preferences);
// For performance reasons, discourage storing VideoFrames in a biplanar
@@ -618,6 +620,9 @@ void GpuDataManagerImplPrivate::UpdateGpuPreferences(
gpu::CreateBufferUsageAndFormatExceptionList();
gpu_preferences->watchdog_starts_backgrounded = !application_is_visible_;
+
+ if (kind == GPU_PROCESS_KIND_UNSANDBOXED_NO_GL)
+ gpu_preferences->gpu_startup_dialog = false;
}
void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
@@ -688,8 +693,7 @@ void GpuDataManagerImplPrivate::HandleGpuSwitch() {
// Notify observers in the browser process.
ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
// Pass the notification to the GPU process to notify observers there.
- GpuProcessHost::CallOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- false /* force_create */,
+ GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
base::BindOnce([](GpuProcessHost* host) {
if (host)
host->gpu_service()->GpuSwitched();
@@ -878,14 +882,7 @@ void GpuDataManagerImplPrivate::FallBackToNextGpuMode() {
#else
// TODO(kylechar): Use GpuMode to store the current mode instead of
// multiple bools.
-
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableSoftwareCompositingFallback)) {
- // Some tests only want to run with a functional GPU Process. Fail out here
- // rather than falling back to software compositing and silently passing.
- LOG(FATAL) << "The GPU Process Crash Limit was reached, and falling back "
- << "to software compositing is disabled.";
- } else if (!card_disabled_) {
+ if (!card_disabled_) {
DisableHardwareAcceleration();
} else if (SwiftShaderAllowed()) {
swiftshader_blocked_ = true;
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 24b8b377c4d..b19b5a219d2 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -72,9 +72,11 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
gpu::GpuFeatureInfo GetGpuFeatureInfo() const;
gpu::GpuFeatureInfo GetGpuFeatureInfoForHardwareGpu() const;
- void AppendGpuCommandLine(base::CommandLine* command_line) const;
+ void AppendGpuCommandLine(base::CommandLine* command_line,
+ GpuProcessKind kind) const;
- void UpdateGpuPreferences(gpu::GpuPreferences* gpu_preferences) const;
+ void UpdateGpuPreferences(gpu::GpuPreferences* gpu_preferences,
+ GpuProcessKind kind) const;
void AddLogMessage(int level,
const std::string& header,
diff --git a/chromium/content/browser/gpu/gpu_internals_ui.cc b/chromium/content/browser/gpu/gpu_internals_ui.cc
index 29f0f187697..6238102c608 100644
--- a/chromium/content/browser/gpu/gpu_internals_ui.cc
+++ b/chromium/content/browser/gpu/gpu_internals_ui.cc
@@ -72,7 +72,6 @@ WebUIDataSource* CreateGpuHTMLSource() {
source->SetJsonPath("strings.js");
source->AddResourcePath("gpu_internals.js", IDR_GPU_INTERNALS_JS);
source->SetDefaultResource(IDR_GPU_INTERNALS_HTML);
- source->UseGzip();
return source;
}
@@ -188,15 +187,12 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue(
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)));
+ basic_info->Append(NewDescriptionValuePair(
+ "YUY2 overlay support",
+ gpu::OverlaySupportToString(gpu_info.yuy2_overlay_support)));
+ basic_info->Append(NewDescriptionValuePair(
+ "NV12 overlay support",
+ gpu::OverlaySupportToString(gpu_info.nv12_overlay_support)));
std::vector<gfx::PhysicalDisplaySize> display_sizes =
gfx::GetPhysicalSizeForDisplays();
@@ -308,6 +304,21 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue(
"RGBA visual ID", base::NumberToString(gpu_info.rgba_visual)));
#endif
+ std::string buffer_formats;
+ for (int i = 0; i <= static_cast<int>(gfx::BufferFormat::LAST); ++i) {
+ const gfx::BufferFormat buffer_format = static_cast<gfx::BufferFormat>(i);
+ if (i > 0)
+ buffer_formats += ", ";
+ buffer_formats += gfx::BufferFormatToString(buffer_format);
+ const bool supported = base::ContainsValue(
+ gpu_feature_info.supported_buffer_formats_for_allocation_and_texturing,
+ buffer_format);
+ buffer_formats += supported ? ": supported" : ": not supported";
+ }
+ basic_info->Append(NewDescriptionValuePair(
+ "gfx::BufferFormats supported for allocation and texturing",
+ buffer_formats));
+
return basic_info;
}
@@ -387,6 +398,11 @@ std::unique_ptr<base::ListValue> getDisplayInfo() {
base::NumberToString(display.depth_per_component())));
display_info->Append(NewDescriptionValuePair(
"Bits per pixel", base::NumberToString(display.color_depth())));
+ if (display.display_frequency()) {
+ display_info->Append(NewDescriptionValuePair(
+ "Refresh Rate in Hz",
+ base::NumberToString(display.display_frequency())));
+ }
}
return display_info;
}
diff --git a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
index 0c28a05e0ee..e1af590f71c 100644
--- a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -252,8 +252,7 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
content::GpuBrowsertestCreateContext(GetGpuChannel());
ContextLostRunLoop run_loop(provider.get());
ASSERT_EQ(provider->BindToCurrentThread(), gpu::ContextResult::kSuccess);
- GpuProcessHost::CallOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- false /* force_create */,
+ GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
base::BindOnce([](GpuProcessHost* host) {
if (host)
host->gpu_service()->Crash();
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index 53fc82c1f2c..de3031466a5 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -75,7 +75,6 @@
#include "services/service_manager/public/cpp/interface_provider.h"
#include "services/service_manager/sandbox/sandbox_type.h"
#include "services/service_manager/sandbox/switches.h"
-#include "services/ws/public/mojom/constants.mojom.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/display/display_switches.h"
@@ -210,9 +209,6 @@ static const char* const kSwitchNames[] = {
switches::kDisableShaderNameHashing,
switches::kDisableSkiaRuntimeOpts,
switches::kDisableWebRtcHWEncoding,
-#if defined(OS_WIN)
- switches::kEnableAcceleratedVpxDecode,
-#endif
switches::kEnableGpuRasterization,
switches::kEnableLogging,
switches::kEnableVizDevTools,
@@ -253,10 +249,7 @@ static const char* const kSwitchNames[] = {
switches::kForceVideoOverlays,
#if defined(OS_ANDROID)
switches::kEnableReachedCodeProfiler,
- switches::kOrderfileMemoryOptimization,
#endif
- switches::kWebglAntialiasingMode,
- switches::kWebglMSAASampleCount,
};
// These values are persisted to logs. Entries should not be renumbered and
@@ -272,9 +265,9 @@ enum GPUProcessLifetimeEvent {
// Indexed by GpuProcessKind. There is one of each kind maximum. This array may
// only be accessed from the IO thread.
-GpuProcessHost* g_gpu_process_hosts[GpuProcessHost::GPU_PROCESS_KIND_COUNT];
+GpuProcessHost* g_gpu_process_hosts[GPU_PROCESS_KIND_COUNT];
-void RunCallbackOnIO(GpuProcessHost::GpuProcessKind kind,
+void RunCallbackOnIO(GpuProcessKind kind,
bool force_create,
base::OnceCallback<void(GpuProcessHost*)> callback) {
GpuProcessHost* host = GpuProcessHost::Get(kind, force_create);
@@ -419,13 +412,7 @@ class GpuSandboxedProcessLauncherDelegate
if (UseOpenGLRenderer())
return true;
- HDESK thread_desktop = ::GetThreadDesktop(::GetCurrentThreadId());
- if (!thread_desktop)
- return false;
-
- base::string16 desktop_name = sandbox::GetWindowObjectName(thread_desktop);
- ::CloseDesktop(thread_desktop);
- return !lstrcmpi(desktop_name.c_str(), L"winlogon");
+ return base::win::IsRunningUnderDesktopName(STRING16_LITERAL("winlogon"));
}
base::CommandLine cmd_line_;
@@ -463,14 +450,6 @@ void BindDiscardableMemoryRequestOnIO(
void BindDiscardableMemoryRequestOnUI(
discardable_memory::mojom::DiscardableSharedMemoryManagerRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-#if defined(USE_AURA)
- if (features::IsMultiProcessMash()) {
- ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
- ws::mojom::kServiceName, std::move(request));
- return;
- }
-#endif
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(
@@ -603,7 +582,7 @@ void GpuProcessHost::CallOnIO(
bool force_create,
base::OnceCallback<void(GpuProcessHost*)> callback) {
#if !defined(OS_WIN)
- DCHECK_NE(kind, GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED_NO_GL);
+ DCHECK_NE(kind, GPU_PROCESS_KIND_UNSANDBOXED_NO_GL);
#endif
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
base::BindOnce(&RunCallbackOnIO, kind, force_create,
@@ -834,7 +813,8 @@ bool GpuProcessHost::Init() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(GetGpuMainThreadFactory());
gpu::GpuPreferences gpu_preferences = GetGpuPreferencesFromCommandLine();
- GpuDataManagerImpl::GetInstance()->UpdateGpuPreferences(&gpu_preferences);
+ GpuDataManagerImpl::GetInstance()->UpdateGpuPreferences(
+ &gpu_preferences, GPU_PROCESS_KIND_SANDBOXED);
in_process_gpu_thread_.reset(GetGpuMainThreadFactory()(
InProcessChildThreadParams(
base::ThreadTaskRunnerHandle::Get(),
@@ -1055,7 +1035,7 @@ void GpuProcessHost::BindDiscardableMemoryRequest(
base::BindOnce(&BindDiscardableMemoryRequestOnUI, std::move(request)));
}
-GpuProcessHost::GpuProcessKind GpuProcessHost::kind() {
+GpuProcessKind GpuProcessHost::kind() {
return kind_;
}
@@ -1085,6 +1065,8 @@ bool GpuProcessHost::LaunchGpuProcess() {
#if defined(OS_LINUX)
int child_flags = gpu_launcher.empty() ? ChildProcessHost::CHILD_ALLOW_SELF
: ChildProcessHost::CHILD_NORMAL;
+#elif defined(OS_MACOSX)
+ int child_flags = ChildProcessHost::CHILD_GPU;
#else
int child_flags = ChildProcessHost::CHILD_NORMAL;
#endif
@@ -1138,7 +1120,8 @@ bool GpuProcessHost::LaunchGpuProcess() {
// TODO(kylechar): The command line flags added here should be based on
// |mode_|.
- GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line.get());
+ GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line.get(),
+ kind_);
// If specified, prepend a launcher program to the command line.
if (!gpu_launcher.empty())
diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h
index 1eba567f989..20974e3000f 100644
--- a/chromium/content/browser/gpu/gpu_process_host.h
+++ b/chromium/content/browser/gpu/gpu_process_host.h
@@ -57,12 +57,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
public IPC::Sender,
public viz::GpuHostImpl::Delegate {
public:
- enum GpuProcessKind {
- GPU_PROCESS_KIND_UNSANDBOXED_NO_GL, // Unsandboxed, no init GL bindings.
- GPU_PROCESS_KIND_SANDBOXED,
- GPU_PROCESS_KIND_COUNT
- };
-
static int GetGpuCrashCount();
// Creates a new GpuProcessHost (if |force_create| is turned on) or gets an
diff --git a/chromium/content/browser/histograms_internals_ui.cc b/chromium/content/browser/histograms_internals_ui.cc
index ef0a7767f98..276cc683491 100644
--- a/chromium/content/browser/histograms_internals_ui.cc
+++ b/chromium/content/browser/histograms_internals_ui.cc
@@ -36,7 +36,6 @@ WebUIDataSource* CreateHistogramsHTMLSource() {
source->AddResourcePath(kHistogramsUIJs, IDR_HISTOGRAMS_INTERNALS_JS);
source->SetDefaultResource(IDR_HISTOGRAMS_INTERNALS_HTML);
- source->UseGzip();
return source;
}
diff --git a/chromium/content/browser/idle/idle_browsertest.cc b/chromium/content/browser/idle/idle_browsertest.cc
new file mode 100644
index 00000000000..d4ede6c2842
--- /dev/null
+++ b/chromium/content/browser/idle/idle_browsertest.cc
@@ -0,0 +1,107 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/idle/idle_manager.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/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 "testing/gmock/include/gmock/gmock.h"
+
+using ::testing::NiceMock;
+
+namespace content {
+
+namespace {
+
+class MockIdleTimeProvider : public IdleManager::IdleTimeProvider {
+ public:
+ MockIdleTimeProvider() = default;
+ ~MockIdleTimeProvider() override = default;
+
+ MOCK_METHOD1(CalculateIdleState, ui::IdleState(base::TimeDelta));
+ MOCK_METHOD0(CalculateIdleTime, base::TimeDelta());
+ MOCK_METHOD0(CheckIdleStateIsLocked, bool());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockIdleTimeProvider);
+};
+
+class IdleTest : public ContentBrowserTest {
+ public:
+ IdleTest() = default;
+ ~IdleTest() override = default;
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ ContentBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitchASCII("enable-blink-features", "IdleDetection");
+ }
+};
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(IdleTest, Start) {
+ NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html"));
+
+ auto mock_time_provider = std::make_unique<NiceMock<MockIdleTimeProvider>>();
+ auto* rph = static_cast<RenderProcessHostImpl*>(
+ shell()->web_contents()->GetMainFrame()->GetProcess());
+ IdleManager* idle_mgr =
+ static_cast<StoragePartitionImpl*>(rph->GetStoragePartition())
+ ->GetIdleManager();
+
+ // Test that statuses are updated after idleDetector.start().
+ std::string script = R"(
+ (async () => {
+ let idleDetector = new IdleDetector({threshold: 60});
+ await idleDetector.start();
+ return new Promise(function(resolve) {
+ let states = [];
+ idleDetector.addEventListener('change', e => {
+ let {user, screen} = idleDetector.state;
+ states.push(`${user}-${screen}`)
+ if (states.length >= 3) {
+ let states_str = states.join(',');
+ resolve(states_str);
+ }
+ });
+ });
+ }) ();
+ )";
+
+ EXPECT_CALL(*mock_time_provider, CalculateIdleTime())
+ // Initial state of the system.
+ .WillOnce(testing::Return(base::TimeDelta::FromSeconds(0)))
+ // Simulates a user going idle.
+ .WillOnce(testing::Return(base::TimeDelta::FromSeconds(60)))
+ // Simulates a screen getting locked after the user goes idle.
+ .WillOnce(testing::Return(base::TimeDelta::FromSeconds(60)))
+ // Simulates a user going back to active.
+ .WillRepeatedly(testing::Return(base::TimeDelta::FromSeconds(0)));
+
+ EXPECT_CALL(*mock_time_provider, CheckIdleStateIsLocked())
+ // Initial state of the system.
+ .WillOnce(testing::Return(false))
+ // Simulates unlocked screen while user goes idle.
+ .WillOnce(testing::Return(false))
+ // Simulates a screen getting locked after the user goes idle.
+ .WillOnce(testing::Return(true))
+ // Simulates an unlocked screen as user goes back to active.
+ .WillRepeatedly(testing::Return(false));
+
+ idle_mgr->SetIdleTimeProviderForTest(std::move(mock_time_provider));
+
+ std::string result = EvalJs(shell(), script).ExtractString();
+ std::vector<std::string> states = base::SplitString(
+ result, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+ EXPECT_EQ("idle-unlocked", states.at(0));
+ EXPECT_EQ("idle-locked", states.at(1));
+ EXPECT_EQ("active-unlocked", states.at(2));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/idle/idle_manager.cc b/chromium/content/browser/idle/idle_manager.cc
index be8e84b728b..5a77c238747 100644
--- a/chromium/content/browser/idle/idle_manager.cc
+++ b/chromium/content/browser/idle/idle_manager.cc
@@ -75,8 +75,7 @@ IdleManager::~IdleManager() {
}
}
-void IdleManager::CreateService(blink::mojom::IdleManagerRequest request,
- const url::Origin& origin) {
+void IdleManager::CreateService(blink::mojom::IdleManagerRequest request) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bindings_.AddBinding(this, std::move(request));
diff --git a/chromium/content/browser/idle/idle_manager.h b/chromium/content/browser/idle/idle_manager.h
index 68cd45e9bbf..81d93bf0de7 100644
--- a/chromium/content/browser/idle/idle_manager.h
+++ b/chromium/content/browser/idle/idle_manager.h
@@ -50,9 +50,7 @@ class CONTENT_EXPORT IdleManager : public blink::mojom::IdleManager {
IdleManager();
~IdleManager() override;
- // TODO: Origin for permission check; needed?
- void CreateService(blink::mojom::IdleManagerRequest request,
- const url::Origin& origin);
+ void CreateService(blink::mojom::IdleManagerRequest request);
// blink.mojom.IdleManager:
void AddMonitor(base::TimeDelta threshold,
diff --git a/chromium/content/browser/idle/idle_manager_unittest.cc b/chromium/content/browser/idle/idle_manager_unittest.cc
index 22e0deddf4e..772bb2f8b4f 100644
--- a/chromium/content/browser/idle/idle_manager_unittest.cc
+++ b/chromium/content/browser/idle/idle_manager_unittest.cc
@@ -77,9 +77,7 @@ TEST_F(IdleManagerTest, AddMonitor) {
auto* mock = new NiceMock<MockIdleTimeProvider>();
impl->SetIdleTimeProviderForTest(base::WrapUnique(mock));
blink::mojom::IdleManagerPtr service_ptr;
- GURL url("http://google.com");
- impl->CreateService(mojo::MakeRequest(&service_ptr),
- url::Origin::Create(url));
+ impl->CreateService(mojo::MakeRequest(&service_ptr));
blink::mojom::IdleMonitorPtr monitor_ptr;
blink::mojom::IdleMonitorRequest monitor_request =
@@ -119,10 +117,7 @@ TEST_F(IdleManagerTest, Idle) {
auto impl = std::make_unique<IdleManager>();
auto* mock = new NiceMock<MockIdleTimeProvider>();
impl->SetIdleTimeProviderForTest(base::WrapUnique(mock));
-
- GURL url("http://google.com");
- impl->CreateService(mojo::MakeRequest(&service_ptr),
- url::Origin::Create(url));
+ impl->CreateService(mojo::MakeRequest(&service_ptr));
blink::mojom::IdleMonitorPtr monitor_ptr;
auto monitor_request = mojo::MakeRequest(&monitor_ptr);
@@ -185,10 +180,7 @@ TEST_F(IdleManagerTest, UnlockingScreen) {
auto impl = std::make_unique<IdleManager>();
auto* mock = new NiceMock<MockIdleTimeProvider>();
impl->SetIdleTimeProviderForTest(base::WrapUnique(mock));
-
- GURL url("http://google.com");
- impl->CreateService(mojo::MakeRequest(&service_ptr),
- url::Origin::Create(url));
+ impl->CreateService(mojo::MakeRequest(&service_ptr));
blink::mojom::IdleMonitorPtr monitor_ptr;
auto monitor_request = mojo::MakeRequest(&monitor_ptr);
@@ -237,10 +229,7 @@ TEST_F(IdleManagerTest, LockingScreen) {
auto impl = std::make_unique<IdleManager>();
auto* mock = new NiceMock<MockIdleTimeProvider>();
impl->SetIdleTimeProviderForTest(base::WrapUnique(mock));
-
- GURL url("http://google.com");
- impl->CreateService(mojo::MakeRequest(&service_ptr),
- url::Origin::Create(url));
+ impl->CreateService(mojo::MakeRequest(&service_ptr));
blink::mojom::IdleMonitorPtr monitor_ptr;
auto monitor_request = mojo::MakeRequest(&monitor_ptr);
@@ -289,10 +278,7 @@ TEST_F(IdleManagerTest, LockingScreenThenIdle) {
auto impl = std::make_unique<IdleManager>();
auto* mock = new NiceMock<MockIdleTimeProvider>();
impl->SetIdleTimeProviderForTest(base::WrapUnique(mock));
-
- GURL url("http://google.com");
- impl->CreateService(mojo::MakeRequest(&service_ptr),
- url::Origin::Create(url));
+ impl->CreateService(mojo::MakeRequest(&service_ptr));
blink::mojom::IdleMonitorPtr monitor_ptr;
auto monitor_request = mojo::MakeRequest(&monitor_ptr);
@@ -364,10 +350,7 @@ TEST_F(IdleManagerTest, LockingScreenAfterIdle) {
auto impl = std::make_unique<IdleManager>();
auto* mock = new NiceMock<MockIdleTimeProvider>();
impl->SetIdleTimeProviderForTest(base::WrapUnique(mock));
-
- GURL url("http://google.com");
- impl->CreateService(mojo::MakeRequest(&service_ptr),
- url::Origin::Create(url));
+ impl->CreateService(mojo::MakeRequest(&service_ptr));
blink::mojom::IdleMonitorPtr monitor_ptr;
auto monitor_request = mojo::MakeRequest(&monitor_ptr);
@@ -378,7 +361,7 @@ TEST_F(IdleManagerTest, LockingScreenAfterIdle) {
{
base::RunLoop loop;
- // Simulates a user going idle, but with the screen still unlocked.
+ // Initial state of the system.
EXPECT_CALL(*mock, CalculateIdleTime())
.WillRepeatedly(testing::Return(base::TimeDelta::FromSeconds(0)));
EXPECT_CALL(*mock, CheckIdleStateIsLocked())
@@ -445,9 +428,7 @@ TEST_F(IdleManagerTest, RemoveMonitorStopsPolling) {
impl->SetIdleTimeProviderForTest(base::WrapUnique(mock));
blink::mojom::IdleManagerPtr service_ptr;
- GURL url("http://google.com");
- impl->CreateService(mojo::MakeRequest(&service_ptr),
- url::Origin::Create(url));
+ impl->CreateService(mojo::MakeRequest(&service_ptr));
blink::mojom::IdleMonitorPtr monitor_ptr;
blink::mojom::IdleMonitorRequest monitor_request =
@@ -487,9 +468,7 @@ TEST_F(IdleManagerTest, Threshold) {
auto* mock = new NiceMock<MockIdleTimeProvider>();
impl->SetIdleTimeProviderForTest(base::WrapUnique(mock));
blink::mojom::IdleManagerPtr service_ptr;
- GURL url("http://google.com");
- impl->CreateService(mojo::MakeRequest(&service_ptr),
- url::Origin::Create(url));
+ impl->CreateService(mojo::MakeRequest(&service_ptr));
blink::mojom::IdleMonitorPtr monitor_ptr;
blink::mojom::IdleMonitorRequest monitor_request =
@@ -519,9 +498,7 @@ TEST_F(IdleManagerTest, BadThreshold) {
auto* mock = new NiceMock<MockIdleTimeProvider>();
impl->SetIdleTimeProviderForTest(base::WrapUnique(mock));
blink::mojom::IdleManagerPtr service_ptr;
- GURL url("http://google.com");
- impl->CreateService(mojo::MakeRequest(&service_ptr),
- url::Origin::Create(url));
+ impl->CreateService(mojo::MakeRequest(&service_ptr));
blink::mojom::IdleMonitorPtr monitor_ptr;
blink::mojom::IdleMonitorRequest monitor_request =
diff --git a/chromium/content/browser/indexed_db/database_impl.cc b/chromium/content/browser/indexed_db/database_impl.cc
index a0b478f1ed2..64f2e0bbcdf 100644
--- a/chromium/content/browser/indexed_db/database_impl.cc
+++ b/chromium/content/browser/indexed_db/database_impl.cc
@@ -33,6 +33,7 @@ class IndexedDBKeyRange;
namespace content {
namespace {
+const char kBadTransactionMode[] = "Bad transaction mode";
const char kTransactionAlreadyExists[] = "Transaction already exists";
} // namespace
@@ -74,6 +75,7 @@ void DatabaseImpl::RenameObjectStore(int64_t transaction_id,
if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
mojo::ReportBadMessage(
"RenameObjectStore must be called from a version change transaction.");
+ return;
}
// Note: This doesn't schedule a task on the transaction because version
@@ -91,6 +93,12 @@ void DatabaseImpl::CreateTransaction(
if (!connection_->IsConnected())
return;
+ if (mode != blink::mojom::IDBTransactionMode::ReadOnly &&
+ mode != blink::mojom::IDBTransactionMode::ReadWrite) {
+ mojo::ReportBadMessage(kBadTransactionMode);
+ return;
+ }
+
if (connection_->GetTransaction(transaction_id)) {
mojo::ReportBadMessage(kTransactionAlreadyExists);
return;
@@ -176,30 +184,38 @@ void DatabaseImpl::Get(
key_only, callbacks);
}
-void DatabaseImpl::GetAll(
- int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKeyRange& key_range,
- bool key_only,
- int64_t max_count,
- blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
+void DatabaseImpl::GetAll(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ bool key_only,
+ int64_t max_count,
+ blink::mojom::IDBDatabase::GetAllCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- scoped_refptr<IndexedDBCallbacks> callbacks(
- new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
- std::move(callbacks_info), idb_runner_));
- if (!connection_->IsConnected())
+ if (!connection_->IsConnected()) {
+ IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError,
+ "Unknown error");
+ std::move(callback).Run(
+ blink::mojom::IDBDatabaseGetAllResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
return;
+ }
IndexedDBTransaction* transaction =
connection_->GetTransaction(transaction_id);
- if (!transaction)
+ if (!transaction) {
+ IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError,
+ "Unknown error");
+ std::move(callback).Run(
+ blink::mojom::IDBDatabaseGetAllResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
return;
+ }
connection_->database()->GetAll(
- transaction, object_store_id, index_id,
+ dispatcher_host_->AsWeakPtr(), transaction, object_store_id, index_id,
std::make_unique<IndexedDBKeyRange>(key_range), key_only, max_count,
- std::move(callbacks));
+ std::move(callback));
}
void DatabaseImpl::SetIndexKeys(
@@ -219,6 +235,7 @@ void DatabaseImpl::SetIndexKeys(
if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
mojo::ReportBadMessage(
"SetIndexKeys must be called from a version change transaction.");
+ return;
}
connection_->database()->SetIndexKeys(
@@ -241,6 +258,7 @@ void DatabaseImpl::SetIndexesReady(int64_t transaction_id,
if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
mojo::ReportBadMessage(
"SetIndexesReady must be called from a version change transaction.");
+ return;
}
connection_->database()->SetIndexesReady(transaction, object_store_id,
@@ -273,6 +291,7 @@ void DatabaseImpl::OpenCursor(
mojo::ReportBadMessage(
"OpenCursor with |Preemptive| task type must be called from a version "
"change transaction.");
+ return;
}
connection_->database()->OpenCursor(
@@ -384,6 +403,7 @@ void DatabaseImpl::CreateIndex(int64_t transaction_id,
if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
mojo::ReportBadMessage(
"CreateIndex must be called from a version change transaction.");
+ return;
}
connection_->database()->CreateIndex(transaction, object_store_id, index_id,
@@ -405,6 +425,7 @@ void DatabaseImpl::DeleteIndex(int64_t transaction_id,
if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
mojo::ReportBadMessage(
"DeleteIndex must be called from a version change transaction.");
+ return;
}
connection_->database()->DeleteIndex(transaction, object_store_id, index_id);
@@ -426,6 +447,7 @@ void DatabaseImpl::RenameIndex(int64_t transaction_id,
if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
mojo::ReportBadMessage(
"RenameIndex must be called from a version change transaction.");
+ return;
}
connection_->database()->RenameIndex(transaction, object_store_id, index_id,
diff --git a/chromium/content/browser/indexed_db/database_impl.h b/chromium/content/browser/indexed_db/database_impl.h
index 8a3e3a16470..e1bb4178442 100644
--- a/chromium/content/browser/indexed_db/database_impl.h
+++ b/chromium/content/browser/indexed_db/database_impl.h
@@ -66,7 +66,7 @@ class DatabaseImpl : public blink::mojom::IDBDatabase {
const blink::IndexedDBKeyRange& key_range,
bool key_only,
int64_t max_count,
- blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override;
+ blink::mojom::IDBDatabase::GetAllCallback callback) override;
void SetIndexKeys(
int64_t transaction_id,
int64_t object_store_id,
diff --git a/chromium/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc
index 811f106aaea..c2190ffaacc 100644
--- a/chromium/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc
@@ -23,6 +23,7 @@ namespace {
class RegistryTestMockFactory : public MockIndexedDBFactory {
public:
RegistryTestMockFactory() : duplicate_calls_(false) {}
+ ~RegistryTestMockFactory() override = default;
void ReportOutstandingBlobs(const url::Origin& origin,
bool blobs_outstanding) override {
@@ -50,8 +51,6 @@ class RegistryTestMockFactory : public MockIndexedDBFactory {
}
private:
- ~RegistryTestMockFactory() override {}
-
std::set<url::Origin> origins_;
bool duplicate_calls_;
@@ -67,6 +66,7 @@ class MockIDBBackingStore : public IndexedDBFakeBackingStore {
base::SequencedTaskRunner* task_runner)
: IndexedDBFakeBackingStore(factory, task_runner),
duplicate_calls_(false) {}
+ ~MockIDBBackingStore() override = default;
void ReportBlobUnused(int64_t database_id, int64_t blob_key) override {
unused_blobs_.insert(std::make_pair(database_id, blob_key));
@@ -82,9 +82,6 @@ class MockIDBBackingStore : public IndexedDBFakeBackingStore {
const KeyPairSet& unused_blobs() const { return unused_blobs_; }
- protected:
- ~MockIDBBackingStore() override {}
-
private:
KeyPairSet unused_blobs_;
bool duplicate_calls_;
@@ -118,8 +115,8 @@ class IndexedDBActiveBlobRegistryTest : public testing::Test {
private:
base::test::ScopedTaskEnvironment task_environment_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
- scoped_refptr<RegistryTestMockFactory> factory_;
- scoped_refptr<MockIDBBackingStore> backing_store_;
+ std::unique_ptr<RegistryTestMockFactory> factory_;
+ std::unique_ptr<MockIDBBackingStore> backing_store_;
std::unique_ptr<IndexedDBActiveBlobRegistry> registry_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBActiveBlobRegistryTest);
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 7fd762fcb12..3e2ba42ba45 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -30,6 +30,7 @@
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_data_format_version.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
+#include "content/browser/indexed_db/indexed_db_factory.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/indexed_db_leveldb_operations.h"
#include "content/browser/indexed_db/indexed_db_metadata_coding.h"
@@ -526,9 +527,7 @@ IndexedDBBackingStore::IndexedDBBackingStore(
origin_identifier_(ComputeOriginIdentifier(origin)),
task_runner_(task_runner),
db_(std::move(db)),
- active_blob_registry_(this),
- committing_transaction_count_(0),
- weak_factory_(this) {
+ active_blob_registry_(this) {
if (backing_store_mode == Mode::kInMemory) {
indexed_db_factory_ = nullptr;
blob_path_ = FilePath();
@@ -1326,7 +1325,7 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
int64_t database_id,
base::WeakPtr<IndexedDBBackingStore> backing_store,
WriteDescriptorVec* blobs,
- scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback) {
+ IndexedDBBackingStore::BlobWriteCallback callback) {
auto writer = base::WrapRefCounted(new ChainedBlobWriterImpl(
database_id, backing_store, std::move(callback)));
writer->blobs_.swap(*blobs);
@@ -1358,7 +1357,7 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
++iter_;
WriteNextFile();
} else {
- callback_->Run(BlobWriteResult::FAILURE_ASYNC);
+ std::move(callback_).Run(BlobWriteResult::FAILURE_ASYNC);
}
}
@@ -1370,14 +1369,13 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
}
private:
- ChainedBlobWriterImpl(
- int64_t database_id,
- base::WeakPtr<IndexedDBBackingStore> backing_store,
- scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback)
+ ChainedBlobWriterImpl(int64_t database_id,
+ base::WeakPtr<IndexedDBBackingStore> backing_store,
+ IndexedDBBackingStore::BlobWriteCallback callback)
: waiting_for_callback_(false),
database_id_(database_id),
backing_store_(backing_store),
- callback_(callback),
+ callback_(std::move(callback)),
aborted_(false) {}
~ChainedBlobWriterImpl() override {}
@@ -1389,12 +1387,12 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
}
if (iter_ == blobs_.end()) {
DCHECK(!self_ref_.get());
- callback_->Run(BlobWriteResult::SUCCESS_ASYNC);
+ std::move(callback_).Run(BlobWriteResult::SUCCESS_ASYNC);
return;
} else {
if (!backing_store_ ||
!backing_store_->WriteBlobFile(database_id_, *iter_, this)) {
- callback_->Run(BlobWriteResult::FAILURE_ASYNC);
+ std::move(callback_).Run(BlobWriteResult::FAILURE_ASYNC);
return;
}
waiting_for_callback_ = true;
@@ -1410,7 +1408,7 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
// Callback result is useless as call stack is no longer transaction's
// operations queue. Errors are instead handled in
// IndexedDBTransaction::BlobWriteComplete.
- scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_;
+ IndexedDBBackingStore::BlobWriteCallback callback_;
std::unique_ptr<FileWriterDelegate> delegate_;
bool aborted_;
@@ -2051,11 +2049,11 @@ IndexedDBBackingStore::Cursor::Cursor(
}
IndexedDBBackingStore::Cursor::Cursor(
- scoped_refptr<IndexedDBBackingStore> backing_store,
+ IndexedDBBackingStore* backing_store,
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
const CursorOptions& cursor_options)
- : backing_store_(backing_store.get()),
+ : backing_store_(backing_store),
transaction_(transaction),
database_id_(database_id),
cursor_options_(cursor_options) {}
@@ -2312,7 +2310,7 @@ const IndexedDBKey& IndexedDBBackingStore::Cursor::primary_key() const {
class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor {
public:
ObjectStoreKeyCursorImpl(
- scoped_refptr<IndexedDBBackingStore> backing_store,
+ IndexedDBBackingStore* backing_store,
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
@@ -2389,7 +2387,7 @@ bool ObjectStoreKeyCursorImpl::LoadCurrentRow(Status* s) {
class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor {
public:
ObjectStoreCursorImpl(
- scoped_refptr<IndexedDBBackingStore> backing_store,
+ IndexedDBBackingStore* backing_store,
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
@@ -2463,7 +2461,7 @@ bool ObjectStoreCursorImpl::LoadCurrentRow(Status* s) {
class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor {
public:
IndexKeyCursorImpl(
- scoped_refptr<IndexedDBBackingStore> backing_store,
+ IndexedDBBackingStore* backing_store,
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
@@ -2580,7 +2578,7 @@ bool IndexKeyCursorImpl::LoadCurrentRow(Status* s) {
class IndexCursorImpl : public IndexedDBBackingStore::Cursor {
public:
IndexCursorImpl(
- scoped_refptr<IndexedDBBackingStore> backing_store,
+ IndexedDBBackingStore* backing_store,
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
@@ -2808,12 +2806,6 @@ IndexedDBBackingStore::OpenIndexCursor(
return std::move(cursor);
}
-void IndexedDBBackingStore::StartPreCloseTasks() {
- DCHECK(pre_close_task_queue_);
- pre_close_task_queue_->Start(base::BindOnce(
- &IndexedDBBackingStore::GetCompleteMetadata, base::Unretained(this)));
-}
-
bool IndexedDBBackingStore::IsBlobCleanupPending() {
return journal_cleaning_timer_.IsRunning();
}
@@ -2960,7 +2952,7 @@ void IndexedDBBackingStore::Transaction::PartitionBlobsToRemove(
}
Status IndexedDBBackingStore::Transaction::CommitPhaseOne(
- scoped_refptr<BlobWriteCallback> callback) {
+ BlobWriteCallback callback) {
IDB_TRACE("IndexedDBBackingStore::Transaction::CommitPhaseOne");
DCHECK(transaction_.get());
DCHECK(backing_store_->task_runner()->RunsTasksInCurrentSequence());
@@ -2990,9 +2982,9 @@ Status IndexedDBBackingStore::Transaction::CommitPhaseOne(
if (!new_files_to_write.empty()) {
// This kicks off the writes of the new blobs, if any.
// This call will zero out new_blob_entries and new_files_to_write.
- WriteNewBlobs(&new_blob_entries, &new_files_to_write, callback);
+ WriteNewBlobs(&new_blob_entries, &new_files_to_write, std::move(callback));
} else {
- return callback->Run(BlobWriteResult::SUCCESS_SYNC);
+ return std::move(callback).Run(BlobWriteResult::SUCCESS_SYNC);
}
return Status::OK();
@@ -3093,49 +3085,10 @@ Status IndexedDBBackingStore::Transaction::CommitPhaseTwo() {
return s;
}
-
-class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper
- : public IndexedDBBackingStore::BlobWriteCallback {
- public:
- BlobWriteCallbackWrapper(
- base::WeakPtr<IndexedDBBackingStore::Transaction> transaction,
- void* tracing_end_ptr,
- scoped_refptr<BlobWriteCallback> callback)
- : transaction_(std::move(transaction)),
- tracing_end_ptr_(tracing_end_ptr),
- callback_(callback) {}
- Status Run(BlobWriteResult result) override {
- DCHECK_NE(result, BlobWriteResult::SUCCESS_SYNC);
- IDB_ASYNC_TRACE_END("IndexedDBBackingStore::Transaction::WriteNewBlobs",
- tracing_end_ptr_);
- Status leveldb_result = callback_->Run(result);
- switch (result) {
- case BlobWriteResult::FAILURE_ASYNC:
- break;
- case BlobWriteResult::SUCCESS_ASYNC:
- case BlobWriteResult::SUCCESS_SYNC:
- if (transaction_)
- transaction_->chained_blob_writer_ = nullptr;
- break;
- }
- return leveldb_result;
- }
-
- private:
- ~BlobWriteCallbackWrapper() override {}
- friend class base::RefCounted<IndexedDBBackingStore::BlobWriteCallback>;
-
- base::WeakPtr<IndexedDBBackingStore::Transaction> transaction_;
- const void* const tracing_end_ptr_;
- scoped_refptr<BlobWriteCallback> callback_;
-
- DISALLOW_COPY_AND_ASSIGN(BlobWriteCallbackWrapper);
-};
-
void IndexedDBBackingStore::Transaction::WriteNewBlobs(
BlobEntryKeyValuePairVec* new_blob_entries,
WriteDescriptorVec* new_files_to_write,
- scoped_refptr<BlobWriteCallback> callback) {
+ BlobWriteCallback callback) {
IDB_ASYNC_TRACE_BEGIN("IndexedDBBackingStore::Transaction::WriteNewBlobs",
this);
DCHECK(!new_files_to_write->empty());
@@ -3153,7 +3106,27 @@ void IndexedDBBackingStore::Transaction::WriteNewBlobs(
// can be destructed before the callback is triggered.
chained_blob_writer_ = ChainedBlobWriterImpl::Create(
database_id_, backing_store_->AsWeakPtr(), new_files_to_write,
- new BlobWriteCallbackWrapper(ptr_factory_.GetWeakPtr(), this, callback));
+ base::BindOnce(
+ [](base::WeakPtr<IndexedDBBackingStore::Transaction> transaction,
+ void* tracing_end_ptr, BlobWriteCallback final_callback,
+ BlobWriteResult result) {
+ DCHECK_NE(result, BlobWriteResult::SUCCESS_SYNC);
+ IDB_ASYNC_TRACE_END(
+ "IndexedDBBackingStore::Transaction::WriteNewBlobs",
+ tracing_end_ptr);
+ Status leveldb_result = std::move(final_callback).Run(result);
+ switch (result) {
+ case BlobWriteResult::FAILURE_ASYNC:
+ break;
+ case BlobWriteResult::SUCCESS_ASYNC:
+ case BlobWriteResult::SUCCESS_SYNC:
+ if (transaction)
+ transaction->chained_blob_writer_ = nullptr;
+ break;
+ }
+ return leveldb_result;
+ },
+ ptr_factory_.GetWeakPtr(), this, std::move(callback)));
}
void IndexedDBBackingStore::Transaction::Rollback() {
diff --git a/chromium/content/browser/indexed_db/indexed_db_backing_store.h b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
index a7e986448c5..411b1bd3b0e 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
@@ -27,10 +27,8 @@
#include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
#include "content/browser/indexed_db/indexed_db_blob_info.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
-#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
-#include "content/browser/indexed_db/scopes/disjoint_range_lock_manager.h"
#include "content/common/content_export.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
@@ -72,8 +70,7 @@ enum class V2SchemaCorruptionStatus {
// All interaction with this class should be done on the task runner given to
// Open.
-class CONTENT_EXPORT IndexedDBBackingStore
- : public base::RefCounted<IndexedDBBackingStore> {
+class CONTENT_EXPORT IndexedDBBackingStore {
public:
class CONTENT_EXPORT Comparator : public LevelDBComparator {
public:
@@ -105,16 +102,8 @@ class CONTENT_EXPORT IndexedDBBackingStore
enum class BlobWriteResult { FAILURE_ASYNC, SUCCESS_ASYNC, SUCCESS_SYNC };
- class BlobWriteCallback : public base::RefCounted<BlobWriteCallback> {
- public:
- // TODO(dmurph): Make all calls to this method async after measuring
- // performance.
- virtual leveldb::Status Run(BlobWriteResult result) = 0;
-
- protected:
- friend class base::RefCounted<BlobWriteCallback>;
- virtual ~BlobWriteCallback() {}
- };
+ using BlobWriteCallback = base::OnceCallback<leveldb::Status(
+ IndexedDBBackingStore::BlobWriteResult result)>;
class BlobChangeRecord {
public:
@@ -150,7 +139,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
// files should be cleaned up.
// The callback will be called eventually on success or failure, or
// immediately if phase one is complete due to lack of any blobs to write.
- virtual leveldb::Status CommitPhaseOne(scoped_refptr<BlobWriteCallback>);
+ virtual leveldb::Status CommitPhaseOne(BlobWriteCallback callback);
// CommitPhaseTwo is called once the blob files (if any) have been written
// to disk, and commits the actual transaction to the backing store,
@@ -245,7 +234,6 @@ class CONTENT_EXPORT IndexedDBBackingStore
typedef std::vector<WriteDescriptor> WriteDescriptorVec;
private:
- class BlobWriteCallbackWrapper;
// Called by CommitPhaseOne: Identifies the blob entries to write and adds
// them to the primary blob journal directly (i.e. not as part of the
@@ -265,13 +253,16 @@ class CONTENT_EXPORT IndexedDBBackingStore
// eventually on success or failure.
void WriteNewBlobs(BlobEntryKeyValuePairVec* new_blob_entries,
WriteDescriptorVec* new_files_to_write,
- scoped_refptr<BlobWriteCallback> callback);
+ BlobWriteCallback callback);
// Called by CommitPhaseTwo: Partition blob references in blobs_to_remove_
// into live (active references) and dead (no references).
void PartitionBlobsToRemove(BlobJournalType* dead_blobs,
BlobJournalType* live_blobs) const;
+ // The raw pointer is not inherently safe, but IndexedDB destroys
+ // transactions & connections before destroying the backing store.
+ // TODO(dmurph): Convert to WeakPtr. https://crbug.com/960992
IndexedDBBackingStore* backing_store_;
scoped_refptr<LevelDBTransaction> transaction_;
std::map<std::string, std::unique_ptr<BlobChangeRecord>> blob_change_map_;
@@ -342,7 +333,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
virtual bool LoadCurrentRow(leveldb::Status* s) = 0;
protected:
- Cursor(scoped_refptr<IndexedDBBackingStore> backing_store,
+ Cursor(IndexedDBBackingStore* backing_store,
Transaction* transaction,
int64_t database_id,
const CursorOptions& cursor_options);
@@ -355,7 +346,13 @@ class CONTENT_EXPORT IndexedDBBackingStore
bool IsPastBounds() const;
bool HaveEnteredRange() const;
+ // The raw pointer is not inherently safe, but IndexedDB destroys
+ // transactions & connections before destroying the backing store.
+ // TODO(dmurph): Convert to WeakPtr. https://crbug.com/960992
IndexedDBBackingStore* backing_store_;
+ // The raw pointer is not inherently safe, but IndexedDB destroys
+ // transactions before cursors.
+ // TODO(dmurph): Convert to WeakPtr. https://crbug.com/960992
Transaction* transaction_;
int64_t database_id_;
const CursorOptions cursor_options_;
@@ -401,6 +398,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
const base::FilePath& blob_path,
std::unique_ptr<LevelDBDatabase> db,
base::SequencedTaskRunner* task_runner);
+ virtual ~IndexedDBBackingStore();
// Initializes the backing store. This must be called before doing any
// operations or method calls on this object.
@@ -409,7 +407,6 @@ class CONTENT_EXPORT IndexedDBBackingStore
const url::Origin& origin() const { return origin_; }
IndexedDBFactory* factory() const { return indexed_db_factory_; }
base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); }
- base::OneShotTimer* close_timer() { return &close_timer_; }
IndexedDBActiveBlobRegistry* active_blob_registry() {
return &active_blob_registry_;
}
@@ -534,17 +531,6 @@ class CONTENT_EXPORT IndexedDBBackingStore
blink::mojom::IDBCursorDirection,
leveldb::Status*);
- IndexedDBPreCloseTaskQueue* pre_close_task_queue() {
- return pre_close_task_queue_.get();
- }
-
- void SetPreCloseTaskList(std::unique_ptr<IndexedDBPreCloseTaskQueue> list) {
- pre_close_task_queue_ = std::move(list);
- }
-
- // |pre_close_task_queue()| must not be null.
- void StartPreCloseTasks();
-
LevelDBDatabase* db() { return db_.get(); }
const std::string& origin_identifier() { return origin_identifier_; }
@@ -579,12 +565,8 @@ class CONTENT_EXPORT IndexedDBBackingStore
return weak_factory_.GetWeakPtr();
}
- DisjointRangeLockManager* lock_manager() { return &lock_manager_; }
-
protected:
- friend class base::RefCounted<IndexedDBBackingStore>;
- virtual ~IndexedDBBackingStore();
-
+ friend class IndexedDBOriginState;
leveldb::Status AnyDatabaseContainsBlobs(LevelDBTransaction* transaction,
bool* blobs_exist);
@@ -671,20 +653,16 @@ class CONTENT_EXPORT IndexedDBBackingStore
// Whenever blobs are registered in active_blob_registry_,
// indexed_db_factory_ will hold a reference to this backing store.
IndexedDBActiveBlobRegistry active_blob_registry_;
- base::OneShotTimer close_timer_;
- std::unique_ptr<IndexedDBPreCloseTaskQueue> pre_close_task_queue_;
// Incremented whenever a transaction starts committing, decremented when
// complete. While > 0, temporary journal entries may exist so out-of-band
// journal cleaning must be deferred.
- size_t committing_transaction_count_;
-
- DisjointRangeLockManager lock_manager_ = {kIndexedDBLockLevelCount};
+ size_t committing_transaction_count_ = 0;
#if DCHECK_IS_ON()
bool initialized_ = false;
#endif
- base::WeakPtrFactory<IndexedDBBackingStore> weak_factory_;
+ base::WeakPtrFactory<IndexedDBBackingStore> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStore);
};
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 60b09d2bbaa..0f5d533834e 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
@@ -27,6 +27,7 @@
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/indexed_db_leveldb_operations.h"
#include "content/browser/indexed_db/indexed_db_metadata_coding.h"
+#include "content/browser/indexed_db/indexed_db_origin_state.h"
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -73,6 +74,7 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
std::move(db),
task_runner),
database_id_(0) {}
+ ~TestableIndexedDBBackingStore() override = default;
const std::vector<IndexedDBBackingStore::Transaction::WriteDescriptor>&
writes() const {
@@ -87,8 +89,6 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
}
protected:
- ~TestableIndexedDBBackingStore() override {}
-
bool WriteBlobFile(
int64_t database_id,
const Transaction::WriteDescriptor& descriptor,
@@ -128,36 +128,24 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
DISALLOW_COPY_AND_ASSIGN(TestableIndexedDBBackingStore);
};
+// Factory subclass to allow the test to use the
+// TestableIndexedDBBackingStore subclass.
class TestIDBFactory : public IndexedDBFactoryImpl {
public:
explicit TestIDBFactory(IndexedDBContextImpl* idb_context)
: IndexedDBFactoryImpl(idb_context,
indexed_db::GetDefaultLevelDBFactory(),
base::DefaultClock::GetInstance()) {}
-
- scoped_refptr<TestableIndexedDBBackingStore> OpenBackingStoreForTest(
- const Origin& origin) {
- IndexedDBDataLossInfo data_loss_info;
- bool disk_full;
- leveldb::Status s;
- scoped_refptr<IndexedDBBackingStore> backing_store;
- std::tie(backing_store, s, data_loss_info, disk_full) =
- OpenBackingStore(origin, context()->data_path());
- scoped_refptr<TestableIndexedDBBackingStore> testable_store =
- static_cast<TestableIndexedDBBackingStore*>(backing_store.get());
- return testable_store;
- }
+ ~TestIDBFactory() override = default;
protected:
- ~TestIDBFactory() override {}
-
- scoped_refptr<IndexedDBBackingStore> CreateBackingStore(
+ std::unique_ptr<IndexedDBBackingStore> CreateBackingStore(
IndexedDBBackingStore::Mode backing_store_mode,
const url::Origin& origin,
const base::FilePath& blob_path,
std::unique_ptr<LevelDBDatabase> db,
base::SequencedTaskRunner* task_runner) override {
- return base::MakeRefCounted<TestableIndexedDBBackingStore>(
+ return std::make_unique<TestableIndexedDBBackingStore>(
backing_store_mode, this, origin, blob_path, std::move(db),
task_runner);
}
@@ -174,39 +162,16 @@ class IndexedDBBackingStoreTest : public testing::Test {
quota_manager_proxy_(
base::MakeRefCounted<MockQuotaManagerProxy>(nullptr, nullptr)) {}
- void CreateFactoryAndBackingStore() {
- // Factory and backing store must be created on IDB task runner.
- base::RunLoop loop;
- idb_context_->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- const Origin origin = Origin::Create(GURL("http://localhost:81"));
- idb_factory_ =
- base::MakeRefCounted<TestIDBFactory>(idb_context_.get());
- backing_store_ = idb_factory_->OpenBackingStoreForTest(origin);
- loop.Quit();
- }));
- loop.Run();
- }
-
- void DestroyFactoryAndBackingStore() {
- // Factory and backing store must be destroyed on IDB task runner
- base::RunLoop loop;
- idb_context_->TaskRunner()->PostTask(FROM_HERE,
- base::BindLambdaForTesting([&]() {
- idb_factory_.reset();
- backing_store_.reset();
- loop.Quit();
- }));
- loop.Run();
- }
-
void SetUp() override {
special_storage_policy_->SetAllUnlimited(true);
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
idb_context_ = base::MakeRefCounted<IndexedDBContextImpl>(
temp_dir_.GetPath(), special_storage_policy_, quota_manager_proxy_,
- indexed_db::GetDefaultLevelDBFactory());
+ indexed_db::GetDefaultLevelDBFactory(),
+ base::DefaultClock::GetInstance());
+ idb_context_->SetTaskRunnerForTesting(
+ base::SequencedTaskRunnerHandle::Get());
CreateFactoryAndBackingStore();
@@ -218,15 +183,34 @@ class IndexedDBBackingStoreTest : public testing::Test {
key2_ = IndexedDBKey(ASCIIToUTF16("key2"));
}
+ void CreateFactoryAndBackingStore() {
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
+ idb_factory_ = std::make_unique<TestIDBFactory>(idb_context_.get());
+
+ leveldb::Status s;
+ std::tie(origin_state_handle_, s, std::ignore, std::ignore) =
+ idb_factory_->GetOrOpenOriginFactory(origin, idb_context_->data_path());
+ if (!origin_state_handle_.IsHeld()) {
+ backing_store_ = nullptr;
+ return;
+ }
+ backing_store_ = static_cast<TestableIndexedDBBackingStore*>(
+ origin_state_handle_.origin_state()->backing_store());
+ }
+
+ void DestroyFactoryAndBackingStore() {
+ origin_state_handle_.Release();
+ idb_factory_.reset();
+ backing_store_ = nullptr;
+ }
+
void TearDown() override {
DestroyFactoryAndBackingStore();
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
}
- TestableIndexedDBBackingStore* backing_store() const {
- return backing_store_.get();
- }
+ TestableIndexedDBBackingStore* backing_store() { return backing_store_; }
protected:
TestBrowserThreadBundle thread_bundle_;
@@ -235,9 +219,10 @@ class IndexedDBBackingStoreTest : public testing::Test {
scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
scoped_refptr<IndexedDBContextImpl> idb_context_;
- scoped_refptr<TestIDBFactory> idb_factory_;
+ std::unique_ptr<TestIDBFactory> idb_factory_;
- scoped_refptr<TestableIndexedDBBackingStore> backing_store_;
+ IndexedDBOriginStateHandle origin_state_handle_;
+ TestableIndexedDBBackingStore* backing_store_ = nullptr;
// Sample keys and values that are consistent.
IndexedDBKey key1_;
@@ -370,28 +355,30 @@ class IndexedDBBackingStoreTestWithBlobs : public IndexedDBBackingStoreTest {
DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTestWithBlobs);
};
-class TestCallback : public IndexedDBBackingStore::BlobWriteCallback {
+class TestCallback {
public:
- TestCallback() : called(false), succeeded(false) {}
- leveldb::Status Run(IndexedDBBackingStore::BlobWriteResult result) override {
- called = true;
- switch (result) {
- case IndexedDBBackingStore::BlobWriteResult::FAILURE_ASYNC:
- // Not tested.
- succeeded = false;
- break;
- case IndexedDBBackingStore::BlobWriteResult::SUCCESS_ASYNC:
- case IndexedDBBackingStore::BlobWriteResult::SUCCESS_SYNC:
- succeeded = true;
- break;
- }
- return leveldb::Status::OK();
+ TestCallback() = default;
+ ~TestCallback() = default;
+
+ IndexedDBBackingStore::BlobWriteCallback CreateCallback() {
+ return base::BindLambdaForTesting(
+ [this](IndexedDBBackingStore::BlobWriteResult result) {
+ this->called = true;
+ switch (result) {
+ case IndexedDBBackingStore::BlobWriteResult::FAILURE_ASYNC:
+ // Not tested.
+ this->succeeded = false;
+ break;
+ case IndexedDBBackingStore::BlobWriteResult::SUCCESS_ASYNC:
+ case IndexedDBBackingStore::BlobWriteResult::SUCCESS_SYNC:
+ this->succeeded = true;
+ break;
+ }
+ return leveldb::Status::OK();
+ });
}
- bool called;
- bool succeeded;
-
- protected:
- ~TestCallback() override {}
+ bool called = false;
+ bool succeeded = false;
private:
DISALLOW_COPY_AND_ASSIGN(TestCallback);
@@ -410,10 +397,12 @@ TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
leveldb::Status s = backing_store()->PutRecord(&transaction1, 1, 1,
key, &value, &record);
EXPECT_TRUE(s.ok());
- auto callback = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
- EXPECT_TRUE(callback->called);
- EXPECT_TRUE(callback->succeeded);
+ TestCallback callback_creator;
+ EXPECT_TRUE(
+ transaction1.CommitPhaseOne(callback_creator.CreateCallback())
+ .ok());
+ EXPECT_TRUE(callback_creator.called);
+ EXPECT_TRUE(callback_creator.succeeded);
EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
}
@@ -424,10 +413,12 @@ TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
EXPECT_TRUE(backing_store()
->GetRecord(&transaction2, 1, 1, key, &result_value)
.ok());
- auto callback = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
- EXPECT_TRUE(callback->called);
- EXPECT_TRUE(callback->succeeded);
+ TestCallback callback_creator;
+ EXPECT_TRUE(
+ transaction2.CommitPhaseOne(callback_creator.CreateCallback())
+ .ok());
+ EXPECT_TRUE(callback_creator.called);
+ EXPECT_TRUE(callback_creator.succeeded);
EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
EXPECT_EQ(value.bits, result_value.bits);
}
@@ -438,9 +429,9 @@ TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
TEST_F(IndexedDBBackingStoreTestWithBlobs, PutGetConsistencyWithBlobs) {
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1;
- scoped_refptr<TestCallback> callback1;
+ TestCallback callback_creator1;
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction3;
- scoped_refptr<TestCallback> callback3;
+ TestCallback callback_creator3;
idb_context_->TaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
@@ -453,16 +444,17 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, PutGetConsistencyWithBlobs) {
backing_store()
->PutRecord(transaction1.get(), 1, 1, key3_, &value3_, &record)
.ok());
- callback1 = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction1->CommitPhaseOne(callback1).ok());
+ EXPECT_TRUE(
+ transaction1->CommitPhaseOne(callback_creator1.CreateCallback())
+ .ok());
}));
RunAllTasksUntilIdle();
idb_context_->TaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
// Finish up transaction1, verifying blob writes.
- EXPECT_TRUE(callback1->called);
- EXPECT_TRUE(callback1->succeeded);
+ EXPECT_TRUE(callback_creator1.called);
+ EXPECT_TRUE(callback_creator1.succeeded);
EXPECT_TRUE(CheckBlobWrites());
EXPECT_TRUE(transaction1->CommitPhaseTwo().ok());
@@ -475,10 +467,12 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, PutGetConsistencyWithBlobs) {
.ok());
// Finish up transaction2, verifying blob reads.
- auto callback = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
- EXPECT_TRUE(callback->called);
- EXPECT_TRUE(callback->succeeded);
+ TestCallback callback_creator;
+ EXPECT_TRUE(
+ transaction2.CommitPhaseOne(callback_creator.CreateCallback())
+ .ok());
+ EXPECT_TRUE(callback_creator.called);
+ EXPECT_TRUE(callback_creator.succeeded);
EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
EXPECT_EQ(value3_.bits, result_value.bits);
EXPECT_TRUE(CheckBlobInfoMatches(result_value.blob_info));
@@ -492,8 +486,9 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, PutGetConsistencyWithBlobs) {
->DeleteRange(transaction3.get(), 1, 1,
IndexedDBKeyRange(key3_))
.ok());
- callback3 = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction3->CommitPhaseOne(callback3).ok());
+ EXPECT_TRUE(
+ transaction3->CommitPhaseOne(callback_creator3.CreateCallback())
+ .ok());
}));
RunAllTasksUntilIdle();
@@ -506,9 +501,7 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, PutGetConsistencyWithBlobs) {
// Clean up on the IDB sequence.
transaction1.reset();
- callback1.reset();
transaction3.reset();
- callback3.reset();
}));
RunAllTasksUntilIdle();
}
@@ -530,9 +523,9 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRange) {
const IndexedDBKeyRange& range = ranges[i];
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1;
- scoped_refptr<TestCallback> callback1;
+ TestCallback callback_creator1;
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction2;
- scoped_refptr<TestCallback> callback2;
+ TestCallback callback_creator2;
std::vector<std::unique_ptr<storage::BlobDataHandle>> blobs;
for (size_t j = 0; j < 4; ++j)
@@ -581,16 +574,17 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRange) {
}
// Start committing transaction1.
- callback1 = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction1->CommitPhaseOne(callback1).ok());
+ EXPECT_TRUE(
+ transaction1->CommitPhaseOne(callback_creator1.CreateCallback())
+ .ok());
}));
RunAllTasksUntilIdle();
idb_context_->TaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
// Finish committing transaction1.
- EXPECT_TRUE(callback1->called);
- EXPECT_TRUE(callback1->succeeded);
+ EXPECT_TRUE(callback_creator1.called);
+ EXPECT_TRUE(callback_creator1.succeeded);
EXPECT_TRUE(transaction1->CommitPhaseTwo().ok());
// Initiate transaction 2 - delete range.
@@ -604,16 +598,17 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRange) {
.ok());
// Start committing transaction2.
- callback2 = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction2->CommitPhaseOne(callback2).ok());
+ EXPECT_TRUE(
+ transaction2->CommitPhaseOne(callback_creator2.CreateCallback())
+ .ok());
}));
RunAllTasksUntilIdle();
idb_context_->TaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
// Finish committing transaction2.
- EXPECT_TRUE(callback2->called);
- EXPECT_TRUE(callback2->succeeded);
+ EXPECT_TRUE(callback_creator2.called);
+ EXPECT_TRUE(callback_creator2.succeeded);
EXPECT_TRUE(transaction2->CommitPhaseTwo().ok());
// Verify blob removals.
@@ -625,9 +620,7 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRange) {
// Clean up on the IDB sequence.
transaction1.reset();
- callback1.reset();
transaction2.reset();
- callback2.reset();
}));
RunAllTasksUntilIdle();
}
@@ -649,9 +642,9 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRangeEmptyRange) {
const IndexedDBKeyRange& range = ranges[i];
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1;
- scoped_refptr<TestCallback> callback1;
+ TestCallback callback_creator1;
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction2;
- scoped_refptr<TestCallback> callback2;
+ TestCallback callback_creator2;
std::vector<std::unique_ptr<storage::BlobDataHandle>> blobs;
for (size_t j = 0; j < 4; ++j)
@@ -700,16 +693,17 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRangeEmptyRange) {
.ok());
}
// Start committing transaction1.
- callback1 = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction1->CommitPhaseOne(callback1).ok());
+ EXPECT_TRUE(
+ transaction1->CommitPhaseOne(callback_creator1.CreateCallback())
+ .ok());
}));
RunAllTasksUntilIdle();
idb_context_->TaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
// Finish committing transaction1.
- EXPECT_TRUE(callback1->called);
- EXPECT_TRUE(callback1->succeeded);
+ EXPECT_TRUE(callback_creator1.called);
+ EXPECT_TRUE(callback_creator1.succeeded);
EXPECT_TRUE(transaction1->CommitPhaseTwo().ok());
// Initiate transaction 2 - delete range.
@@ -723,16 +717,17 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRangeEmptyRange) {
.ok());
// Start committing transaction2.
- callback2 = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction2->CommitPhaseOne(callback2).ok());
+ EXPECT_TRUE(
+ transaction2->CommitPhaseOne(callback_creator2.CreateCallback())
+ .ok());
}));
RunAllTasksUntilIdle();
idb_context_->TaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
// Finish committing transaction2.
- EXPECT_TRUE(callback2->called);
- EXPECT_TRUE(callback2->succeeded);
+ EXPECT_TRUE(callback_creator2.called);
+ EXPECT_TRUE(callback_creator2.succeeded);
EXPECT_TRUE(transaction2->CommitPhaseTwo().ok());
// Verify blob removals.
@@ -740,9 +735,7 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRangeEmptyRange) {
// Clean on the IDB sequence.
transaction1.reset();
- callback1.reset();
transaction2.reset();
- callback2.reset();
}));
RunAllTasksUntilIdle();
}
@@ -750,9 +743,9 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRangeEmptyRange) {
TEST_F(IndexedDBBackingStoreTestWithBlobs, BlobJournalInterleavedTransactions) {
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1;
- scoped_refptr<TestCallback> callback1;
+ TestCallback callback_creator1;
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction2;
- scoped_refptr<TestCallback> callback2;
+ TestCallback callback_creator2;
idb_context_->TaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
@@ -765,16 +758,17 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, BlobJournalInterleavedTransactions) {
backing_store()
->PutRecord(transaction1.get(), 1, 1, key3_, &value3_, &record1)
.ok());
- callback1 = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction1->CommitPhaseOne(callback1).ok());
+ EXPECT_TRUE(
+ transaction1->CommitPhaseOne(callback_creator1.CreateCallback())
+ .ok());
}));
RunAllTasksUntilIdle();
idb_context_->TaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
// Verify transaction1 phase one completed.
- EXPECT_TRUE(callback1->called);
- EXPECT_TRUE(callback1->succeeded);
+ EXPECT_TRUE(callback_creator1.called);
+ EXPECT_TRUE(callback_creator1.succeeded);
EXPECT_TRUE(CheckBlobWrites());
EXPECT_EQ(0U, backing_store()->removals().size());
@@ -787,16 +781,17 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, BlobJournalInterleavedTransactions) {
backing_store()
->PutRecord(transaction2.get(), 1, 1, key1_, &value1_, &record2)
.ok());
- callback2 = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction2->CommitPhaseOne(callback2).ok());
+ EXPECT_TRUE(
+ transaction2->CommitPhaseOne(callback_creator2.CreateCallback())
+ .ok());
}));
RunAllTasksUntilIdle();
idb_context_->TaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
// Verify transaction2 phase one completed.
- EXPECT_TRUE(callback2->called);
- EXPECT_TRUE(callback2->succeeded);
+ EXPECT_TRUE(callback_creator2.called);
+ EXPECT_TRUE(callback_creator2.succeeded);
EXPECT_TRUE(CheckBlobWrites());
EXPECT_EQ(0U, backing_store()->removals().size());
@@ -809,18 +804,16 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, BlobJournalInterleavedTransactions) {
// Clean up on the IDB sequence.
transaction1.reset();
- callback1.reset();
transaction2.reset();
- callback2.reset();
}));
RunAllTasksUntilIdle();
}
TEST_F(IndexedDBBackingStoreTestWithBlobs, LiveBlobJournal) {
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1;
- scoped_refptr<TestCallback> callback1;
+ TestCallback callback_creator1;
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction3;
- scoped_refptr<TestCallback> callback3;
+ TestCallback callback_creator3;
IndexedDBValue read_result_value;
idb_context_->TaskRunner()->PostTask(
@@ -833,15 +826,16 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, LiveBlobJournal) {
backing_store()
->PutRecord(transaction1.get(), 1, 1, key3_, &value3_, &record)
.ok());
- callback1 = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction1->CommitPhaseOne(callback1).ok());
+ EXPECT_TRUE(
+ transaction1->CommitPhaseOne(callback_creator1.CreateCallback())
+ .ok());
}));
RunAllTasksUntilIdle();
idb_context_->TaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
- EXPECT_TRUE(callback1->called);
- EXPECT_TRUE(callback1->succeeded);
+ EXPECT_TRUE(callback_creator1.called);
+ EXPECT_TRUE(callback_creator1.succeeded);
EXPECT_TRUE(CheckBlobWrites());
EXPECT_TRUE(transaction1->CommitPhaseTwo().ok());
@@ -851,10 +845,12 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, LiveBlobJournal) {
backing_store()
->GetRecord(&transaction2, 1, 1, key3_, &read_result_value)
.ok());
- auto callback = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
- EXPECT_TRUE(callback->called);
- EXPECT_TRUE(callback->succeeded);
+ TestCallback callback_creator;
+ EXPECT_TRUE(
+ transaction2.CommitPhaseOne(callback_creator.CreateCallback())
+ .ok());
+ EXPECT_TRUE(callback_creator.called);
+ EXPECT_TRUE(callback_creator.succeeded);
EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
EXPECT_EQ(value3_.bits, read_result_value.bits);
EXPECT_TRUE(CheckBlobInfoMatches(read_result_value.blob_info));
@@ -870,15 +866,16 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, LiveBlobJournal) {
->DeleteRange(transaction3.get(), 1, 1,
IndexedDBKeyRange(key3_))
.ok());
- callback3 = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction3->CommitPhaseOne(callback3).ok());
+ EXPECT_TRUE(
+ transaction3->CommitPhaseOne(callback_creator3.CreateCallback())
+ .ok());
}));
RunAllTasksUntilIdle();
idb_context_->TaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
- EXPECT_TRUE(callback3->called);
- EXPECT_TRUE(callback3->succeeded);
+ EXPECT_TRUE(callback_creator3.called);
+ EXPECT_TRUE(callback_creator3.succeeded);
EXPECT_TRUE(transaction3->CommitPhaseTwo().ok());
EXPECT_EQ(0U, backing_store()->removals().size());
for (size_t i = 0; i < read_result_value.blob_info.size(); ++i) {
@@ -909,9 +906,7 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, LiveBlobJournal) {
// Clean on the IDB sequence.
transaction1.reset();
- callback1.reset();
transaction3.reset();
- callback3.reset();
IndexedDBValue read_result_value;
}));
RunAllTasksUntilIdle();
@@ -956,10 +951,12 @@ TEST_F(IndexedDBBackingStoreTest, HighIds) {
high_index_id, index_key, record);
EXPECT_TRUE(s.ok());
- auto callback = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
- EXPECT_TRUE(callback->called);
- EXPECT_TRUE(callback->succeeded);
+ TestCallback callback_creator;
+ EXPECT_TRUE(
+ transaction1.CommitPhaseOne(callback_creator.CreateCallback())
+ .ok());
+ EXPECT_TRUE(callback_creator.called);
+ EXPECT_TRUE(callback_creator.succeeded);
EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
}
@@ -985,10 +982,12 @@ TEST_F(IndexedDBBackingStoreTest, HighIds) {
EXPECT_TRUE(s.ok());
EXPECT_TRUE(new_primary_key->Equals(key1));
- auto callback = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
- EXPECT_TRUE(callback->called);
- EXPECT_TRUE(callback->succeeded);
+ TestCallback callback_creator;
+ EXPECT_TRUE(
+ transaction2.CommitPhaseOne(callback_creator.CreateCallback())
+ .ok());
+ EXPECT_TRUE(callback_creator.called);
+ EXPECT_TRUE(callback_creator.succeeded);
EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
}
loop.Quit();
@@ -1118,10 +1117,12 @@ TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
index_name, index_key_path, unique, multi_entry, &index);
EXPECT_TRUE(s.ok());
- auto callback = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction.CommitPhaseOne(callback).ok());
- EXPECT_TRUE(callback->called);
- EXPECT_TRUE(callback->succeeded);
+ TestCallback callback_creator;
+ EXPECT_TRUE(
+ transaction.CommitPhaseOne(callback_creator.CreateCallback())
+ .ok());
+ EXPECT_TRUE(callback_creator.called);
+ EXPECT_TRUE(callback_creator.succeeded);
EXPECT_TRUE(transaction.CommitPhaseTwo().ok());
}
@@ -1303,10 +1304,12 @@ TEST_F(IndexedDBBackingStoreTest, SchemaUpgradeWithoutBlobsSurvives) {
&object_store);
EXPECT_TRUE(s.ok());
- auto callback = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction.CommitPhaseOne(callback).ok());
- EXPECT_TRUE(callback->called);
- EXPECT_TRUE(callback->succeeded);
+ TestCallback callback_creator;
+ EXPECT_TRUE(
+ transaction.CommitPhaseOne(callback_creator.CreateCallback())
+ .ok());
+ EXPECT_TRUE(callback_creator.called);
+ EXPECT_TRUE(callback_creator.succeeded);
EXPECT_TRUE(transaction.CommitPhaseTwo().ok());
}
}));
@@ -1323,10 +1326,12 @@ TEST_F(IndexedDBBackingStoreTest, SchemaUpgradeWithoutBlobsSurvives) {
leveldb::Status s = backing_store()->PutRecord(
&transaction1, database_id, object_store_id, key, &value, &record);
EXPECT_TRUE(s.ok());
- auto callback = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
- EXPECT_TRUE(callback->called);
- EXPECT_TRUE(callback->succeeded);
+ TestCallback callback_creator;
+ EXPECT_TRUE(
+ transaction1.CommitPhaseOne(callback_creator.CreateCallback())
+ .ok());
+ EXPECT_TRUE(callback_creator.called);
+ EXPECT_TRUE(callback_creator.succeeded);
EXPECT_TRUE(transaction1.CommitPhaseTwo().ok());
// Set the schema to 2, which was before blob support.
@@ -1354,10 +1359,12 @@ TEST_F(IndexedDBBackingStoreTest, SchemaUpgradeWithoutBlobsSurvives) {
->GetRecord(&transaction2, database_id, object_store_id,
key, &result_value)
.ok());
- auto callback = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
- EXPECT_TRUE(callback->called);
- EXPECT_TRUE(callback->succeeded);
+ TestCallback callback_creator;
+ EXPECT_TRUE(
+ transaction2.CommitPhaseOne(callback_creator.CreateCallback())
+ .ok());
+ EXPECT_TRUE(callback_creator.called);
+ EXPECT_TRUE(callback_creator.succeeded);
EXPECT_TRUE(transaction2.CommitPhaseTwo().ok());
EXPECT_EQ(value.bits, result_value.bits);
@@ -1389,9 +1396,7 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, SchemaUpgradeWithBlobsCorrupt) {
int64_t database_id;
const int64_t object_store_id = 99;
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1;
- scoped_refptr<TestCallback> callback1;
- std::unique_ptr<IndexedDBBackingStore::Transaction> transaction3;
- scoped_refptr<TestCallback> callback3;
+ TestCallback callback_creator1;
// The database metadata needs to be written so the blob entry keys can
// be detected.
@@ -1426,10 +1431,12 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, SchemaUpgradeWithBlobsCorrupt) {
&object_store);
EXPECT_TRUE(s.ok());
- auto callback = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction.CommitPhaseOne(callback).ok());
- EXPECT_TRUE(callback->called);
- EXPECT_TRUE(callback->succeeded);
+ TestCallback callback_creator;
+ EXPECT_TRUE(
+ transaction.CommitPhaseOne(callback_creator.CreateCallback())
+ .ok());
+ EXPECT_TRUE(callback_creator.called);
+ EXPECT_TRUE(callback_creator.succeeded);
EXPECT_TRUE(transaction.CommitPhaseTwo().ok());
}
}));
@@ -1446,16 +1453,17 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, SchemaUpgradeWithBlobsCorrupt) {
->PutRecord(transaction1.get(), database_id,
object_store_id, key3_, &value3_, &record)
.ok());
- callback1 = base::MakeRefCounted<TestCallback>();
- EXPECT_TRUE(transaction1->CommitPhaseOne(callback1).ok());
+ EXPECT_TRUE(
+ transaction1->CommitPhaseOne(callback_creator1.CreateCallback())
+ .ok());
}));
RunAllTasksUntilIdle();
idb_context_->TaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
// Finish up transaction1, verifying blob writes.
- EXPECT_TRUE(callback1->called);
- EXPECT_TRUE(callback1->succeeded);
+ EXPECT_TRUE(callback_creator1.called);
+ EXPECT_TRUE(callback_creator1.succeeded);
EXPECT_TRUE(CheckBlobWrites());
EXPECT_TRUE(transaction1->CommitPhaseTwo().ok());
@@ -1469,9 +1477,6 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, SchemaUpgradeWithBlobsCorrupt) {
// Clean up on the IDB sequence.
transaction1.reset();
- callback1.reset();
- transaction3.reset();
- callback3.reset();
}));
RunAllTasksUntilIdle();
diff --git a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
index 9013eaea209..8126d44454f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -29,6 +29,7 @@
#include "content/browser/browser_main_loop.h"
#include "content/browser/indexed_db/indexed_db_class_factory.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
@@ -658,18 +659,17 @@ std::unique_ptr<net::test_server::HttpResponse> ServePath(
void CompactIndexedDBBackingStore(scoped_refptr<IndexedDBContextImpl> context,
const Origin& origin) {
- IndexedDBFactory* factory = context->GetIDBFactory();
+ IndexedDBFactoryImpl* factory = context->GetIDBFactory();
- std::pair<IndexedDBFactory::OriginDBMapIterator,
- IndexedDBFactory::OriginDBMapIterator>
- range = factory->GetOpenDatabasesForOrigin(origin);
+ std::vector<IndexedDBDatabase*> databases =
+ factory->GetOpenDatabasesForOrigin(origin);
- if (range.first == range.second) // If no open db's for this origin
+ if (databases.empty())
return;
// Compact the first db's backing store since all the db's are in the same
// backing store.
- IndexedDBDatabase* db = range.first->second;
+ IndexedDBDatabase* db = databases[0];
IndexedDBBackingStore* backing_store = db->backing_store();
backing_store->Compact();
}
@@ -762,17 +762,9 @@ std::unique_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler(
std::string escaped_value(
request_query.substr(value_pos.begin, value_pos.len));
- std::string key = net::UnescapeURLComponent(
- escaped_key,
- net::UnescapeRule::NORMAL | net::UnescapeRule::SPACES |
- net::UnescapeRule::PATH_SEPARATORS |
- net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS);
-
- std::string value = net::UnescapeURLComponent(
- escaped_value,
- net::UnescapeRule::NORMAL | net::UnescapeRule::SPACES |
- net::UnescapeRule::PATH_SEPARATORS |
- net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS);
+ std::string key = net::UnescapeBinaryURLComponent(escaped_key);
+
+ std::string value = net::UnescapeBinaryURLComponent(escaped_value);
if (key == "method")
fail_method = value;
diff --git a/chromium/content/browser/indexed_db/indexed_db_callback_helpers.h b/chromium/content/browser/indexed_db/indexed_db_callback_helpers.h
new file mode 100644
index 00000000000..781fd815513
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_callback_helpers.h
@@ -0,0 +1,118 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_CALLBACK_HELPERS_H_
+#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_CALLBACK_HELPERS_H_
+
+#include <memory>
+
+#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/indexed_db/indexed_db_transaction.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
+#include "third_party/leveldatabase/env_chromium.h"
+
+// Since functions in this file use templates, they must be in a header file
+// and can't be placed in a definition file. Please ensure any including file
+// is a definition file, itself, and never include this into a header file.
+
+namespace content {
+namespace indexed_db_callback_helpers_internal {
+
+template <typename T>
+leveldb::Status InvokeOrSucceed(base::WeakPtr<T> ptr,
+ IndexedDBTransaction::Operation operation,
+ IndexedDBTransaction* transaction) {
+ if (ptr)
+ return std::move(operation).Run(transaction);
+ return leveldb::Status::OK();
+}
+
+template <typename R>
+R AbortCallback(base::WeakPtr<IndexedDBTransaction> transaction) {
+ if (transaction)
+ transaction->IncrementNumErrorsSent();
+ IndexedDBDatabaseError error(
+ blink::kWebIDBDatabaseExceptionIgnorableAbortError,
+ "Backend aborted error");
+ return R::Struct::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message()));
+}
+
+template <typename R>
+base::OnceCallback<R()> CreateAbortCallback(
+ base::WeakPtr<IndexedDBTransaction> transaction) {
+ return base::BindOnce(&AbortCallback<R>, std::move(transaction));
+}
+
+// CallbackAbortOnDestruct wraps a callback in a class with a destructor that
+// invokes that callback. When the CallbackAbortOnDestruct is instantiated,
+// it expects a separate callback that, when called at destruct, will return
+// the arguments that should be passed to the wrapped callback.
+//
+// This class is loosely based on //mojo/public/cpp/bindings/callback_helpers.h
+// WrapCallbackWithDefaultInvokeIfNotRun. The difference is that the destructor
+// calls |callback_| with args it gets on destruct rather than using static args
+// given when the wrapper is created.
+template <typename T, typename R>
+class CallbackAbortOnDestruct {
+ public:
+ CallbackAbortOnDestruct(T callback,
+ base::WeakPtr<IndexedDBTransaction> transaction)
+ : callback_(std::move(callback)),
+ args_at_destroy_(CreateAbortCallback<R>(transaction)),
+ called_(false) {}
+ ~CallbackAbortOnDestruct() {
+ if (called_)
+ return;
+ R args = std::move(args_at_destroy_).Run();
+ std::move(callback_).Run(std::move(args));
+ }
+
+ void Run(R ptr) {
+ called_ = true;
+ std::move(callback_).Run(std::move(ptr));
+ }
+
+ private:
+ T callback_;
+ base::OnceCallback<R()> args_at_destroy_;
+ bool called_;
+ DISALLOW_COPY_AND_ASSIGN(CallbackAbortOnDestruct);
+};
+
+} // namespace indexed_db_callback_helpers_internal
+
+// CreateCallbackAbortOnDestruct is a helper function to create an instance
+// of CallbackAbortOnDestruct that returns a callback. By using this helper
+// function, the wrapping callback can exist with the same type signature as
+// the wrapped callback.
+template <typename T, typename R>
+T CreateCallbackAbortOnDestruct(
+ T cb,
+ base::WeakPtr<IndexedDBTransaction> transaction) {
+ return base::BindOnce(
+ &indexed_db_callback_helpers_internal::CallbackAbortOnDestruct<T, R>::Run,
+ std::make_unique<
+ indexed_db_callback_helpers_internal::CallbackAbortOnDestruct<T, R>>(
+ std::move(cb), std::move(transaction)));
+}
+
+// This allows us to bind a function with a return value to a weak ptr, and if
+// the weak pointer is invalidated then we just return a default (success).
+template <typename T, typename Functor, typename... Args>
+IndexedDBTransaction::Operation BindWeakOperation(Functor&& functor,
+ base::WeakPtr<T> ptr,
+ Args&&... args) {
+ DCHECK(ptr);
+ T* raw_ptr = ptr.get();
+ return base::BindOnce(
+ &indexed_db_callback_helpers_internal::InvokeOrSucceed<T>, std::move(ptr),
+ base::BindOnce(std::forward<Functor>(functor), base::Unretained(raw_ptr),
+ std::forward<Args>(args)...));
+}
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_CALLBACK_HELPERS_H_
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
index 7cc498b1fb5..bbb0e9d7e84 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -60,7 +60,7 @@ class SafeConnectionWrapper {
idb_runner_->PostTask(
FROM_HERE, base::BindOnce(
[](std::unique_ptr<IndexedDBConnection> connection) {
- connection->ForceClose();
+ connection->CloseAndReportForceClose();
},
std::move(connection_)));
}
@@ -165,9 +165,7 @@ IndexedDBCallbacks::IndexedDBValueBlob::GetIndexedDBValueBlobs(
// static
bool IndexedDBCallbacks::CreateAllBlobs(
scoped_refptr<ChromeBlobStorageContext> blob_context,
- scoped_refptr<base::SequencedTaskRunner> idb_runner,
std::vector<IndexedDBValueBlob> value_blobs) {
- DCHECK(idb_runner->RunsTasksInCurrentSequence());
IDB_TRACE("IndexedDBCallbacks::CreateAllBlobs");
if (value_blobs.empty())
@@ -206,7 +204,7 @@ bool IndexedDBCallbacks::CreateAllBlobs(
}
*inner_result = true;
},
- std::move(blob_context), std::move(idb_runner),
+ std::move(blob_context), base::SequencedTaskRunnerHandle::Get(),
std::move(value_blobs), &signal_when_finished, &result));
signal_when_finished.Wait();
return result;
@@ -395,7 +393,7 @@ void IndexedDBCallbacks::OnSuccess(std::unique_ptr<IndexedDBCursor> cursor,
std::make_unique<CursorImpl>(std::move(cursor_wrapper.cursor_), origin_,
dispatcher_host_.get(), idb_runner_);
if (mojo_value && !IndexedDBCallbacks::CreateAllBlobs(
- dispatcher_host_->blob_storage_context(), idb_runner_,
+ dispatcher_host_->blob_storage_context(),
IndexedDBValueBlob::GetIndexedDBValueBlobs(
blob_info, &mojo_value->blob_or_file_info))) {
return;
@@ -432,7 +430,7 @@ void IndexedDBCallbacks::OnSuccess(IndexedDBReturnValue* value) {
if (mojo_value &&
!IndexedDBCallbacks::CreateAllBlobs(
- dispatcher_host_->blob_storage_context(), idb_runner_,
+ dispatcher_host_->blob_storage_context(),
IndexedDBValueBlob::GetIndexedDBValueBlobs(
blob_info, &mojo_value->value->blob_or_file_info))) {
return;
@@ -442,44 +440,6 @@ void IndexedDBCallbacks::OnSuccess(IndexedDBReturnValue* value) {
complete_ = true;
}
-void IndexedDBCallbacks::OnSuccessArray(
- std::vector<IndexedDBReturnValue>* values) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(!complete_);
-
- DCHECK_EQ(blink::mojom::IDBDataLoss::None, data_loss_);
-
- std::vector<blink::mojom::IDBReturnValuePtr> mojo_values;
- mojo_values.reserve(values->size());
- for (size_t i = 0; i < values->size(); ++i) {
- mojo_values.push_back(
- IndexedDBReturnValue::ConvertReturnValue(&(*values)[i]));
- }
-
- if (!callbacks_)
- return;
- if (!dispatcher_host_) {
- OnConnectionError();
- return;
- }
-
- std::vector<IndexedDBValueBlob> value_blobs;
- for (size_t i = 0; i < mojo_values.size(); ++i) {
- IndexedDBValueBlob::GetIndexedDBValueBlobs(
- &value_blobs, (*values)[i].blob_info,
- &mojo_values[i]->value->blob_or_file_info);
- }
-
- if (!IndexedDBCallbacks::CreateAllBlobs(
- dispatcher_host_->blob_storage_context(), idb_runner_,
- std::move(value_blobs))) {
- return;
- }
-
- callbacks_->SuccessArray(std::move(mojo_values));
- complete_ = true;
-}
-
void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& value) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!complete_);
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.h b/chromium/content/browser/indexed_db/indexed_db_callbacks.h
index b26cb8740ab..2ed69a166fd 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.h
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.h
@@ -82,7 +82,6 @@ class CONTENT_EXPORT IndexedDBCallbacks
static bool CreateAllBlobs(
scoped_refptr<ChromeBlobStorageContext> blob_context,
- scoped_refptr<base::SequencedTaskRunner> idb_runner,
std::vector<IndexedDBValueBlob> value_blobs);
IndexedDBCallbacks(base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
@@ -120,9 +119,6 @@ class CONTENT_EXPORT IndexedDBCallbacks
// IndexedDBCursor::Advance
virtual void OnSuccess(IndexedDBReturnValue* value);
- // IndexedDBDatabase::GetAll
- virtual void OnSuccessArray(std::vector<IndexedDBReturnValue>* values);
-
// IndexedDBDatabase::Put / IndexedDBCursor::Update
virtual void OnSuccess(const blink::IndexedDBKey& key);
diff --git a/chromium/content/browser/indexed_db/indexed_db_class_factory.cc b/chromium/content/browser/indexed_db/indexed_db_class_factory.cc
index 0adcb537fc7..04aec78c7a7 100644
--- a/chromium/content/browser/indexed_db/indexed_db_class_factory.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_class_factory.cc
@@ -30,27 +30,33 @@ IndexedDBClassFactory* IndexedDBClassFactory::Get() {
return s_factory.Pointer();
}
-scoped_refptr<IndexedDBDatabase> IndexedDBClassFactory::CreateIndexedDBDatabase(
+std::unique_ptr<IndexedDBDatabase>
+IndexedDBClassFactory::CreateIndexedDBDatabase(
const base::string16& name,
- scoped_refptr<IndexedDBBackingStore> backing_store,
- scoped_refptr<IndexedDBFactory> factory,
+ IndexedDBBackingStore* backing_store,
+ IndexedDBFactory* factory,
+ IndexedDBDatabase::ErrorCallback error_callback,
+ base::OnceClosure destroy_me,
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
const IndexedDBDatabase::Identifier& unique_identifier,
ScopesLockManager* transaction_lock_manager) {
- return new IndexedDBDatabase(name, backing_store, factory,
- std::move(metadata_coding), unique_identifier,
- transaction_lock_manager);
+ return base::WrapUnique(new IndexedDBDatabase(
+ name, backing_store, factory, std::move(error_callback),
+ std::move(destroy_me), std::move(metadata_coding), unique_identifier,
+ transaction_lock_manager));
}
std::unique_ptr<IndexedDBTransaction>
IndexedDBClassFactory::CreateIndexedDBTransaction(
int64_t id,
IndexedDBConnection* connection,
+ ErrorCallback error_callback,
const std::set<int64_t>& scope,
blink::mojom::IDBTransactionMode mode,
IndexedDBBackingStore::Transaction* backing_store_transaction) {
- return std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction(
- id, connection, scope, mode, backing_store_transaction));
+ return base::WrapUnique(
+ new IndexedDBTransaction(id, connection, std::move(error_callback), scope,
+ mode, backing_store_transaction));
}
scoped_refptr<LevelDBTransaction>
diff --git a/chromium/content/browser/indexed_db/indexed_db_class_factory.h b/chromium/content/browser/indexed_db/indexed_db_class_factory.h
index afd9f76df6c..18922b8a842 100644
--- a/chromium/content/browser/indexed_db/indexed_db_class_factory.h
+++ b/chromium/content/browser/indexed_db/indexed_db_class_factory.h
@@ -10,6 +10,7 @@
#include <memory>
#include <set>
+#include "base/callback.h"
#include "base/lazy_instance.h"
#include "base/memory/ref_counted.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
@@ -36,27 +37,36 @@ class LevelDBTransaction;
// Use this factory to create some IndexedDB objects. Exists solely to
// facilitate tests which sometimes need to inject mock objects into the system.
-// TODO(dmurph): Remove th8s class in favor of dependency injection. This makes
+// TODO(dmurph): Remove this class in favor of dependency injection. This makes
// it really hard to iterate on the system.
class CONTENT_EXPORT IndexedDBClassFactory {
public:
typedef IndexedDBClassFactory* GetterCallback();
+ // Used to report irrecoverable backend errors. The second argument can be
+ // null.
+ using ErrorCallback =
+ base::RepeatingCallback<void(leveldb::Status, const char*)>;
static IndexedDBClassFactory* Get();
static void SetIndexedDBClassFactoryGetter(GetterCallback* cb);
- virtual scoped_refptr<IndexedDBDatabase> CreateIndexedDBDatabase(
+ // See IndexedDBDatabase::Create.
+ virtual std::unique_ptr<IndexedDBDatabase> CreateIndexedDBDatabase(
const base::string16& name,
- scoped_refptr<IndexedDBBackingStore> backing_store,
- scoped_refptr<IndexedDBFactory> factory,
+ IndexedDBBackingStore* backing_store,
+ IndexedDBFactory* factory,
+ IndexedDBDatabase::ErrorCallback error_callback,
+ base::OnceClosure destroy_me,
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
const IndexedDBDatabase::Identifier& unique_identifier,
ScopesLockManager* transaction_lock_manager);
+ // |error_callback| is used to report unrecoverable errors.
virtual std::unique_ptr<IndexedDBTransaction> CreateIndexedDBTransaction(
int64_t id,
IndexedDBConnection* connection,
+ ErrorCallback error_callback,
const std::set<int64_t>& scope,
blink::mojom::IDBTransactionMode mode,
IndexedDBBackingStore::Transaction* backing_store_transaction);
diff --git a/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
index 9f517a98f10..0cdcbabd1c3 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
@@ -37,8 +37,8 @@ TEST(IndexedDBIOErrorTest, CleanUpTest) {
const base::FilePath path = temp_directory.GetPath();
auto task_runner = base::SequencedTaskRunnerHandle::Get();
- scoped_refptr<IndexedDBBackingStore> backing_store =
- base::MakeRefCounted<IndexedDBBackingStore>(
+ std::unique_ptr<IndexedDBBackingStore> backing_store =
+ std::make_unique<IndexedDBBackingStore>(
IndexedDBBackingStore::Mode::kInMemory, nullptr, origin, path,
std::make_unique<LevelDBDatabase>(
indexed_db::FakeLevelDBFactory::GetBrokenLevelDB(
@@ -69,8 +69,8 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
MakeIOError("some filename", "some message", leveldb_env::kNewLogger,
base::File::FILE_ERROR_FAILED)};
for (leveldb::Status error_status : errors) {
- scoped_refptr<IndexedDBBackingStore> backing_store =
- base::MakeRefCounted<IndexedDBBackingStore>(
+ std::unique_ptr<IndexedDBBackingStore> backing_store =
+ std::make_unique<IndexedDBBackingStore>(
IndexedDBBackingStore::Mode::kInMemory, nullptr, origin, path,
std::make_unique<LevelDBDatabase>(
indexed_db::FakeLevelDBFactory::GetBrokenLevelDB(error_status,
diff --git a/chromium/content/browser/indexed_db/indexed_db_connection.cc b/chromium/content/browser/indexed_db/indexed_db_connection.cc
index 52a16fd95d2..ea768af32fd 100644
--- a/chromium/content/browser/indexed_db/indexed_db_connection.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_connection.cc
@@ -9,9 +9,11 @@
#include "content/browser/indexed_db/indexed_db_class_factory.h"
#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
+#include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/indexed_db_observer.h"
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
namespace content {
@@ -23,59 +25,62 @@ static int32_t g_next_indexed_db_connection_id;
IndexedDBConnection::IndexedDBConnection(
int child_process_id,
- scoped_refptr<IndexedDBDatabase> database,
+ IndexedDBOriginStateHandle origin_state_handle,
+ base::WeakPtr<IndexedDBDatabase> database,
+ base::RepeatingClosure on_version_change_ignored,
+ base::OnceCallback<void(IndexedDBConnection*)> on_close,
+ ErrorCallback error_callback,
scoped_refptr<IndexedDBDatabaseCallbacks> callbacks)
: id_(g_next_indexed_db_connection_id++),
child_process_id_(child_process_id),
- database_(database),
- callbacks_(callbacks),
- weak_factory_(this) {
+ origin_state_handle_(std::move(origin_state_handle)),
+ database_(std::move(database)),
+ on_version_change_ignored_(std::move(on_version_change_ignored)),
+ on_close_(std::move(on_close)),
+ error_callback_(std::move(error_callback)),
+ callbacks_(callbacks) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
IndexedDBConnection::~IndexedDBConnection() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (on_close_)
+ std::move(on_close_).Run(this);
}
void IndexedDBConnection::Close() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!callbacks_.get())
return;
+
+ // Finish up any transaction, in case there were any running.
+ FinishAllTransactions(IndexedDBDatabaseError(
+ blink::kWebIDBDatabaseExceptionUnknownError, "Connection is closing."));
+
+ // Calling |on_close_| can destroy this object.
base::WeakPtr<IndexedDBConnection> this_obj = weak_factory_.GetWeakPtr();
- database_->Close(this, false /* forced */);
- if (this_obj) {
- database_ = nullptr;
- callbacks_ = nullptr;
- active_observers_.clear();
- }
+ std::move(on_close_).Run(this);
+ if (this_obj)
+ ClearStateAfterClose();
}
-void IndexedDBConnection::ForceClose() {
+void IndexedDBConnection::CloseAndReportForceClose() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!callbacks_.get())
return;
- // IndexedDBDatabase::Close() can delete this instance.
- base::WeakPtr<IndexedDBConnection> this_obj = weak_factory_.GetWeakPtr();
scoped_refptr<IndexedDBDatabaseCallbacks> callbacks(callbacks_);
- database_->Close(this, true /* forced */);
- if (this_obj) {
- database_ = nullptr;
- callbacks_ = nullptr;
- active_observers_.clear();
- }
+ Close();
callbacks->OnForcedClose();
}
void IndexedDBConnection::VersionChangeIgnored() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!database_.get())
- return;
- database_->VersionChangeIgnored();
+ on_version_change_ignored_.Run();
}
bool IndexedDBConnection::IsConnected() {
- return database_.get() != nullptr;
+ return callbacks_.get();
}
// The observers begin listening to changes only once they are activated.
@@ -120,7 +125,7 @@ IndexedDBTransaction* IndexedDBConnection::CreateTransaction(
CHECK_EQ(GetTransaction(id), nullptr) << "Duplicate transaction id." << id;
std::unique_ptr<IndexedDBTransaction> transaction =
IndexedDBClassFactory::Get()->CreateIndexedDBTransaction(
- id, this, scope, mode, backing_store_transaction);
+ id, this, error_callback_, scope, mode, backing_store_transaction);
IndexedDBTransaction* transaction_ptr = transaction.get();
transactions_[id] = std::move(transaction);
return transaction_ptr;
@@ -177,4 +182,10 @@ void IndexedDBConnection::RemoveTransaction(int64_t id) {
transactions_.erase(id);
}
+void IndexedDBConnection::ClearStateAfterClose() {
+ callbacks_ = nullptr;
+ active_observers_.clear();
+ origin_state_handle_.Release();
+}
+
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_connection.h b/chromium/content/browser/indexed_db/indexed_db_connection.h
index 9e5b3524fa7..bcf152428cb 100644
--- a/chromium/content/browser/indexed_db/indexed_db_connection.h
+++ b/chromium/content/browser/indexed_db/indexed_db_connection.h
@@ -14,6 +14,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/indexed_db/indexed_db_database.h"
+#include "content/browser/indexed_db/indexed_db_origin_state_handle.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
namespace content {
@@ -21,18 +22,27 @@ class IndexedDBDatabaseCallbacks;
class IndexedDBDatabaseError;
class IndexedDBObserver;
class IndexedDBTransaction;
+class IndexedDBOriginStateHandle;
class CONTENT_EXPORT IndexedDBConnection {
public:
+ // Used to report irrecoverable backend errors. The second argument can be
+ // null.
+ using ErrorCallback =
+ base::RepeatingCallback<void(leveldb::Status, const char*)>;
+
IndexedDBConnection(int child_process_id,
- scoped_refptr<IndexedDBDatabase> db,
+ IndexedDBOriginStateHandle origin_state_handle,
+ base::WeakPtr<IndexedDBDatabase> database,
+ base::RepeatingClosure on_version_change_ignored,
+ base::OnceCallback<void(IndexedDBConnection*)> on_close,
+ ErrorCallback error_callback,
scoped_refptr<IndexedDBDatabaseCallbacks> callbacks);
virtual ~IndexedDBConnection();
- // These methods are virtual to allow subclassing in unit tests.
- virtual void ForceClose();
- virtual void Close();
- virtual bool IsConnected();
+ void Close();
+ void CloseAndReportForceClose();
+ bool IsConnected();
void VersionChangeIgnored();
@@ -46,7 +56,7 @@ class CONTENT_EXPORT IndexedDBConnection {
int32_t id() const { return id_; }
int child_process_id() const { return child_process_id_; }
- IndexedDBDatabase* database() const { return database_.get(); }
+ base::WeakPtr<IndexedDBDatabase> database() const { return database_; }
IndexedDBDatabaseCallbacks* callbacks() const { return callbacks_.get(); }
const std::vector<std::unique_ptr<IndexedDBObserver>>& active_observers()
const {
@@ -87,14 +97,22 @@ class CONTENT_EXPORT IndexedDBConnection {
}
private:
+ void ClearStateAfterClose();
+
const int32_t id_;
// The process id of the child process this connection is associated with.
// Tracked for IndexedDBContextImpl::GetAllOriginsDetails and debugging.
const int child_process_id_;
- // NULL in some unit tests, and after the connection is closed.
- scoped_refptr<IndexedDBDatabase> database_;
+ // Keeps the factory for this origin alive.
+ IndexedDBOriginStateHandle origin_state_handle_;
+
+ base::WeakPtr<IndexedDBDatabase> database_;
+ base::RepeatingClosure on_version_change_ignored_;
+ // Note: Calling |on_close_| can destroy this object.
+ base::OnceCallback<void(IndexedDBConnection*)> on_close_;
+ ErrorCallback error_callback_;
// The connection owns transactions created on this connection.
std::unordered_map<int64_t, std::unique_ptr<IndexedDBTransaction>>
@@ -107,7 +125,7 @@ class CONTENT_EXPORT IndexedDBConnection {
SEQUENCE_CHECKER(sequence_checker_);
- base::WeakPtrFactory<IndexedDBConnection> weak_factory_;
+ base::WeakPtrFactory<IndexedDBConnection> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(IndexedDBConnection);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
index d70d360a2bd..4af787549d7 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -68,7 +68,6 @@ void GetAllOriginsAndPaths(const base::FilePath& indexeddb_path,
if (file_path.Extension() == indexed_db::kLevelDBExtension &&
file_path.RemoveExtension().Extension() ==
indexed_db::kIndexedDBExtension) {
- // TODO(dmurph): Unittest this.
std::string origin_id = file_path.BaseName()
.RemoveExtension()
.RemoveExtension()
@@ -86,7 +85,8 @@ IndexedDBContextImpl::IndexedDBContextImpl(
const base::FilePath& data_path,
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
- indexed_db::LevelDBFactory* leveldb_factory)
+ indexed_db::LevelDBFactory* leveldb_factory,
+ base::Clock* clock)
: force_keep_session_state_(false),
special_storage_policy_(special_storage_policy),
quota_manager_proxy_(quota_manager_proxy),
@@ -95,21 +95,22 @@ IndexedDBContextImpl::IndexedDBContextImpl(
base::TaskPriority::USER_VISIBLE,
// BLOCK_SHUTDOWN to support clearing session-only storage.
base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
- leveldb_factory_(leveldb_factory) {
+ leveldb_factory_(leveldb_factory),
+ clock_(clock) {
IDB_TRACE("init");
if (!data_path.empty())
data_path_ = data_path.Append(kIndexedDBDirectory);
quota_manager_proxy->RegisterClient(new IndexedDBQuotaClient(this));
}
-IndexedDBFactory* IndexedDBContextImpl::GetIDBFactory() {
+IndexedDBFactoryImpl* IndexedDBContextImpl::GetIDBFactory() {
DCHECK(TaskRunner()->RunsTasksInCurrentSequence());
if (!indexeddb_factory_.get()) {
// Prime our cache of origins with existing databases so we can
// detect when dbs are newly created.
GetOriginSet();
- indexeddb_factory_ = base::MakeRefCounted<IndexedDBFactoryImpl>(
- this, leveldb_factory_, base::DefaultClock::GetInstance());
+ indexeddb_factory_ =
+ std::make_unique<IndexedDBFactoryImpl>(this, leveldb_factory_, clock_);
}
return indexeddb_factory_.get();
}
@@ -173,15 +174,13 @@ base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
list->Append(std::move(info));
continue;
}
- std::pair<IndexedDBFactory::OriginDBMapIterator,
- IndexedDBFactory::OriginDBMapIterator>
- range = indexeddb_factory_->GetOpenDatabasesForOrigin(origin);
+ std::vector<IndexedDBDatabase*> databases =
+ indexeddb_factory_->GetOpenDatabasesForOrigin(origin);
// TODO(jsbell): Sort by name?
std::unique_ptr<base::ListValue> database_list(
std::make_unique<base::ListValue>());
- for (auto it = range.first; it != range.second; ++it) {
- const IndexedDBDatabase* db = it->second;
+ for (IndexedDBDatabase* db : databases) {
std::unique_ptr<base::DictionaryValue> db_info(
std::make_unique<base::DictionaryValue>());
@@ -446,6 +445,20 @@ void IndexedDBContextImpl::ResetCachesForTesting() {
origin_size_map_.clear();
}
+void IndexedDBContextImpl::SetForceKeepSessionState() {
+ force_keep_session_state_ = true;
+}
+
+void IndexedDBContextImpl::FactoryOpened(const Origin& origin) {
+ DCHECK(TaskRunner()->RunsTasksInCurrentSequence());
+ if (GetOriginSet()->insert(origin).second) {
+ // A newly created db, notify the quota system.
+ QueryDiskAndUpdateQuotaUsage(origin);
+ } else {
+ EnsureDiskUsageCacheInitialized(origin);
+ }
+}
+
void IndexedDBContextImpl::ConnectionOpened(const Origin& origin,
IndexedDBConnection* connection) {
DCHECK(TaskRunner()->RunsTasksInCurrentSequence());
@@ -534,7 +547,7 @@ void IndexedDBContextImpl::Shutdown() {
FROM_HERE,
base::BindOnce(
[](const base::FilePath& indexeddb_path,
- scoped_refptr<IndexedDBFactory> factory,
+ std::unique_ptr<IndexedDBFactory> factory,
scoped_refptr<storage::SpecialStoragePolicy>
special_storage_policy) {
std::vector<Origin> origins;
@@ -554,7 +567,8 @@ void IndexedDBContextImpl::Shutdown() {
base::DeleteFile(*file_path, true);
}
},
- data_path_, indexeddb_factory_, special_storage_policy_));
+ data_path_, std::move(indexeddb_factory_),
+ special_storage_policy_));
}
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_context_impl.h b/chromium/content/browser/indexed_db/indexed_db_context_impl.h
index 8d371c9008a..0a6117b2d63 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.h
@@ -18,7 +18,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "content/browser/browser_main_loop.h"
-#include "content/browser/indexed_db/indexed_db_factory.h"
+#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/leveldb/leveldb_env.h"
#include "content/public/browser/indexed_db_context.h"
#include "storage/browser/quota/quota_manager_proxy.h"
@@ -26,6 +26,7 @@
#include "url/origin.h"
namespace base {
+class Clock;
class ListValue;
class FilePath;
class SequencedTaskRunner;
@@ -36,8 +37,8 @@ class Origin;
}
namespace content {
-
class IndexedDBConnection;
+class IndexedDBFactoryImpl;
class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
public:
@@ -73,15 +74,14 @@ class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
const base::FilePath& data_path,
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
- indexed_db::LevelDBFactory* leveldb_factory);
+ indexed_db::LevelDBFactory* leveldb_factory,
+ base::Clock* clock);
- IndexedDBFactory* GetIDBFactory();
+ IndexedDBFactoryImpl* GetIDBFactory();
// Called by StoragePartitionImpl to clear session-only data.
void Shutdown();
- // Disables the exit-time deletion of session-only data.
- void SetForceKeepSessionState() { force_keep_session_state_ = true; }
int64_t GetOriginDiskUsage(const url::Origin& origin);
@@ -94,8 +94,11 @@ class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
base::FilePath GetFilePathForTesting(
const url::Origin& origin) const override;
void ResetCachesForTesting() override;
+ void SetForceKeepSessionState() override;
- // Methods called by IndexedDBDispatcherHost for quota support.
+ // Methods called by IndexedDBFactoryImpl or IndexedDBDispatcherHost for
+ // quota support.
+ void FactoryOpened(const url::Origin& origin);
void ConnectionOpened(const url::Origin& origin, IndexedDBConnection* db);
void ConnectionClosed(const url::Origin& origin, IndexedDBConnection* db);
void TransactionComplete(const url::Origin& origin);
@@ -126,6 +129,7 @@ class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
std::vector<base::FilePath> GetStoragePaths(const url::Origin& origin) const;
base::FilePath data_path() const { return data_path_; }
+ bool IsInMemoryContext() const { return data_path_.empty(); }
size_t GetConnectionCount(const url::Origin& origin);
int GetOriginBlobFileCount(const url::Origin& origin);
@@ -177,7 +181,7 @@ class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
// backing stores); the cache will be primed as needed by checking disk.
std::set<url::Origin>* GetOriginSet();
- scoped_refptr<IndexedDBFactory> indexeddb_factory_;
+ std::unique_ptr<IndexedDBFactoryImpl> indexeddb_factory_;
// If |data_path_| is empty then this is an incognito session and the backing
// store will be held in-memory rather than on-disk.
@@ -192,6 +196,7 @@ class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
std::map<url::Origin, int64_t> origin_size_map_;
base::ObserverList<Observer>::Unchecked observers_;
indexed_db::LevelDBFactory* leveldb_factory_;
+ base::Clock* clock_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBContextImpl);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_cursor.cc b/chromium/content/browser/indexed_db/indexed_db_cursor.cc
index 9aaf05d6edb..23a88afea36 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cursor.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_cursor.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/task/post_task.h"
+#include "content/browser/indexed_db/indexed_db_callback_helpers.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
@@ -40,34 +41,11 @@ IndexedDBDatabaseError CreateError(
uint16_t code,
const char* message,
base::WeakPtr<IndexedDBTransaction> transaction) {
- DCHECK(transaction);
- transaction->IncrementNumErrorsSent();
+ if (transaction)
+ transaction->IncrementNumErrorsSent();
return IndexedDBDatabaseError(code, message);
}
-leveldb::Status InvokeOrSucceed(base::WeakPtr<IndexedDBCursor> weak_cursor,
- IndexedDBTransaction::Operation operation,
- IndexedDBTransaction* transaction) {
- if (weak_cursor)
- return std::move(operation).Run(transaction);
- return leveldb::Status::OK();
-}
-
-// This allows us to bind a function with a return value to a weak ptr, and if
-// the weak pointer is invalidated then we just return a default (success).
-template <typename Functor, typename... Args>
-IndexedDBTransaction::Operation BindWeakOperation(
- Functor&& functor,
- base::WeakPtr<IndexedDBCursor> weak_cursor,
- Args&&... args) {
- DCHECK(weak_cursor);
- IndexedDBCursor* cursor_ptr = weak_cursor.get();
- return base::BindOnce(&InvokeOrSucceed, std::move(weak_cursor),
- base::BindOnce(std::forward<Functor>(functor),
- base::Unretained(cursor_ptr),
- std::forward<Args>(args)...));
-}
-
} // namespace
IndexedDBCursor::IndexedDBCursor(
@@ -101,25 +79,26 @@ void IndexedDBCursor::Advance(
Close();
if (closed_) {
const IndexedDBDatabaseError error(CreateCursorClosedError());
- std::move(callback).Run(
- blink::mojom::IDBError::New(error.code(), error.message()),
- blink::mojom::IDBCursorValuePtr());
+ std::move(callback).Run(blink::mojom::IDBCursorResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
return;
}
+ blink::mojom::IDBCursor::AdvanceCallback aborting_callback =
+ CreateCallbackAbortOnDestruct<blink::mojom::IDBCursor::AdvanceCallback,
+ blink::mojom::IDBCursorResultPtr>(
+ std::move(callback), transaction_);
+
transaction_->ScheduleTask(
task_type_,
- BindWeakOperation(
+ BindWeakOperation<IndexedDBCursor>(
&IndexedDBCursor::CursorAdvanceOperation, ptr_factory_.GetWeakPtr(),
- count, std::move(dispatcher_host),
- base::WrapRefCounted(dispatcher_host->context()->TaskRunner()),
- std::move(callback)));
+ count, std::move(dispatcher_host), std::move(aborting_callback)));
}
leveldb::Status IndexedDBCursor::CursorAdvanceOperation(
uint32_t count,
base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
- scoped_refptr<base::SequencedTaskRunner> idb_runner,
blink::mojom::IDBCursor::AdvanceCallback callback,
IndexedDBTransaction* /*transaction*/) {
IDB_TRACE("IndexedDBCursor::CursorAdvanceOperation");
@@ -131,8 +110,7 @@ leveldb::Status IndexedDBCursor::CursorAdvanceOperation(
cursor_.reset();
if (s.ok()) {
- std::move(callback).Run(blink::mojom::IDBErrorPtr(),
- blink::mojom::IDBCursorValuePtr());
+ std::move(callback).Run(blink::mojom::IDBCursorResult::NewEmpty(true));
return s;
}
@@ -141,9 +119,8 @@ leveldb::Status IndexedDBCursor::CursorAdvanceOperation(
auto error = CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
"Error advancing cursor", transaction_);
Close();
- std::move(callback).Run(
- blink::mojom::IDBError::New(error.code(), error.message()),
- blink::mojom::IDBCursorValuePtr());
+ std::move(callback).Run(blink::mojom::IDBCursorResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
return s;
}
@@ -155,7 +132,7 @@ leveldb::Status IndexedDBCursor::CursorAdvanceOperation(
blob_info.swap(value->blob_info);
if (!IndexedDBCallbacks::CreateAllBlobs(
- dispatcher_host->blob_storage_context(), idb_runner,
+ dispatcher_host->blob_storage_context(),
IndexedDBCallbacks::IndexedDBValueBlob::GetIndexedDBValueBlobs(
blob_info, &mojo_value->blob_or_file_info))) {
return s;
@@ -168,10 +145,9 @@ leveldb::Status IndexedDBCursor::CursorAdvanceOperation(
std::vector<IndexedDBKey> primary_keys = {primary_key()};
std::vector<blink::mojom::IDBValuePtr> values;
values.push_back(std::move(mojo_value));
- blink::mojom::IDBCursorValuePtr cursor_value =
+ std::move(callback).Run(blink::mojom::IDBCursorResult::NewValues(
blink::mojom::IDBCursorValue::New(
- std::move(keys), std::move(primary_keys), std::move(values));
- std::move(callback).Run(blink::mojom::IDBErrorPtr(), std::move(cursor_value));
+ std::move(keys), std::move(primary_keys), std::move(values))));
return s;
}
@@ -185,24 +161,26 @@ void IndexedDBCursor::Continue(
Close();
if (closed_) {
const IndexedDBDatabaseError error(CreateCursorClosedError());
- std::move(callback).Run(
- blink::mojom::IDBError::New(error.code(), error.message()),
- blink::mojom::IDBCursorValuePtr());
+ std::move(callback).Run(blink::mojom::IDBCursorResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
return;
}
+ blink::mojom::IDBCursor::CursorContinueCallback aborting_callback =
+ CreateCallbackAbortOnDestruct<
+ blink::mojom::IDBCursor::CursorContinueCallback,
+ blink::mojom::IDBCursorResultPtr>(std::move(callback), transaction_);
+
transaction_->ScheduleTask(
task_type_,
- BindWeakOperation(
+ BindWeakOperation<IndexedDBCursor>(
&IndexedDBCursor::CursorContinueOperation, ptr_factory_.GetWeakPtr(),
- std::move(dispatcher_host),
- base::WrapRefCounted(dispatcher_host->context()->TaskRunner()),
- base::Passed(&key), base::Passed(&primary_key), std::move(callback)));
+ std::move(dispatcher_host), base::Passed(&key),
+ base::Passed(&primary_key), std::move(aborting_callback)));
}
leveldb::Status IndexedDBCursor::CursorContinueOperation(
base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
- scoped_refptr<base::SequencedTaskRunner> idb_runner,
std::unique_ptr<IndexedDBKey> key,
std::unique_ptr<IndexedDBKey> primary_key,
blink::mojom::IDBCursor::CursorContinueCallback callback,
@@ -218,8 +196,7 @@ leveldb::Status IndexedDBCursor::CursorContinueOperation(
cursor_.reset();
if (s.ok()) {
// This happens if we reach the end of the iterator and can't continue.
- std::move(callback).Run(blink::mojom::IDBErrorPtr(),
- blink::mojom::IDBCursorValuePtr());
+ std::move(callback).Run(blink::mojom::IDBCursorResult::NewEmpty(true));
return s;
}
@@ -229,9 +206,8 @@ leveldb::Status IndexedDBCursor::CursorContinueOperation(
CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
"Error continuing cursor.", transaction_);
Close();
- std::move(callback).Run(
- blink::mojom::IDBError::New(error.code(), error.message()),
- blink::mojom::IDBCursorValuePtr());
+ std::move(callback).Run(blink::mojom::IDBCursorResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
return s;
}
@@ -243,7 +219,7 @@ leveldb::Status IndexedDBCursor::CursorContinueOperation(
blob_info.swap(value->blob_info);
if (!IndexedDBCallbacks::CreateAllBlobs(
- dispatcher_host->blob_storage_context(), idb_runner,
+ dispatcher_host->blob_storage_context(),
IndexedDBCallbacks::IndexedDBValueBlob::GetIndexedDBValueBlobs(
blob_info, &mojo_value->blob_or_file_info))) {
return s;
@@ -256,10 +232,9 @@ leveldb::Status IndexedDBCursor::CursorContinueOperation(
std::vector<IndexedDBKey> primary_keys = {this->primary_key()};
std::vector<blink::mojom::IDBValuePtr> values;
values.push_back(std::move(mojo_value));
- blink::mojom::IDBCursorValuePtr cursor_value =
+ std::move(callback).Run(blink::mojom::IDBCursorResult::NewValues(
blink::mojom::IDBCursorValue::New(
- std::move(keys), std::move(primary_keys), std::move(values));
- std::move(callback).Run(blink::mojom::IDBErrorPtr(), std::move(cursor_value));
+ std::move(keys), std::move(primary_keys), std::move(values))));
return s;
}
@@ -273,24 +248,25 @@ void IndexedDBCursor::PrefetchContinue(
Close();
if (closed_) {
const IndexedDBDatabaseError error(CreateCursorClosedError());
- std::move(callback).Run(
- blink::mojom::IDBError::New(error.code(), error.message()),
- blink::mojom::IDBCursorValuePtr());
+ std::move(callback).Run(blink::mojom::IDBCursorResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
return;
}
+ blink::mojom::IDBCursor::PrefetchCallback aborting_callback =
+ CreateCallbackAbortOnDestruct<blink::mojom::IDBCursor::PrefetchCallback,
+ blink::mojom::IDBCursorResultPtr>(
+ std::move(callback), transaction_);
+
transaction_->ScheduleTask(
- task_type_,
- BindWeakOperation(
- &IndexedDBCursor::CursorPrefetchIterationOperation,
- ptr_factory_.GetWeakPtr(), std::move(dispatcher_host),
- base::WrapRefCounted(dispatcher_host->context()->TaskRunner()),
- number_to_fetch, std::move(callback)));
+ task_type_, BindWeakOperation<IndexedDBCursor>(
+ &IndexedDBCursor::CursorPrefetchIterationOperation,
+ ptr_factory_.GetWeakPtr(), std::move(dispatcher_host),
+ number_to_fetch, std::move(aborting_callback)));
}
leveldb::Status IndexedDBCursor::CursorPrefetchIterationOperation(
base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
- scoped_refptr<base::SequencedTaskRunner> idb_runner,
int number_to_fetch,
blink::mojom::IDBCursor::PrefetchCallback callback,
IndexedDBTransaction* /*transaction*/) {
@@ -324,9 +300,8 @@ leveldb::Status IndexedDBCursor::CursorPrefetchIterationOperation(
CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
"Error continuing cursor.", transaction_);
Close();
- std::move(callback).Run(
- blink::mojom::IDBError::New(error.code(), error.message()),
- blink::mojom::IDBCursorValuePtr());
+ std::move(callback).Run(blink::mojom::IDBCursorResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
return s;
}
@@ -361,8 +336,7 @@ leveldb::Status IndexedDBCursor::CursorPrefetchIterationOperation(
}
if (found_keys.empty()) {
- std::move(callback).Run(blink::mojom::IDBErrorPtr(),
- blink::mojom::IDBCursorValuePtr());
+ std::move(callback).Run(blink::mojom::IDBCursorResult::NewEmpty(true));
return s;
}
@@ -371,9 +345,10 @@ leveldb::Status IndexedDBCursor::CursorPrefetchIterationOperation(
std::vector<blink::mojom::IDBValuePtr> mojo_values;
mojo_values.reserve(found_values.size());
- for (size_t i = 0; i < found_values.size(); ++i)
+ for (size_t i = 0; i < found_values.size(); ++i) {
mojo_values.push_back(
IndexedDBValue::ConvertAndEraseValue(&found_values[i]));
+ }
std::vector<IndexedDBCallbacks::IndexedDBValueBlob> value_blobs;
for (size_t i = 0; i < mojo_values.size(); ++i) {
@@ -383,16 +358,14 @@ leveldb::Status IndexedDBCursor::CursorPrefetchIterationOperation(
}
if (!IndexedDBCallbacks::CreateAllBlobs(
- dispatcher_host->blob_storage_context(), idb_runner,
- std::move(value_blobs))) {
+ dispatcher_host->blob_storage_context(), std::move(value_blobs))) {
return s;
}
- blink::mojom::IDBCursorValuePtr cursor_value =
+ std::move(callback).Run(blink::mojom::IDBCursorResult::NewValues(
blink::mojom::IDBCursorValue::New(std::move(found_keys),
std::move(found_primary_keys),
- std::move(mojo_values));
- std::move(callback).Run(blink::mojom::IDBErrorPtr(), std::move(cursor_value));
+ std::move(mojo_values))));
return s;
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_cursor.h b/chromium/content/browser/indexed_db/indexed_db_cursor.h
index 261f6a883d9..5e0e26f92a1 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cursor.h
+++ b/chromium/content/browser/indexed_db/indexed_db_cursor.h
@@ -59,7 +59,6 @@ class CONTENT_EXPORT IndexedDBCursor {
leveldb::Status CursorContinueOperation(
base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
- scoped_refptr<base::SequencedTaskRunner> idb_runner,
std::unique_ptr<blink::IndexedDBKey> key,
std::unique_ptr<blink::IndexedDBKey> primary_key,
blink::mojom::IDBCursor::CursorContinueCallback callback,
@@ -67,12 +66,10 @@ class CONTENT_EXPORT IndexedDBCursor {
leveldb::Status CursorAdvanceOperation(
uint32_t count,
base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
- scoped_refptr<base::SequencedTaskRunner> idb_runner,
blink::mojom::IDBCursor::AdvanceCallback callback,
IndexedDBTransaction* transaction);
leveldb::Status CursorPrefetchIterationOperation(
base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
- scoped_refptr<base::SequencedTaskRunner> idb_runner,
int number_to_fetch,
blink::mojom::IDBCursor::PrefetchCallback callback,
IndexedDBTransaction* transaction);
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.cc b/chromium/content/browser/indexed_db/indexed_db_database.cc
index 1e8c19ed949..dfcffedcc18 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database.cc
@@ -21,11 +21,13 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/indexed_db/indexed_db_blob_info.h"
+#include "content/browser/indexed_db/indexed_db_callback_helpers.h"
#include "content/browser/indexed_db/indexed_db_class_factory.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_cursor.h"
#include "content/browser/indexed_db/indexed_db_factory.h"
+#include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/indexed_db_index_writer.h"
#include "content/browser/indexed_db/indexed_db_metadata_coding.h"
#include "content/browser/indexed_db/indexed_db_pending_connection.h"
@@ -84,6 +86,20 @@ HistogramIDBKeyPathType HistogramKeyPathType(const IndexedDBKeyPath& key_path) {
return KEY_PATH_TYPE_NONE;
}
+IndexedDBDatabaseError CreateError(uint16_t code,
+ const char* message,
+ IndexedDBTransaction* transaction) {
+ transaction->IncrementNumErrorsSent();
+ return IndexedDBDatabaseError(code, message);
+}
+
+IndexedDBDatabaseError CreateError(uint16_t code,
+ const base::string16& message,
+ IndexedDBTransaction* transaction) {
+ transaction->IncrementNumErrorsSent();
+ return IndexedDBDatabaseError(code, message);
+}
+
} // namespace
// This represents what script calls an 'IDBOpenDBRequest' - either a database
@@ -92,7 +108,10 @@ HistogramIDBKeyPathType HistogramKeyPathType(const IndexedDBKeyPath& key_path) {
// expecting a further callback.
class IndexedDBDatabase::ConnectionRequest {
public:
- explicit ConnectionRequest(scoped_refptr<IndexedDBDatabase> db) : db_(db) {}
+ ConnectionRequest(IndexedDBOriginStateHandle origin_state_handle,
+ IndexedDBDatabase* db)
+ : origin_state_handle_(std::move(origin_state_handle)),
+ db_(std::move(db)) {}
virtual ~ConnectionRequest() {}
@@ -105,19 +124,28 @@ class IndexedDBDatabase::ConnectionRequest {
// Called when a connection is closed; if it corresponds to this connection,
// need to do cleanup. Otherwise, it may unblock further steps.
+ // |connection| can be null if all connections were closed (see ForceClose).
virtual void OnConnectionClosed(IndexedDBConnection* connection) = 0;
+ // Called when the transaction should be bound.
+ virtual void CreateAndBindTransaction() = 0;
+
// Called when the upgrade transaction has started executing.
virtual void UpgradeTransactionStarted(int64_t old_version) = 0;
// Called when the upgrade transaction has finished.
virtual void UpgradeTransactionFinished(bool committed) = 0;
- // Called for pending tasks that we need to clear for a force close.
- virtual void AbortForForceClose() = 0;
+ // Called for pending tasks that we need to clear for a force close. Returns
+ // if the request should still execute after all the connections are
+ // removed. This is not called for the active request - instead,
+ // OnConnectionClosed is called with a nullptr |connection|.
+ virtual bool OnForceClose() = 0;
protected:
- scoped_refptr<IndexedDBDatabase> db_;
+ IndexedDBOriginStateHandle origin_state_handle_;
+ // This is safe because IndexedDBDatabase owns this object.
+ IndexedDBDatabase* db_;
private:
DISALLOW_COPY_AND_ASSIGN(ConnectionRequest);
@@ -126,9 +154,10 @@ class IndexedDBDatabase::ConnectionRequest {
class IndexedDBDatabase::OpenRequest
: public IndexedDBDatabase::ConnectionRequest {
public:
- OpenRequest(scoped_refptr<IndexedDBDatabase> db,
+ OpenRequest(IndexedDBOriginStateHandle origin_state_handle,
+ IndexedDBDatabase* db,
std::unique_ptr<IndexedDBPendingConnection> pending_connection)
- : ConnectionRequest(db),
+ : ConnectionRequest(std::move(origin_state_handle), db),
pending_(std::move(pending_connection)),
weak_factory_(this) {}
@@ -166,7 +195,8 @@ class IndexedDBDatabase::OpenRequest
// DEFAULT_VERSION throws exception.)
DCHECK(is_new_database);
pending_->callbacks->OnSuccess(
- db_->CreateConnection(pending_->database_callbacks,
+ db_->CreateConnection(std::move(origin_state_handle_),
+ pending_->database_callbacks,
pending_->child_process_id),
db_->metadata_);
db_->RequestComplete(this);
@@ -177,7 +207,8 @@ class IndexedDBDatabase::OpenRequest
(new_version == old_version ||
new_version == IndexedDBDatabaseMetadata::NO_VERSION)) {
pending_->callbacks->OnSuccess(
- db_->CreateConnection(pending_->database_callbacks,
+ db_->CreateConnection(std::move(origin_state_handle_),
+ pending_->database_callbacks,
pending_->child_process_id),
db_->metadata_);
db_->RequestComplete(this);
@@ -205,12 +236,12 @@ class IndexedDBDatabase::OpenRequest
// Requested version is higher than current version - upgrade needed.
DCHECK_GT(new_version, old_version);
- if (db_->connections_.empty()) {
+ if (db_->HasNoConnections()) {
std::vector<ScopesLockManager::ScopeLockRequest> lock_requests = {
{kDatabaseRangeLockLevel, GetDatabaseLockRange(db_->metadata_.id),
ScopesLockManager::LockType::kExclusive}};
db_->lock_manager_->AcquireLocks(
- std::move(lock_requests),
+ std::move(lock_requests), lock_receiver_.weak_factory.GetWeakPtr(),
base::BindOnce(&IndexedDBDatabase::OpenRequest::StartUpgrade,
weak_factory_.GetWeakPtr()));
return;
@@ -223,8 +254,7 @@ class IndexedDBDatabase::OpenRequest
// "versionchange" event was ignored.
DCHECK_NE(pending_->data_loss_info.status,
blink::mojom::IDBDataLoss::Total);
- for (const auto* connection : db_->connections_)
- connection->callbacks()->OnVersionChange(old_version, new_version);
+ db_->SendVersionChangeToAllConnections(old_version, new_version);
// When all connections have closed the upgrade can proceed.
}
@@ -234,6 +264,13 @@ class IndexedDBDatabase::OpenRequest
}
void OnConnectionClosed(IndexedDBConnection* connection) override {
+ if (!connection) {
+ pending_->callbacks->OnError(
+ IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionAbortError,
+ "All connections were closed."));
+ db_->RequestComplete(this);
+ return;
+ }
// This connection closed prematurely; signal an error and complete.
if (connection && connection->callbacks() == pending_->database_callbacks) {
pending_->callbacks->OnError(
@@ -243,14 +280,14 @@ class IndexedDBDatabase::OpenRequest
return;
}
- if (!db_->connections_.empty())
+ if (!db_->HasNoConnections())
return;
std::vector<ScopesLockManager::ScopeLockRequest> lock_requests = {
{kDatabaseRangeLockLevel, GetDatabaseLockRange(db_->metadata_.id),
ScopesLockManager::LockType::kExclusive}};
db_->lock_manager_->AcquireLocks(
- std::move(lock_requests),
+ std::move(lock_requests), lock_receiver_.weak_factory.GetWeakPtr(),
base::BindOnce(&IndexedDBDatabase::OpenRequest::StartUpgrade,
weak_factory_.GetWeakPtr()));
}
@@ -258,8 +295,10 @@ class IndexedDBDatabase::OpenRequest
// Initiate the upgrade. The bulk of the work actually happens in
// IndexedDBDatabase::VersionChangeOperation in order to kick the
// transaction into the correct state.
- void StartUpgrade(std::vector<ScopeLock> locks) {
- connection_ = db_->CreateConnection(pending_->database_callbacks,
+ void StartUpgrade() {
+ DCHECK(!lock_receiver_.locks.empty());
+ connection_ = db_->CreateConnection(std::move(origin_state_handle_),
+ pending_->database_callbacks,
pending_->child_process_id);
DCHECK_EQ(db_->connections_.count(connection_.get()), 1UL);
@@ -271,13 +310,22 @@ class IndexedDBDatabase::OpenRequest
blink::mojom::IDBTransactionMode::VersionChange,
new IndexedDBBackingStore::Transaction(db_->backing_store()));
- std::move(pending_->create_transaction_callback)
- .Run(transaction->AsWeakPtr());
+ // Save a WeakPtr<IndexedDBTransaction> for the CreateAndBindTransaction
+ // function to use later.
+ pending_->transaction = transaction->AsWeakPtr();
+
+ transaction->ScheduleTask(BindWeakOperation(
+ &IndexedDBDatabase::VersionChangeOperation, db_->AsWeakPtr(),
+ pending_->version, pending_->callbacks));
+ transaction->locks_receiver()->locks = std::move(lock_receiver_.locks);
+ transaction->Start();
+ }
- transaction->ScheduleTask(
- base::BindOnce(&IndexedDBDatabase::VersionChangeOperation, db_,
- pending_->version, pending_->callbacks));
- transaction->Start(std::move(locks));
+ void CreateAndBindTransaction() override {
+ if (pending_->create_transaction_callback && pending_->transaction) {
+ std::move(pending_->create_transaction_callback)
+ .Run(std::move(pending_->transaction));
+ }
}
// Called when the upgrade transaction has started executing.
@@ -304,13 +352,16 @@ class IndexedDBDatabase::OpenRequest
db_->RequestComplete(this);
}
- void AbortForForceClose() override {
+ bool OnForceClose() override {
DCHECK(!connection_);
pending_->database_callbacks->OnForcedClose();
pending_.reset();
+ return false;
}
private:
+ ScopesLocksHolder lock_receiver_;
+
std::unique_ptr<IndexedDBPendingConnection> pending_;
// If an upgrade is needed, holds the pending connection until ownership is
@@ -324,12 +375,17 @@ class IndexedDBDatabase::OpenRequest
class IndexedDBDatabase::DeleteRequest
: public IndexedDBDatabase::ConnectionRequest {
public:
- DeleteRequest(scoped_refptr<IndexedDBDatabase> db,
- scoped_refptr<IndexedDBCallbacks> callbacks)
- : ConnectionRequest(db), callbacks_(callbacks), weak_factory_(this) {}
+ DeleteRequest(IndexedDBOriginStateHandle origin_state_handle,
+ IndexedDBDatabase* db,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ base::OnceClosure on_database_deleted)
+ : ConnectionRequest(std::move(origin_state_handle), db),
+ callbacks_(callbacks),
+ on_database_deleted_(std::move(on_database_deleted)),
+ weak_factory_(this) {}
void Perform() override {
- if (db_->connections_.empty()) {
+ if (db_->HasNoConnections()) {
// No connections, so delete immediately.
DoDelete();
return;
@@ -339,8 +395,7 @@ class IndexedDBDatabase::DeleteRequest
// close_pending set.
const int64_t old_version = db_->metadata_.version;
const int64_t new_version = IndexedDBDatabaseMetadata::NO_VERSION;
- for (const auto* connection : db_->connections_)
- connection->callbacks()->OnVersionChange(old_version, new_version);
+ db_->SendVersionChangeToAllConnections(old_version, new_version);
}
void OnVersionChangeIgnored() const override {
@@ -348,7 +403,7 @@ class IndexedDBDatabase::DeleteRequest
}
void OnConnectionClosed(IndexedDBConnection* connection) override {
- if (!db_->connections_.empty())
+ if (!db_->HasNoConnections())
return;
DoDelete();
@@ -363,12 +418,11 @@ class IndexedDBDatabase::DeleteRequest
IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError,
"Internal error deleting database.");
callbacks_->OnError(error);
- if (s.IsCorruption()) {
- url::Origin origin = db_->backing_store_->origin();
- db_->backing_store_ = nullptr;
- db_->factory_->HandleBackingStoreCorruption(origin, error);
- }
- db_->RequestComplete(this);
+
+ base::WeakPtr<IndexedDBDatabase> database = db_->AsWeakPtr();
+ db_->error_callback_.Run(s, "Internal error deleting database.");
+ if (database)
+ database->RequestComplete(this);
return;
}
@@ -378,50 +432,56 @@ class IndexedDBDatabase::DeleteRequest
db_->metadata_.max_object_store_id = kInvalidId;
db_->metadata_.object_stores.clear();
callbacks_->OnSuccess(old_version);
- db_->factory_->DatabaseDeleted(db_->identifier_);
+ std::move(on_database_deleted_).Run();
db_->RequestComplete(this);
}
+ void CreateAndBindTransaction() override { NOTREACHED(); }
+
void UpgradeTransactionStarted(int64_t old_version) override { NOTREACHED(); }
void UpgradeTransactionFinished(bool committed) override { NOTREACHED(); }
- void AbortForForceClose() override {
- IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError,
- "The request could not be completed.");
- callbacks_->OnError(error);
- callbacks_ = nullptr;
- }
+ // The delete requests should always be run during force close.
+ bool OnForceClose() override { return true; }
private:
scoped_refptr<IndexedDBCallbacks> callbacks_;
+ base::OnceClosure on_database_deleted_;
base::WeakPtrFactory<DeleteRequest> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DeleteRequest);
};
-std::tuple<scoped_refptr<IndexedDBDatabase>, Status> IndexedDBDatabase::Create(
+// static
+std::tuple<std::unique_ptr<IndexedDBDatabase>, Status>
+IndexedDBDatabase::Create(
const base::string16& name,
- scoped_refptr<IndexedDBBackingStore> backing_store,
- scoped_refptr<IndexedDBFactory> factory,
+ IndexedDBBackingStore* backing_store,
+ IndexedDBFactory* factory,
+ ErrorCallback error_callback,
+ base::OnceClosure destroy_me,
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
const Identifier& unique_identifier,
ScopesLockManager* transaction_lock_manager) {
- scoped_refptr<IndexedDBDatabase> database =
+ std::unique_ptr<IndexedDBDatabase> database =
IndexedDBClassFactory::Get()->CreateIndexedDBDatabase(
- name, backing_store, factory, std::move(metadata_coding),
- unique_identifier, transaction_lock_manager);
+ name, backing_store, factory, std::move(error_callback),
+ std::move(destroy_me), std::move(metadata_coding), unique_identifier,
+ transaction_lock_manager);
Status s = database->OpenInternal();
if (!s.ok())
database = nullptr;
- return std::tie(database, s);
+ return {std::move(database), s};
}
IndexedDBDatabase::IndexedDBDatabase(
const base::string16& name,
- scoped_refptr<IndexedDBBackingStore> backing_store,
- scoped_refptr<IndexedDBFactory> factory,
+ IndexedDBBackingStore* backing_store,
+ IndexedDBFactory* factory,
+ ErrorCallback error_callback,
+ base::OnceClosure destroy_me,
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
const Identifier& unique_identifier,
ScopesLockManager* transaction_lock_manager)
@@ -433,10 +493,20 @@ IndexedDBDatabase::IndexedDBDatabase(
identifier_(unique_identifier),
factory_(factory),
metadata_coding_(std::move(metadata_coding)),
- lock_manager_(transaction_lock_manager) {
+ lock_manager_(transaction_lock_manager),
+ error_callback_(std::move(error_callback)),
+ destroy_me_(std::move(destroy_me)) {
+ DCHECK(destroy_me_);
DCHECK(factory != nullptr);
}
+IndexedDBDatabase::~IndexedDBDatabase() {
+ DCHECK(!active_request_);
+ DCHECK(pending_requests_.empty());
+ DCHECK(connections_.empty())
+ << "Cannot destroy a database that has connections";
+}
+
void IndexedDBDatabase::AddObjectStore(
IndexedDBObjectStoreMetadata object_store,
int64_t new_max_object_store_id) {
@@ -503,11 +573,6 @@ Status IndexedDBDatabase::OpenInternal() {
metadata_.version, &metadata_);
}
-IndexedDBDatabase::~IndexedDBDatabase() {
- DCHECK(!active_request_);
- DCHECK(pending_requests_.empty());
-}
-
// kIDBMaxMessageSize is defined based on the original
// IPC::Channel::kMaximumMessageSize value. We use kIDBMaxMessageSize to limit
// the size of arguments we pass into our Mojo calls. We want to ensure this
@@ -523,16 +588,67 @@ size_t IndexedDBDatabase::GetUsableMessageSizeInBytes() const {
}
std::unique_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection(
+ IndexedDBOriginStateHandle origin_state_handle,
scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
int child_process_id) {
- std::unique_ptr<IndexedDBConnection> connection(
- std::make_unique<IndexedDBConnection>(child_process_id, this,
- database_callbacks));
+ std::unique_ptr<IndexedDBConnection> connection =
+ std::make_unique<IndexedDBConnection>(
+ child_process_id, std::move(origin_state_handle),
+ weak_factory_.GetWeakPtr(),
+ base::BindRepeating(&IndexedDBDatabase::VersionChangeIgnored,
+ weak_factory_.GetWeakPtr()),
+ base::BindOnce(&IndexedDBDatabase::ConnectionClosed,
+ weak_factory_.GetWeakPtr()),
+ error_callback_, database_callbacks);
connections_.insert(connection.get());
backing_store_->GrantChildProcessPermissions(child_process_id);
return connection;
}
+void IndexedDBDatabase::VersionChangeIgnored() {
+ if (active_request_)
+ active_request_->OnVersionChangeIgnored();
+}
+
+bool IndexedDBDatabase::HasNoConnections() const {
+ return force_closing_ || connections_.empty();
+}
+
+void IndexedDBDatabase::SendVersionChangeToAllConnections(int64_t old_version,
+ int64_t new_version) {
+ if (force_closing_)
+ return;
+ for (const auto* connection : connections_)
+ connection->callbacks()->OnVersionChange(old_version, new_version);
+}
+
+void IndexedDBDatabase::ConnectionClosed(IndexedDBConnection* connection) {
+ if (force_closing_)
+ return;
+ DCHECK(connections_.count(connection));
+ DCHECK(connection->IsConnected());
+ DCHECK(connection->transactions().empty());
+ DCHECK(connection->database().get() == this);
+
+ IDB_TRACE("IndexedDBDatabase::Close");
+
+ // Abort transactions before removing the connection; aborting may complete
+ // an upgrade, and thus allow the next open/delete requests to proceed. The
+ // new active_request_ should see the old connection count until explicitly
+ // notified below.
+ connections_.erase(connection);
+
+ base::WeakPtr<IndexedDBDatabase> database = weak_factory_.GetWeakPtr();
+ // Notify the active request, which may need to do cleanup or proceed with
+ // the operation. This may trigger other work, such as more connections or
+ // deletions, so |active_request_| itself may change.
+ if (active_request_)
+ active_request_->OnConnectionClosed(connection);
+
+ if (database)
+ ProcessRequestQueueAndMaybeRelease();
+}
+
bool IndexedDBDatabase::ValidateObjectStoreId(int64_t object_store_id) const {
if (!base::ContainsKey(metadata_.object_stores, object_store_id)) {
DLOG(ERROR) << "Invalid object_store_id";
@@ -620,14 +736,15 @@ void IndexedDBDatabase::CreateObjectStore(IndexedDBTransaction* transaction,
auto_increment, &object_store_metadata);
if (!s.ok()) {
- ReportErrorWithDetails(s, "Internal error creating object store.");
+ error_callback_.Run(s, "Internal error creating object store.");
return;
}
AddObjectStore(std::move(object_store_metadata), object_store_id);
+
transaction->ScheduleAbortTask(
- base::BindOnce(&IndexedDBDatabase::CreateObjectStoreAbortOperation, this,
- object_store_id));
+ base::BindOnce(&IndexedDBDatabase::CreateObjectStoreAbortOperation,
+ AsWeakPtr(), object_store_id));
}
void IndexedDBDatabase::DeleteObjectStore(IndexedDBTransaction* transaction,
@@ -641,8 +758,9 @@ void IndexedDBDatabase::DeleteObjectStore(IndexedDBTransaction* transaction,
if (!ValidateObjectStoreId(object_store_id))
return;
- transaction->ScheduleTask(base::BindOnce(
- &IndexedDBDatabase::DeleteObjectStoreOperation, this, object_store_id));
+ transaction->ScheduleTask(
+ BindWeakOperation(&IndexedDBDatabase::DeleteObjectStoreOperation,
+ AsWeakPtr(), object_store_id));
}
void IndexedDBDatabase::RenameObjectStore(IndexedDBTransaction* transaction,
@@ -671,14 +789,14 @@ void IndexedDBDatabase::RenameObjectStore(IndexedDBTransaction* transaction,
&object_store_metadata);
if (!s.ok()) {
- ReportErrorWithDetails(s, "Internal error renaming object store.");
+ error_callback_.Run(s, "Internal error renaming object store.");
return;
}
DCHECK_EQ(object_store_metadata.name, new_name);
transaction->ScheduleAbortTask(
- base::BindOnce(&IndexedDBDatabase::RenameObjectStoreAbortOperation, this,
- object_store_id, std::move(old_name)));
+ base::BindOnce(&IndexedDBDatabase::RenameObjectStoreAbortOperation,
+ AsWeakPtr(), object_store_id, std::move(old_name)));
}
void IndexedDBDatabase::CreateIndex(IndexedDBTransaction* transaction,
@@ -726,7 +844,7 @@ void IndexedDBDatabase::CreateIndex(IndexedDBTransaction* transaction,
AddIndex(object_store_id, std::move(index_metadata), index_id);
transaction->ScheduleAbortTask(
- base::BindOnce(&IndexedDBDatabase::CreateIndexAbortOperation, this,
+ base::BindOnce(&IndexedDBDatabase::CreateIndexAbortOperation, AsWeakPtr(),
object_store_id, index_id));
}
@@ -748,8 +866,8 @@ void IndexedDBDatabase::DeleteIndex(IndexedDBTransaction* transaction,
return;
transaction->ScheduleTask(
- base::BindOnce(&IndexedDBDatabase::DeleteIndexOperation, this,
- object_store_id, index_id));
+ BindWeakOperation(&IndexedDBDatabase::DeleteIndexOperation, AsWeakPtr(),
+ object_store_id, index_id));
}
Status IndexedDBDatabase::DeleteIndexOperation(
@@ -779,7 +897,7 @@ Status IndexedDBDatabase::DeleteIndexOperation(
}
transaction->ScheduleAbortTask(
- base::BindOnce(&IndexedDBDatabase::DeleteIndexAbortOperation, this,
+ base::BindOnce(&IndexedDBDatabase::DeleteIndexAbortOperation, AsWeakPtr(),
object_store_id, std::move(index_metadata)));
return s;
}
@@ -821,13 +939,13 @@ void IndexedDBDatabase::RenameIndex(IndexedDBTransaction* transaction,
&index_metadata);
if (!s.ok()) {
- ReportErrorWithDetails(s, "Internal error renaming index.");
+ error_callback_.Run(s, "Internal error renaming index.");
return;
}
DCHECK_EQ(index_metadata.name, new_name);
transaction->ScheduleAbortTask(
- base::BindOnce(&IndexedDBDatabase::RenameIndexAbortOperation, this,
+ base::BindOnce(&IndexedDBDatabase::RenameIndexAbortOperation, AsWeakPtr(),
object_store_id, index_id, std::move(old_name)));
}
@@ -851,10 +969,12 @@ void IndexedDBDatabase::Commit(IndexedDBTransaction* transaction) {
// been dispatched to the frontend, so it will find out about that
// asynchronously.
if (transaction) {
- scoped_refptr<IndexedDBFactory> factory = factory_;
+ // The database can be destroyed in the call to Commit(), so save a copy of
+ // the error callback in case of an error.
+ auto error_callback_copy = error_callback_;
Status result = transaction->Commit();
if (!result.ok())
- ReportError(result);
+ error_callback_copy.Run(result, nullptr);
}
}
@@ -918,24 +1038,39 @@ void IndexedDBDatabase::SendObservations(
}
}
-void IndexedDBDatabase::GetAll(IndexedDBTransaction* transaction,
- int64_t object_store_id,
- int64_t index_id,
- std::unique_ptr<IndexedDBKeyRange> key_range,
- bool key_only,
- int64_t max_count,
- scoped_refptr<IndexedDBCallbacks> callbacks) {
+void IndexedDBDatabase::GetAll(
+ base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
+ IndexedDBTransaction* transaction,
+ int64_t object_store_id,
+ int64_t index_id,
+ std::unique_ptr<IndexedDBKeyRange> key_range,
+ bool key_only,
+ int64_t max_count,
+ blink::mojom::IDBDatabase::GetAllCallback callback) {
DCHECK(transaction);
IDB_TRACE1("IndexedDBDatabase::GetAll", "txn.id", transaction->id());
- if (!ValidateObjectStoreId(object_store_id))
+ if (!ValidateObjectStoreId(object_store_id)) {
+ IndexedDBDatabaseError error =
+ CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
+ "Unknown error", transaction);
+ std::move(callback).Run(
+ blink::mojom::IDBDatabaseGetAllResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
return;
+ }
+
+ blink::mojom::IDBDatabase::GetAllCallback aborting_callback =
+ CreateCallbackAbortOnDestruct<blink::mojom::IDBDatabase::GetAllCallback,
+ blink::mojom::IDBDatabaseGetAllResultPtr>(
+ std::move(callback), transaction->AsWeakPtr());
- transaction->ScheduleTask(base::BindOnce(
- &IndexedDBDatabase::GetAllOperation, this, object_store_id, index_id,
+ transaction->ScheduleTask(BindWeakOperation(
+ &IndexedDBDatabase::GetAllOperation, AsWeakPtr(),
+ std::move(dispatcher_host), object_store_id, index_id,
std::move(key_range),
key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
- max_count, callbacks));
+ max_count, std::move(aborting_callback)));
}
void IndexedDBDatabase::Get(IndexedDBTransaction* transaction,
@@ -950,8 +1085,8 @@ void IndexedDBDatabase::Get(IndexedDBTransaction* transaction,
if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
return;
- transaction->ScheduleTask(base::BindOnce(
- &IndexedDBDatabase::GetOperation, this, object_store_id, index_id,
+ transaction->ScheduleTask(BindWeakOperation(
+ &IndexedDBDatabase::GetOperation, AsWeakPtr(), object_store_id, index_id,
std::move(key_range),
key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
callbacks));
@@ -1085,12 +1220,13 @@ static_assert(blink::mojom::kIDBMaxMessageOverhead <= INT32_MAX,
"kIDBMaxMessageOverhead is more than INT32_MAX");
Status IndexedDBDatabase::GetAllOperation(
+ base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
int64_t object_store_id,
int64_t index_id,
std::unique_ptr<IndexedDBKeyRange> key_range,
indexed_db::CursorType cursor_type,
int64_t max_count,
- scoped_refptr<IndexedDBCallbacks> callbacks,
+ blink::mojom::IDBDatabase::GetAllCallback callback,
IndexedDBTransaction* transaction) {
IDB_TRACE1("IndexedDBDatabase::GetAllOperation", "txn.id", transaction->id());
@@ -1102,6 +1238,15 @@ Status IndexedDBDatabase::GetAllOperation(
metadata_.object_stores[object_store_id];
Status s = Status::OK();
+ if (!dispatcher_host) {
+ IndexedDBDatabaseError error =
+ CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
+ "Unknown error", transaction);
+ std::move(callback).Run(
+ blink::mojom::IDBDatabaseGetAllResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
+ return s;
+ }
std::unique_ptr<IndexedDBBackingStore::Cursor> cursor;
@@ -1135,6 +1280,12 @@ Status IndexedDBDatabase::GetAllOperation(
if (!s.ok()) {
DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString();
+ IndexedDBDatabaseError error =
+ CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
+ "Corruption detected, unable to continue", transaction);
+ std::move(callback).Run(
+ blink::mojom::IDBDatabaseGetAllResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
return s;
}
@@ -1143,7 +1294,9 @@ Status IndexedDBDatabase::GetAllOperation(
if (!cursor) {
// Doesn't matter if key or value array here - will be empty array when it
// hits JavaScript.
- callbacks->OnSuccessArray(&found_values);
+ std::vector<blink::mojom::IDBReturnValuePtr> mojo_found_values;
+ std::move(callback).Run(blink::mojom::IDBDatabaseGetAllResult::NewValues(
+ std::move(mojo_found_values)));
return s;
}
@@ -1161,8 +1314,15 @@ Status IndexedDBDatabase::GetAllOperation(
cursor_valid = cursor->FirstSeek(&s);
did_first_seek = true;
}
- if (!s.ok())
+ if (!s.ok()) {
+ IndexedDBDatabaseError error =
+ CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
+ "Seek failure, unable to continue", transaction);
+ std::move(callback).Run(
+ blink::mojom::IDBDatabaseGetAllResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
return s;
+ }
if (!cursor_valid)
break;
@@ -1186,9 +1346,12 @@ Status IndexedDBDatabase::GetAllOperation(
else
response_size += return_value.SizeEstimate();
if (response_size > GetUsableMessageSizeInBytes()) {
- callbacks->OnError(
+ IndexedDBDatabaseError error =
CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
- "Maximum IPC message size exceeded.", transaction));
+ "Maximum IPC message size exceeded.", transaction);
+ std::move(callback).Run(
+ blink::mojom::IDBDatabaseGetAllResult::NewErrorResult(
+ blink::mojom::IDBError::New(error.code(), error.message())));
return s;
}
@@ -1201,10 +1364,32 @@ Status IndexedDBDatabase::GetAllOperation(
if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
// IndexedDBKey already supports an array of values so we can leverage this
// to return an array of keys - no need to create our own array of keys.
- callbacks->OnSuccess(IndexedDBKey(std::move(found_keys)));
- } else {
- callbacks->OnSuccessArray(&found_values);
+ std::move(callback).Run(blink::mojom::IDBDatabaseGetAllResult::NewKey(
+ IndexedDBKey(std::move(found_keys))));
+ return s;
+ }
+
+ std::vector<blink::mojom::IDBReturnValuePtr> mojo_values;
+ mojo_values.reserve(found_values.size());
+ for (size_t i = 0; i < found_values.size(); ++i) {
+ mojo_values.push_back(
+ IndexedDBReturnValue::ConvertReturnValue(&found_values[i]));
+ }
+
+ std::vector<IndexedDBCallbacks::IndexedDBValueBlob> value_blobs;
+ for (size_t i = 0; i < mojo_values.size(); ++i) {
+ IndexedDBCallbacks::IndexedDBValueBlob::GetIndexedDBValueBlobs(
+ &value_blobs, found_values[i].blob_info,
+ &mojo_values[i]->value->blob_or_file_info);
}
+
+ if (!IndexedDBCallbacks::CreateAllBlobs(
+ dispatcher_host->blob_storage_context(), std::move(value_blobs))) {
+ return s;
+ }
+
+ std::move(callback).Run(
+ blink::mojom::IDBDatabaseGetAllResult::NewValues(std::move(mojo_values)));
return s;
}
@@ -1287,8 +1472,8 @@ void IndexedDBDatabase::Put(IndexedDBTransaction* transaction,
params->put_mode = put_mode;
params->callbacks = callbacks;
params->index_keys = index_keys;
- transaction->ScheduleTask(base::BindOnce(&IndexedDBDatabase::PutOperation,
- this, std::move(params)));
+ transaction->ScheduleTask(BindWeakOperation(&IndexedDBDatabase::PutOperation,
+ AsWeakPtr(), std::move(params)));
}
Status IndexedDBDatabase::PutOperation(
@@ -1309,8 +1494,8 @@ Status IndexedDBDatabase::PutOperation(
std::unique_ptr<IndexedDBKey> key;
if (params->put_mode != blink::mojom::IDBPutMode::CursorUpdate &&
object_store.auto_increment && !params->key->IsValid()) {
- std::unique_ptr<IndexedDBKey> auto_inc_key = GenerateKey(
- backing_store_.get(), transaction, id(), params->object_store_id);
+ std::unique_ptr<IndexedDBKey> auto_inc_key =
+ GenerateKey(backing_store_, transaction, id(), params->object_store_id);
key_was_generated = true;
if (!auto_inc_key->IsValid()) {
params->callbacks->OnError(
@@ -1344,10 +1529,9 @@ Status IndexedDBDatabase::PutOperation(
std::vector<std::unique_ptr<IndexWriter>> index_writers;
base::string16 error_message;
bool obeys_constraints = false;
- bool backing_store_success =
- MakeIndexWriters(transaction, backing_store_.get(), id(), object_store,
- *key, key_was_generated, params->index_keys,
- &index_writers, &error_message, &obeys_constraints);
+ bool backing_store_success = MakeIndexWriters(
+ transaction, backing_store_, id(), object_store, *key, key_was_generated,
+ params->index_keys, &index_writers, &error_message, &obeys_constraints);
if (!backing_store_success) {
params->callbacks->OnError(
CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
@@ -1374,7 +1558,7 @@ Status IndexedDBDatabase::PutOperation(
IDB_TRACE1("IndexedDBDatabase::PutOperation.UpdateIndexes", "txn.id",
transaction->id());
for (const auto& writer : index_writers) {
- writer->WriteIndexKeys(record_identifier, backing_store_.get(),
+ writer->WriteIndexKeys(record_identifier, backing_store_,
transaction->BackingStoreTransaction(), id(),
params->object_store_id);
}
@@ -1385,7 +1569,7 @@ Status IndexedDBDatabase::PutOperation(
key->type() == blink::mojom::IDBKeyType::Number) {
IDB_TRACE1("IndexedDBDatabase::PutOperation.AutoIncrement", "txn.id",
transaction->id());
- s = UpdateKeyGenerator(backing_store_.get(), transaction, id(),
+ s = UpdateKeyGenerator(backing_store_, transaction, id(),
params->object_store_id, *key, !key_was_generated);
if (!s.ok())
return s;
@@ -1428,7 +1612,7 @@ void IndexedDBDatabase::SetIndexKeys(
transaction->BackingStoreTransaction(), metadata_.id, object_store_id,
*primary_key, &record_identifier, &found);
if (!s.ok()) {
- ReportErrorWithDetails(s, "Internal error setting index keys.");
+ error_callback_.Run(s, "Internal error setting index keys.");
return;
}
if (!found) {
@@ -1445,10 +1629,9 @@ void IndexedDBDatabase::SetIndexKeys(
metadata_.object_stores.end());
const IndexedDBObjectStoreMetadata& object_store_metadata =
metadata_.object_stores[object_store_id];
- bool backing_store_success =
- MakeIndexWriters(transaction, backing_store_.get(), id(),
- object_store_metadata, *primary_key, false, index_keys,
- &index_writers, &error_message, &obeys_constraints);
+ bool backing_store_success = MakeIndexWriters(
+ transaction, backing_store_, id(), object_store_metadata, *primary_key,
+ false, index_keys, &index_writers, &error_message, &obeys_constraints);
if (!backing_store_success) {
transaction->Abort(IndexedDBDatabaseError(
blink::kWebIDBDatabaseExceptionUnknownError,
@@ -1462,7 +1645,7 @@ void IndexedDBDatabase::SetIndexKeys(
}
for (const auto& writer : index_writers) {
- writer->WriteIndexKeys(record_identifier, backing_store_.get(),
+ writer->WriteIndexKeys(record_identifier, backing_store_,
transaction->BackingStoreTransaction(), id(),
object_store_id);
}
@@ -1477,8 +1660,8 @@ void IndexedDBDatabase::SetIndexesReady(IndexedDBTransaction* transaction,
transaction->ScheduleTask(
blink::mojom::IDBTaskType::Preemptive,
- base::BindOnce(&IndexedDBDatabase::SetIndexesReadyOperation, this,
- index_ids.size()));
+ BindWeakOperation(&IndexedDBDatabase::SetIndexesReadyOperation,
+ AsWeakPtr(), index_ids.size()));
}
Status IndexedDBDatabase::SetIndexesReadyOperation(
@@ -1530,8 +1713,8 @@ void IndexedDBDatabase::OpenCursor(
key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE;
params->task_type = task_type;
params->callbacks = callbacks;
- transaction->ScheduleTask(base::BindOnce(
- &IndexedDBDatabase::OpenCursorOperation, this, std::move(params)));
+ transaction->ScheduleTask(BindWeakOperation(
+ &IndexedDBDatabase::OpenCursorOperation, AsWeakPtr(), std::move(params)));
}
Status IndexedDBDatabase::OpenCursorOperation(
@@ -1605,9 +1788,9 @@ void IndexedDBDatabase::Count(IndexedDBTransaction* transaction,
if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
return;
- transaction->ScheduleTask(base::BindOnce(&IndexedDBDatabase::CountOperation,
- this, object_store_id, index_id,
- std::move(key_range), callbacks));
+ transaction->ScheduleTask(BindWeakOperation(
+ &IndexedDBDatabase::CountOperation, AsWeakPtr(), object_store_id,
+ index_id, std::move(key_range), callbacks));
}
Status IndexedDBDatabase::CountOperation(
@@ -1662,8 +1845,8 @@ void IndexedDBDatabase::DeleteRange(
return;
transaction->ScheduleTask(
- base::BindOnce(&IndexedDBDatabase::DeleteRangeOperation, this,
- object_store_id, std::move(key_range), callbacks));
+ BindWeakOperation(&IndexedDBDatabase::DeleteRangeOperation, AsWeakPtr(),
+ object_store_id, std::move(key_range), callbacks));
}
Status IndexedDBDatabase::DeleteRangeOperation(
@@ -1696,9 +1879,9 @@ void IndexedDBDatabase::GetKeyGeneratorCurrentNumber(
"Object store id not valid.", transaction));
return;
}
- transaction->ScheduleTask(
- base::BindOnce(&IndexedDBDatabase::GetKeyGeneratorCurrentNumberOperation,
- this, object_store_id, callbacks));
+ transaction->ScheduleTask(BindWeakOperation(
+ &IndexedDBDatabase::GetKeyGeneratorCurrentNumberOperation, AsWeakPtr(),
+ object_store_id, callbacks));
}
Status IndexedDBDatabase::GetKeyGeneratorCurrentNumberOperation(
@@ -1706,7 +1889,7 @@ Status IndexedDBDatabase::GetKeyGeneratorCurrentNumberOperation(
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction) {
int64_t current_number;
- Status s = backing_store_.get()->GetKeyGeneratorCurrentNumber(
+ Status s = backing_store_->GetKeyGeneratorCurrentNumber(
transaction->BackingStoreTransaction(), id(), object_store_id,
&current_number);
if (!s.ok()) {
@@ -1729,8 +1912,9 @@ void IndexedDBDatabase::Clear(IndexedDBTransaction* transaction,
if (!ValidateObjectStoreId(object_store_id))
return;
- transaction->ScheduleTask(base::BindOnce(&IndexedDBDatabase::ClearOperation,
- this, object_store_id, callbacks));
+ transaction->ScheduleTask(
+ BindWeakOperation(&IndexedDBDatabase::ClearOperation, AsWeakPtr(),
+ object_store_id, callbacks));
}
Status IndexedDBDatabase::ClearOperation(
@@ -1783,8 +1967,8 @@ Status IndexedDBDatabase::DeleteObjectStoreOperation(
return s;
}
transaction->ScheduleAbortTask(
- base::BindOnce(&IndexedDBDatabase::DeleteObjectStoreAbortOperation, this,
- std::move(object_store_metadata)));
+ base::BindOnce(&IndexedDBDatabase::DeleteObjectStoreAbortOperation,
+ AsWeakPtr(), std::move(object_store_metadata)));
return s;
}
@@ -1801,9 +1985,11 @@ Status IndexedDBDatabase::VersionChangeOperation(
transaction->BackingStoreTransaction()->transaction(), id(), version,
&metadata_);
- transaction->ScheduleAbortTask(base::BindOnce(
- &IndexedDBDatabase::VersionChangeAbortOperation, this, old_version));
+ transaction->ScheduleAbortTask(
+ base::BindOnce(&IndexedDBDatabase::VersionChangeAbortOperation,
+ AsWeakPtr(), old_version));
+ active_request_->CreateAndBindTransaction();
active_request_->UpgradeTransactionStarted(old_version);
return Status::OK();
}
@@ -1829,7 +2015,8 @@ void IndexedDBDatabase::TransactionFinished(
// connections to close, or the actual upgrade transaction from an active
// request. Notify the active request if it's the latter.
if (active_request_ &&
- mode == blink::mojom::IDBTransactionMode::VersionChange) {
+ mode == blink::mojom::IDBTransactionMode::VersionChange &&
+ !force_closing_) {
active_request_->UpgradeTransactionFinished(committed);
}
}
@@ -1839,39 +2026,43 @@ void IndexedDBDatabase::AppendRequest(
pending_requests_.push(std::move(request));
if (!active_request_)
- ProcessRequestQueue();
+ ProcessRequestQueueAndMaybeRelease();
}
void IndexedDBDatabase::RequestComplete(ConnectionRequest* request) {
DCHECK_EQ(request, active_request_.get());
- scoped_refptr<IndexedDBDatabase> protect(this);
+ // Destroying a request can cause this instance to be destroyed (through
+ // ConnectionClosed), so hold a WeakPtr.
+ base::WeakPtr<IndexedDBDatabase> weak_ptr = weak_factory_.GetWeakPtr();
active_request_.reset();
- // Exit early if |active_request_| held the last reference to |this|.
- if (protect->HasOneRef())
+ if (!weak_ptr)
return;
- if (!pending_requests_.empty())
- ProcessRequestQueue();
+ ProcessRequestQueueAndMaybeRelease();
}
-void IndexedDBDatabase::ProcessRequestQueue() {
+void IndexedDBDatabase::ProcessRequestQueueAndMaybeRelease() {
// Don't run re-entrantly to avoid exploding call stacks for requests that
// complete synchronously. The loop below will process requests until one is
// blocked.
if (processing_pending_requests_)
return;
-
- DCHECK(!active_request_);
- DCHECK(!pending_requests_.empty());
-
- base::AutoReset<bool> processing(&processing_pending_requests_, true);
- do {
+ processing_pending_requests_ = true;
+ // If the active request completed synchronously, keep going.
+ while (!active_request_ && !pending_requests_.empty()) {
active_request_ = std::move(pending_requests_.front());
pending_requests_.pop();
active_request_->Perform();
- // If the active request completed synchronously, keep going.
- } while (!active_request_ && !pending_requests_.empty());
+ }
+ processing_pending_requests_ = false;
+ MaybeReleaseDatabase();
+}
+
+void IndexedDBDatabase::MaybeReleaseDatabase() {
+ if (!active_request_ && pending_requests_.empty() && connections_.empty() &&
+ !force_closing_)
+ std::move(destroy_me_).Run();
}
void IndexedDBDatabase::RegisterAndScheduleTransaction(
@@ -1896,83 +2087,57 @@ void IndexedDBDatabase::RegisterAndScheduleTransaction(
}
lock_manager_->AcquireLocks(
std::move(lock_requests),
+ transaction->locks_receiver()->weak_factory.GetWeakPtr(),
base::BindOnce(&IndexedDBTransaction::Start, transaction->AsWeakPtr()));
}
-void IndexedDBDatabase::OpenConnection(
+void IndexedDBDatabase::ScheduleOpenConnection(
+ IndexedDBOriginStateHandle origin_state_handle,
std::unique_ptr<IndexedDBPendingConnection> connection) {
- AppendRequest(std::make_unique<OpenRequest>(this, std::move(connection)));
+ AppendRequest(std::make_unique<OpenRequest>(std::move(origin_state_handle),
+ this, std::move(connection)));
}
-void IndexedDBDatabase::DeleteDatabase(
+void IndexedDBDatabase::ScheduleDeleteDatabase(
+ IndexedDBOriginStateHandle origin_state_handle,
scoped_refptr<IndexedDBCallbacks> callbacks,
- bool force_close) {
- AppendRequest(std::make_unique<DeleteRequest>(this, callbacks));
- // Close the connections only after the request is queued to make sure
- // the store is still open.
- if (force_close)
- ForceClose();
+ base::OnceClosure on_deletion_complete) {
+ AppendRequest(std::make_unique<DeleteRequest>(
+ std::move(origin_state_handle), this, callbacks,
+ std::move(on_deletion_complete)));
}
void IndexedDBDatabase::ForceClose() {
- // IndexedDBConnection::ForceClose() may delete this database, so hold ref.
- scoped_refptr<IndexedDBDatabase> protect(this);
-
+ force_closing_ = true;
+ // Remove all pending requests that don't want to execute during force close
+ // (open requests).
+ base::queue<std::unique_ptr<ConnectionRequest>> requests_to_still_run;
while (!pending_requests_.empty()) {
std::unique_ptr<ConnectionRequest> request =
std::move(pending_requests_.front());
pending_requests_.pop();
- request->AbortForForceClose();
+ if (request->OnForceClose())
+ requests_to_still_run.push(std::move(request));
}
+ if (!requests_to_still_run.empty())
+ pending_requests_ = std::move(requests_to_still_run);
+
+ // Since |force_closing_| is true, there are no re-entry modifications to
+ // this list by ConnectionClosed().
while (!connections_.empty()) {
IndexedDBConnection* connection = *connections_.begin();
- connection->ForceClose();
+ connection->CloseAndReportForceClose();
connections_.erase(connection);
}
- DCHECK(connections_.empty());
- DCHECK(!active_request_);
-}
-
-void IndexedDBDatabase::VersionChangeIgnored() {
- if (active_request_)
- active_request_->OnVersionChangeIgnored();
-}
-
-void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
- DCHECK(connections_.count(connection));
- DCHECK(connection->IsConnected());
- DCHECK(connection->database() == this);
-
- IDB_TRACE("IndexedDBDatabase::Close");
-
- // Abort outstanding transactions from the closing connection. This can not
- // happen if the close is requested by the connection itself as the
- // front-end defers the close until all transactions are complete, but can
- // occur on process termination or forced close.
- connection->FinishAllTransactions(IndexedDBDatabaseError(
- blink::kWebIDBDatabaseExceptionUnknownError, "Connection is closing."));
-
- // Abort transactions before removing the connection; aborting may complete
- // an upgrade, and thus allow the next open/delete requests to proceed. The
- // new active_request_ should see the old connection count until explicitly
- // notified below.
- connections_.erase(connection);
+ force_closing_ = false;
- // Notify the active request, which may need to do cleanup or proceed with
- // the operation. This may trigger other work, such as more connections or
- // deletions, so |active_request_| itself may change.
+ // OnConnectionClosed usually synchronously calls RequestComplete.
if (active_request_)
- active_request_->OnConnectionClosed(connection);
-
- // If there are no more connections (current, active, or pending), tell the
- // factory to clean us up.
- if (connections_.empty() && !active_request_ && pending_requests_.empty()) {
- backing_store_ = nullptr;
- factory_->ReleaseDatabase(identifier_, forced);
- }
+ active_request_->OnConnectionClosed(nullptr);
+ else
+ ProcessRequestQueueAndMaybeRelease();
}
-
void IndexedDBDatabase::CreateObjectStoreAbortOperation(
int64_t object_store_id) {
IDB_TRACE("IndexedDBDatabase::CreateObjectStoreAbortOperation");
@@ -2011,43 +2176,4 @@ void IndexedDBDatabase::AbortAllTransactionsForConnections() {
}
}
-void IndexedDBDatabase::ReportError(Status status) {
- DCHECK(!status.ok());
- if (status.IsCorruption()) {
- IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError,
- base::ASCIIToUTF16(status.ToString()));
- factory_->HandleBackingStoreCorruption(backing_store_->origin(), error);
- } else {
- factory_->HandleBackingStoreFailure(backing_store_->origin());
- }
-}
-
-void IndexedDBDatabase::ReportErrorWithDetails(Status status,
- const char* message) {
- DCHECK(!status.ok());
- if (status.IsCorruption()) {
- IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError,
- message);
- factory_->HandleBackingStoreCorruption(backing_store_->origin(), error);
- } else {
- factory_->HandleBackingStoreFailure(backing_store_->origin());
- }
-}
-
-IndexedDBDatabaseError IndexedDBDatabase::CreateError(
- uint16_t code,
- const char* message,
- IndexedDBTransaction* transaction) {
- transaction->IncrementNumErrorsSent();
- return IndexedDBDatabaseError(code, message);
-}
-
-IndexedDBDatabaseError IndexedDBDatabase::CreateError(
- uint16_t code,
- const base::string16& message,
- IndexedDBTransaction* transaction) {
- transaction->IncrementNumErrorsSent();
- return IndexedDBDatabaseError(code, message);
-}
-
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.h b/chromium/content/browser/indexed_db/indexed_db_database.h
index 5622190dae5..ced3908a31a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.h
+++ b/chromium/content/browser/indexed_db/indexed_db_database.h
@@ -16,14 +16,17 @@
#include <utility>
#include <vector>
+#include "base/callback.h"
#include "base/containers/queue.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/indexed_db/indexed_db.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_observer.h"
+#include "content/browser/indexed_db/indexed_db_origin_state_handle.h"
#include "content/browser/indexed_db/indexed_db_pending_connection.h"
#include "content/browser/indexed_db/list_set.h"
#include "content/browser/indexed_db/scopes/scopes_lock_manager.h"
@@ -50,28 +53,40 @@ class IndexedDBConnection;
class IndexedDBDatabaseCallbacks;
class IndexedDBFactory;
class IndexedDBMetadataCoding;
+class IndexedDBOriginStateHandle;
class IndexedDBTransaction;
struct IndexedDBValue;
-class CONTENT_EXPORT IndexedDBDatabase
- : public base::RefCounted<IndexedDBDatabase> {
+class CONTENT_EXPORT IndexedDBDatabase {
public:
// Identifier is pair of (origin, database name).
using Identifier = std::pair<url::Origin, base::string16>;
+ // Used to report irrecoverable backend errors. The second argument can be
+ // null.
+ using ErrorCallback =
+ base::RepeatingCallback<void(leveldb::Status, const char*)>;
static const int64_t kInvalidId = 0;
static const int64_t kMinimumIndexId = 30;
- static std::tuple<scoped_refptr<IndexedDBDatabase>, leveldb::Status> Create(
+ // |error_callback| is called when a backing store operation has failed. The
+ // database will be closed (IndexedDBFactory::ForceClose) when the callback is
+ // called.
+ // |destroy_me| will destroy the IndexedDBDatabase object.
+ static std::tuple<std::unique_ptr<IndexedDBDatabase>, leveldb::Status> Create(
const base::string16& name,
- scoped_refptr<IndexedDBBackingStore> backing_store,
- scoped_refptr<IndexedDBFactory> factory,
+ IndexedDBBackingStore* backing_store,
+ IndexedDBFactory* factory,
+ ErrorCallback error_callback,
+ base::OnceClosure destroy_me,
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
const Identifier& unique_identifier,
ScopesLockManager* lock_manager);
+ virtual ~IndexedDBDatabase();
+
const Identifier& identifier() const { return identifier_; }
- IndexedDBBackingStore* backing_store() { return backing_store_.get(); }
+ IndexedDBBackingStore* backing_store() { return backing_store_; }
int64_t id() const { return metadata_.id; }
const base::string16& name() const { return metadata_.name; }
@@ -87,9 +102,13 @@ class CONTENT_EXPORT IndexedDBDatabase
blink::IndexedDBIndexMetadata RemoveIndex(int64_t object_store_id,
int64_t index_id);
- void OpenConnection(std::unique_ptr<IndexedDBPendingConnection> connection);
- void DeleteDatabase(scoped_refptr<IndexedDBCallbacks> callbacks,
- bool force_close);
+ void ScheduleOpenConnection(
+ IndexedDBOriginStateHandle origin_state_handle,
+ std::unique_ptr<IndexedDBPendingConnection> connection);
+ void ScheduleDeleteDatabase(IndexedDBOriginStateHandle origin_state_handle,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ base::OnceClosure on_deletion_complete);
+
const blink::IndexedDBDatabaseMetadata& metadata() const { return metadata_; }
void CreateObjectStore(IndexedDBTransaction* transaction,
@@ -106,13 +125,11 @@ class CONTENT_EXPORT IndexedDBDatabase
// TODO(dmurph): Remove this method and have transactions be directly
// scheduled using the lock manager.
void RegisterAndScheduleTransaction(IndexedDBTransaction* transaction);
- void Close(IndexedDBConnection* connection, bool forced);
- void ForceClose();
- // Ack that one of the connections notified with a "versionchange" event did
- // not promptly close. Therefore a "blocked" event should be fired at the
- // pending connection.
- void VersionChangeIgnored();
+ // The database object (this object) must be kept alive for the duration of
+ // this call. This means the caller should own an IndexedDBOriginStateHandle
+ // while caling this methods.
+ void ForceClose();
void Commit(IndexedDBTransaction* transaction);
@@ -161,13 +178,14 @@ class CONTENT_EXPORT IndexedDBDatabase
std::unique_ptr<blink::IndexedDBKeyRange> key_range,
bool key_only,
scoped_refptr<IndexedDBCallbacks> callbacks);
- void GetAll(IndexedDBTransaction* transaction,
+ void GetAll(base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
+ IndexedDBTransaction* transaction,
int64_t object_store_id,
int64_t index_id,
std::unique_ptr<blink::IndexedDBKeyRange> key_range,
bool key_only,
int64_t max_count,
- scoped_refptr<IndexedDBCallbacks> callbacks);
+ blink::mojom::IDBDatabase::GetAllCallback callback);
void Put(IndexedDBTransaction* transaction,
int64_t object_store_id,
IndexedDBValue* value,
@@ -248,12 +266,13 @@ class CONTENT_EXPORT IndexedDBDatabase
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction);
leveldb::Status GetAllOperation(
+ base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
int64_t object_store_id,
int64_t index_id,
std::unique_ptr<blink::IndexedDBKeyRange> key_range,
indexed_db::CursorType cursor_type,
int64_t max_count,
- scoped_refptr<IndexedDBCallbacks> callbacks,
+ blink::mojom::IDBDatabase::GetAllCallback callback,
IndexedDBTransaction* transaction);
struct PutOperationParams;
leveldb::Status PutOperation(std::unique_ptr<PutOperationParams> params,
@@ -283,41 +302,30 @@ class CONTENT_EXPORT IndexedDBDatabase
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction);
- // Called when a backing store operation has failed. The database will be
- // closed (IndexedDBFactory::ForceClose) during this call. This should NOT
- // be used in an method scheduled as a transaction operation.
- void ReportError(leveldb::Status status);
- void ReportErrorWithDetails(leveldb::Status status, const char* message);
-
- IndexedDBFactory* factory() const { return factory_.get(); }
-
const list_set<IndexedDBConnection*>& connections() const {
return connections_;
}
+ base::WeakPtr<IndexedDBDatabase> AsWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
+
protected:
friend class IndexedDBTransaction;
IndexedDBDatabase(const base::string16& name,
- scoped_refptr<IndexedDBBackingStore> backing_store,
- scoped_refptr<IndexedDBFactory> factory,
+ IndexedDBBackingStore* backing_store,
+ IndexedDBFactory* factory,
+ ErrorCallback error_callback,
+ base::OnceClosure destroy_me,
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
const Identifier& unique_identifier,
ScopesLockManager* transaction_lock_manager);
- virtual ~IndexedDBDatabase();
// May be overridden in tests.
virtual size_t GetUsableMessageSizeInBytes() const;
- static IndexedDBDatabaseError CreateError(uint16_t code,
- const char* message,
- IndexedDBTransaction* transaction);
- static IndexedDBDatabaseError CreateError(uint16_t code,
- const base::string16& message,
- IndexedDBTransaction* transaction);
-
private:
- friend class base::RefCounted<IndexedDBDatabase>;
friend class IndexedDBClassFactory;
FRIEND_TEST_ALL_PREFIXES(IndexedDBDatabaseTest, OpenDeleteClear);
@@ -339,13 +347,34 @@ class CONTENT_EXPORT IndexedDBDatabase
// requests, the queue will be synchronously processed.
void RequestComplete(ConnectionRequest* request);
- // Pop the first request from the queue and start it.
- void ProcessRequestQueue();
+ // If there is no active request, grab a new one from the pending queue and
+ // start it. Afterwards, possibly release the database by calling
+ // MaybeReleaseDatabase().
+ void ProcessRequestQueueAndMaybeRelease();
+
+ // If there are no connections, pending requests, or an active request, then
+ // this function will call |destroy_me_|, which can destruct this object.
+ void MaybeReleaseDatabase();
std::unique_ptr<IndexedDBConnection> CreateConnection(
+ IndexedDBOriginStateHandle origin_state_handle,
scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
int child_process_id);
+ // Ack that one of the connections notified with a "versionchange" event did
+ // not promptly close. Therefore a "blocked" event should be fired at the
+ // pending connection.
+ void VersionChangeIgnored();
+
+ bool HasNoConnections() const;
+
+ void SendVersionChangeToAllConnections(int64_t old_version,
+ int64_t new_version);
+
+ // This can only be called when the given connection is closed and no longer
+ // has any transaction objects.
+ void ConnectionClosed(IndexedDBConnection* connection);
+
bool ValidateObjectStoreId(int64_t object_store_id) const;
bool ValidateObjectStoreIdAndIndexId(int64_t object_store_id,
int64_t index_id) const;
@@ -354,18 +383,35 @@ class CONTENT_EXPORT IndexedDBDatabase
bool ValidateObjectStoreIdAndNewIndexId(int64_t object_store_id,
int64_t index_id) const;
- scoped_refptr<IndexedDBBackingStore> backing_store_;
+ // Safe because the IndexedDBBackingStore is owned by the same object which
+ // owns us, the IndexedDBPerOriginFactory.
+ IndexedDBBackingStore* backing_store_;
blink::IndexedDBDatabaseMetadata metadata_;
const Identifier identifier_;
- scoped_refptr<IndexedDBFactory> factory_;
+ // TODO(dmurph): Remove the need for this to be here (and then remove it).
+ IndexedDBFactory* factory_;
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding_;
ScopesLockManager* lock_manager_;
int64_t transaction_count_ = 0;
+ // Called when a backing store operation has failed. The database will be
+ // closed (IndexedDBFactory::ForceClose) during this call. This should NOT
+ // be used in an method scheduled as a transaction operation.
+ ErrorCallback error_callback_;
+
+ // Calling this closure will destroy this object.
+ base::OnceClosure destroy_me_;
+
list_set<IndexedDBConnection*> connections_;
+ // During ForceClose(), the internal state can be inconsistent during cleanup,
+ // specifically for ConnectionClosed() and MaybeReleaseDatabase(). Keeping
+ // track of whether the code is currently in the ForceClose() method helps
+ // ensure that the state stays consistent.
+ bool force_closing_ = false;
+
// This holds the first open or delete request that is currently being
// processed. The request has already broadcast OnVersionChange if
// necessary.
@@ -381,6 +427,9 @@ class CONTENT_EXPORT IndexedDBDatabase
// synchronously.
bool processing_pending_requests_ = false;
+ // |weak_factory_| is used for all callback uses.
+ base::WeakPtrFactory<IndexedDBDatabase> weak_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabase);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
index af626a49a25..e15ac3994f9 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -15,6 +15,7 @@
#include "base/run_loop.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/indexed_db/fake_indexed_db_metadata_coding.h"
#include "content/browser/indexed_db/indexed_db.h"
@@ -23,6 +24,7 @@
#include "content/browser/indexed_db/indexed_db_class_factory.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_cursor.h"
+#include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
@@ -57,39 +59,41 @@ class IndexedDBDatabaseTest : public ::testing::Test {
IndexedDBDatabaseTest() : lock_manager_(kIndexedDBLockLevelCount) {}
void SetUp() override {
- backing_store_ = new IndexedDBFakeBackingStore();
- factory_ = new MockIndexedDBFactory();
+ backing_store_ = std::make_unique<IndexedDBFakeBackingStore>();
+ factory_ = std::make_unique<MockIndexedDBFactory>();
std::unique_ptr<FakeIndexedDBMetadataCoding> metadata_coding =
std::make_unique<FakeIndexedDBMetadataCoding>();
metadata_coding_ = metadata_coding.get();
- EXPECT_TRUE(backing_store_->HasOneRef());
leveldb::Status s;
std::tie(db_, s) = IndexedDBDatabase::Create(
ASCIIToUTF16("db"), backing_store_.get(), factory_.get(),
+ GetErrorCallback(), base::BindLambdaForTesting([&]() {
+ db_.reset();
+ metadata_coding_ = nullptr;
+ }),
std::move(metadata_coding), IndexedDBDatabase::Identifier(),
&lock_manager_);
ASSERT_TRUE(s.ok());
- EXPECT_FALSE(backing_store_->HasOneRef()); // local and db
+ }
+
+ IndexedDBTransaction::ErrorCallback GetErrorCallback() {
+ return base::BindLambdaForTesting(
+ [&](leveldb::Status, const char*) { error_called_ = true; });
}
protected:
- scoped_refptr<IndexedDBFakeBackingStore> backing_store_;
- scoped_refptr<MockIndexedDBFactory> factory_;
- scoped_refptr<IndexedDBDatabase> db_;
+ std::unique_ptr<IndexedDBFakeBackingStore> backing_store_;
+ std::unique_ptr<MockIndexedDBFactory> factory_;
+ std::unique_ptr<IndexedDBDatabase> db_;
FakeIndexedDBMetadataCoding* metadata_coding_;
+ bool error_called_ = false;
private:
TestBrowserThreadBundle thread_bundle_;
DisjointRangeLockManager lock_manager_;
};
-TEST_F(IndexedDBDatabaseTest, BackingStoreRetention) {
- EXPECT_FALSE(backing_store_->HasOneRef()); // local and db
- db_ = nullptr;
- EXPECT_TRUE(backing_store_->HasOneRef()); // local
-}
-
TEST_F(IndexedDBDatabaseTest, ConnectionLifecycle) {
scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks());
scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
@@ -102,9 +106,8 @@ TEST_F(IndexedDBDatabaseTest, ConnectionLifecycle) {
request1, callbacks1, kFakeChildProcessId, transaction_id1,
IndexedDBDatabaseMetadata::DEFAULT_VERSION,
std::move(create_transaction_callback1)));
- db_->OpenConnection(std::move(connection1));
-
- EXPECT_FALSE(backing_store_->HasOneRef()); // db, connection count > 0
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection1));
scoped_refptr<MockIndexedDBCallbacks> request2(new MockIndexedDBCallbacks());
scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks2(
@@ -117,22 +120,16 @@ TEST_F(IndexedDBDatabaseTest, ConnectionLifecycle) {
request2, callbacks2, kFakeChildProcessId, transaction_id2,
IndexedDBDatabaseMetadata::DEFAULT_VERSION,
std::move(create_transaction_callback2)));
- db_->OpenConnection(std::move(connection2));
-
- EXPECT_FALSE(backing_store_->HasOneRef()); // local and connection
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection2));
- request1->connection()->ForceClose();
+ request1->connection()->CloseAndReportForceClose();
EXPECT_FALSE(request1->connection()->IsConnected());
- EXPECT_FALSE(backing_store_->HasOneRef()); // local and connection
-
- request2->connection()->ForceClose();
+ request2->connection()->CloseAndReportForceClose();
EXPECT_FALSE(request2->connection()->IsConnected());
- EXPECT_TRUE(backing_store_->HasOneRef());
- EXPECT_FALSE(db_->backing_store());
-
- db_ = nullptr;
+ EXPECT_FALSE(db_);
}
TEST_F(IndexedDBDatabaseTest, ForcedClose) {
@@ -147,8 +144,9 @@ TEST_F(IndexedDBDatabaseTest, ForcedClose) {
request, callbacks, kFakeChildProcessId, upgrade_transaction_id,
IndexedDBDatabaseMetadata::DEFAULT_VERSION,
std::move(create_transaction_callback)));
- db_->OpenConnection(std::move(connection));
- EXPECT_EQ(db_.get(), request->connection()->database());
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection));
+ EXPECT_EQ(db_.get(), request->connection()->database().get());
const int64_t transaction_id = 123;
const std::vector<int64_t> scope;
@@ -158,9 +156,8 @@ TEST_F(IndexedDBDatabaseTest, ForcedClose) {
new IndexedDBBackingStore::Transaction(backing_store_.get()));
db_->RegisterAndScheduleTransaction(transaction);
- request->connection()->ForceClose();
+ request->connection()->CloseAndReportForceClose();
- EXPECT_TRUE(backing_store_->HasOneRef()); // local
EXPECT_TRUE(callbacks->abort_called());
}
@@ -204,35 +201,33 @@ TEST_F(IndexedDBDatabaseTest, PendingDelete) {
request1, callbacks1, kFakeChildProcessId, transaction_id1,
IndexedDBDatabaseMetadata::DEFAULT_VERSION,
std::move(create_transaction_callback1)));
- db_->OpenConnection(std::move(connection));
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection));
EXPECT_EQ(db_->ConnectionCount(), 1UL);
EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL);
EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
- EXPECT_FALSE(backing_store_->HasOneRef()); // local and db
+ bool deleted = false;
scoped_refptr<MockCallbacks> request2(new MockCallbacks());
- db_->DeleteDatabase(request2, false /* force_delete */);
+ db_->ScheduleDeleteDatabase(
+ IndexedDBOriginStateHandle(), request2,
+ base::BindLambdaForTesting([&]() { deleted = true; }));
EXPECT_EQ(db_->ConnectionCount(), 1UL);
EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
EXPECT_FALSE(request2->blocked_called());
- db_->VersionChangeIgnored();
+ request1->connection()->VersionChangeIgnored();
EXPECT_TRUE(request2->blocked_called());
EXPECT_EQ(db_->ConnectionCount(), 1UL);
EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
- EXPECT_FALSE(backing_store_->HasOneRef()); // local and db
-
- db_->Close(request1->connection(), true /* forced */);
- EXPECT_EQ(db_->ConnectionCount(), 0UL);
- EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL);
- EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
+ db_->ForceClose();
+ EXPECT_FALSE(db_);
- EXPECT_FALSE(db_->backing_store());
- EXPECT_TRUE(backing_store_->HasOneRef()); // local
+ EXPECT_TRUE(deleted);
EXPECT_TRUE(request2->success_called());
}
@@ -250,12 +245,12 @@ TEST_F(IndexedDBDatabaseTest, OpenDeleteClear) {
std::make_unique<IndexedDBPendingConnection>(
request1, callbacks1, kFakeChildProcessId, transaction_id1,
kDatabaseVersion, std::move(create_transaction_callback1)));
- db_->OpenConnection(std::move(connection1));
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection1));
EXPECT_EQ(db_->ConnectionCount(), 1UL);
EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
- EXPECT_FALSE(backing_store_->HasOneRef()); // local and db
scoped_refptr<MockIndexedDBCallbacks> request2(
new MockIndexedDBCallbacks(false));
@@ -268,12 +263,12 @@ TEST_F(IndexedDBDatabaseTest, OpenDeleteClear) {
std::make_unique<IndexedDBPendingConnection>(
request2, callbacks2, kFakeChildProcessId, transaction_id2,
kDatabaseVersion, std::move(create_transaction_callback2)));
- db_->OpenConnection(std::move(connection2));
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection2));
EXPECT_EQ(db_->ConnectionCount(), 1UL);
EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
EXPECT_EQ(db_->PendingOpenDeleteCount(), 1UL);
- EXPECT_FALSE(backing_store_->HasOneRef()); // local and db
scoped_refptr<MockIndexedDBCallbacks> request3(
new MockIndexedDBCallbacks(false));
@@ -286,7 +281,8 @@ TEST_F(IndexedDBDatabaseTest, OpenDeleteClear) {
std::make_unique<IndexedDBPendingConnection>(
request3, callbacks3, kFakeChildProcessId, transaction_id3,
kDatabaseVersion, std::move(create_transaction_callback3)));
- db_->OpenConnection(std::move(connection3));
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection3));
// This causes the active request to call OnUpgradeNeeded on its callbacks.
// The Abort() triggered by ForceClose() assumes that the transaction was
@@ -298,11 +294,10 @@ TEST_F(IndexedDBDatabaseTest, OpenDeleteClear) {
EXPECT_EQ(db_->ConnectionCount(), 1UL);
EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
EXPECT_EQ(db_->PendingOpenDeleteCount(), 2UL);
- EXPECT_FALSE(backing_store_->HasOneRef());
db_->ForceClose();
+ EXPECT_FALSE(db_);
- EXPECT_TRUE(backing_store_->HasOneRef()); // local
EXPECT_TRUE(callbacks1->forced_close_called());
EXPECT_TRUE(request1->error_called());
EXPECT_TRUE(callbacks2->forced_close_called());
@@ -323,22 +318,23 @@ TEST_F(IndexedDBDatabaseTest, ForceDelete) {
request1, callbacks1, kFakeChildProcessId, transaction_id1,
IndexedDBDatabaseMetadata::DEFAULT_VERSION,
std::move(create_transaction_callback1)));
- db_->OpenConnection(std::move(connection));
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection));
EXPECT_EQ(db_->ConnectionCount(), 1UL);
EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL);
EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
- EXPECT_FALSE(backing_store_->HasOneRef()); // local and db
+ bool deleted = false;
scoped_refptr<MockCallbacks> request2(new MockCallbacks());
- db_->DeleteDatabase(request2, true /* force_delete */);
- EXPECT_EQ(db_->ConnectionCount(), 0UL);
- EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL);
- EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
+ db_->ScheduleDeleteDatabase(
+ IndexedDBOriginStateHandle(), request2,
+ base::BindLambdaForTesting([&]() { deleted = true; }));
+ EXPECT_FALSE(deleted);
+ db_->ForceClose();
+ EXPECT_FALSE(db_);
+ EXPECT_TRUE(deleted);
EXPECT_FALSE(request2->blocked_called());
-
- EXPECT_FALSE(db_->backing_store());
- EXPECT_TRUE(backing_store_->HasOneRef()); // local
EXPECT_TRUE(request2->success_called());
}
@@ -356,12 +352,12 @@ TEST_F(IndexedDBDatabaseTest, ForceCloseWhileOpenPending) {
request1, callbacks1, kFakeChildProcessId, transaction_id1,
IndexedDBDatabaseMetadata::DEFAULT_VERSION,
std::move(create_transaction_callback1)));
- db_->OpenConnection(std::move(connection));
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection));
EXPECT_EQ(db_->ConnectionCount(), 1UL);
EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL);
EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
- EXPECT_FALSE(backing_store_->HasOneRef()); // local and db
scoped_refptr<MockIndexedDBCallbacks> request2(
new MockIndexedDBCallbacks(false));
@@ -374,17 +370,64 @@ TEST_F(IndexedDBDatabaseTest, ForceCloseWhileOpenPending) {
std::make_unique<IndexedDBPendingConnection>(
request1, callbacks1, kFakeChildProcessId, transaction_id2, 3,
std::move(create_transaction_callback2)));
- db_->OpenConnection(std::move(connection2));
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection2));
EXPECT_EQ(db_->ConnectionCount(), 1UL);
EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
- EXPECT_FALSE(backing_store_->HasOneRef()); // local and db
db_->ForceClose();
- EXPECT_EQ(db_->ConnectionCount(), 0UL);
+ EXPECT_FALSE(db_);
+}
+
+TEST_F(IndexedDBDatabaseTest, ForceCloseWhileOpenAndDeletePending) {
+ // Verify that pending connection requests are handled correctly during a
+ // ForceClose.
+ auto request1 = base::MakeRefCounted<MockIndexedDBCallbacks>();
+ auto callbacks1 = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
+ const int64_t transaction_id1 = 1;
+ auto create_transaction_callback1 =
+ base::BindOnce(&CreateAndBindTransactionPlaceholder);
+ std::unique_ptr<IndexedDBPendingConnection> connection =
+ std::make_unique<IndexedDBPendingConnection>(
+ request1, callbacks1, kFakeChildProcessId, transaction_id1,
+ IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+ std::move(create_transaction_callback1));
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection));
+
+ EXPECT_EQ(db_->ConnectionCount(), 1UL);
EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL);
EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
+
+ auto request2 = base::MakeRefCounted<MockIndexedDBCallbacks>(false);
+ auto callbacks2 = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
+ const int64_t transaction_id2 = 2;
+ auto create_transaction_callback2 =
+ base::BindOnce(&CreateAndBindTransactionPlaceholder);
+ std::unique_ptr<IndexedDBPendingConnection> connection2(
+ std::make_unique<IndexedDBPendingConnection>(
+ request1, callbacks1, kFakeChildProcessId, transaction_id2, 3,
+ std::move(create_transaction_callback2)));
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection2));
+
+ bool deleted = false;
+ auto request3 = base::MakeRefCounted<MockCallbacks>();
+ db_->ScheduleDeleteDatabase(
+ IndexedDBOriginStateHandle(), request3,
+ base::BindLambdaForTesting([&]() { deleted = true; }));
+ EXPECT_FALSE(deleted);
+
+ EXPECT_EQ(db_->ConnectionCount(), 1UL);
+ EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
+ EXPECT_EQ(db_->PendingOpenDeleteCount(), 1UL);
+
+ db_->ForceClose();
+
+ EXPECT_TRUE(deleted);
+ EXPECT_FALSE(db_);
}
leveldb::Status DummyOperation(IndexedDBTransaction* transaction) {
@@ -399,13 +442,17 @@ class IndexedDBDatabaseOperationTest : public testing::Test {
factory_(new MockIndexedDBFactory()) {}
void SetUp() override {
- backing_store_ = new IndexedDBFakeBackingStore();
+ backing_store_ = std::make_unique<IndexedDBFakeBackingStore>();
std::unique_ptr<FakeIndexedDBMetadataCoding> metadata_coding =
std::make_unique<FakeIndexedDBMetadataCoding>();
metadata_coding_ = metadata_coding.get();
leveldb::Status s;
std::tie(db_, s) = IndexedDBDatabase::Create(
ASCIIToUTF16("db"), backing_store_.get(), factory_.get(),
+ GetErrorCallback(), base::BindLambdaForTesting([&]() {
+ db_.reset();
+ metadata_coding_ = nullptr;
+ }),
std::move(metadata_coding), IndexedDBDatabase::Identifier(),
&lock_manager_);
ASSERT_TRUE(s.ok());
@@ -420,12 +467,11 @@ class IndexedDBDatabaseOperationTest : public testing::Test {
request_, callbacks_, kFakeChildProcessId, transaction_id,
IndexedDBDatabaseMetadata::DEFAULT_VERSION,
std::move(create_transaction_callback1)));
- db_->OpenConnection(std::move(connection));
+ db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
+ std::move(connection));
EXPECT_EQ(IndexedDBDatabaseMetadata::NO_VERSION, db_->metadata().version);
- connection_ = std::make_unique<IndexedDBConnection>(kFakeChildProcessId,
- db_, callbacks_);
- transaction_ = connection_->CreateTransaction(
+ transaction_ = request_->connection()->CreateTransaction(
transaction_id, std::set<int64_t>() /*scope*/,
blink::mojom::IDBTransactionMode::VersionChange,
new IndexedDBFakeBackingStore::FakeTransaction(commit_success_));
@@ -439,24 +485,29 @@ class IndexedDBDatabaseOperationTest : public testing::Test {
void RunPostedTasks() { base::RunLoop().RunUntilIdle(); }
-private:
+ IndexedDBTransaction::ErrorCallback GetErrorCallback() {
+ return base::BindLambdaForTesting(
+ [&](leveldb::Status, const char*) { error_called_ = true; });
+ }
+
+ private:
// Needs to outlive |db_|.
content::TestBrowserThreadBundle thread_bundle_;
protected:
- scoped_refptr<IndexedDBFakeBackingStore> backing_store_;
- scoped_refptr<IndexedDBDatabase> db_;
- FakeIndexedDBMetadataCoding* metadata_coding_;
+ std::unique_ptr<IndexedDBFakeBackingStore> backing_store_;
+ std::unique_ptr<IndexedDBDatabase> db_;
+ FakeIndexedDBMetadataCoding* metadata_coding_ = nullptr;
scoped_refptr<MockIndexedDBCallbacks> request_;
scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks_;
- IndexedDBTransaction* transaction_;
- std::unique_ptr<IndexedDBConnection> connection_;
+ IndexedDBTransaction* transaction_ = nullptr;
DisjointRangeLockManager lock_manager_;
+ bool error_called_ = false;
leveldb::Status commit_success_;
private:
- scoped_refptr<MockIndexedDBFactory> factory_;
+ std::unique_ptr<MockIndexedDBFactory> factory_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationTest);
};
@@ -540,7 +591,6 @@ TEST_F(IndexedDBDatabaseOperationTest, CreatePutDelete) {
IndexedDBKeyPath(), false /*auto_increment*/);
EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
-
// Put is asynchronous
IndexedDBValue value("value1", std::vector<IndexedDBBlobInfo>());
std::unique_ptr<IndexedDBKey> key(std::make_unique<IndexedDBKey>("key"));
diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index ec7304f19d9..52257a104fa 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -18,6 +18,7 @@
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
+#include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/indexed_db_pending_connection.h"
#include "content/browser/indexed_db/transaction_impl.h"
#include "content/public/browser/browser_task_traits.h"
diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
index 684cae99f5d..545b31e1f8d 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -16,6 +16,7 @@
#include "base/test/bind_test_util.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread.h"
+#include "base/time/default_clock.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
@@ -183,7 +184,8 @@ class IndexedDBDispatcherHostTest : public testing::Test {
CreateAndReturnTempDir(&temp_dir_),
special_storage_policy_,
quota_manager_->proxy(),
- indexed_db::GetDefaultLevelDBFactory())),
+ indexed_db::GetDefaultLevelDBFactory(),
+ base::DefaultClock::GetInstance())),
host_(new IndexedDBDispatcherHost(
kFakeProcessId,
context_impl_,
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory.h b/chromium/content/browser/indexed_db/indexed_db_factory.h
index 7a90e80a8d8..ef032d0b1c4 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory.h
@@ -7,12 +7,13 @@
#include <stddef.h>
-#include <map>
#include <memory>
-#include <set>
#include <tuple>
#include <utility>
+#include <vector>
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -28,17 +29,15 @@ namespace content {
class IndexedDBBackingStore;
struct IndexedDBPendingConnection;
-struct IndexedDBDataLossInfo;
-class CONTENT_EXPORT IndexedDBFactory
- : public base::RefCountedThreadSafe<IndexedDBFactory> {
+// TODO(dmurph): Remove this interface.
+class CONTENT_EXPORT IndexedDBFactory {
public:
- typedef std::multimap<url::Origin, IndexedDBDatabase*> OriginDBMap;
- typedef OriginDBMap::const_iterator OriginDBMapIterator;
- typedef std::pair<OriginDBMapIterator, OriginDBMapIterator> OriginDBs;
+ virtual ~IndexedDBFactory() = default;
+
+ using OriginDBMap =
+ base::flat_map<base::string16, std::unique_ptr<IndexedDBDatabase>>;
- virtual void ReleaseDatabase(const IndexedDBDatabase::Identifier& identifier,
- bool forced_close) = 0;
virtual void GetDatabaseInfo(scoped_refptr<IndexedDBCallbacks> callbacks,
const url::Origin& origin,
const base::FilePath& data_directory) = 0;
@@ -70,7 +69,7 @@ class CONTENT_EXPORT IndexedDBFactory
const url::Origin& origin,
const IndexedDBDatabaseError& error) = 0;
- virtual OriginDBs GetOpenDatabasesForOrigin(
+ virtual std::vector<IndexedDBDatabase*> GetOpenDatabasesForOrigin(
const url::Origin& origin) const = 0;
// Close all connections to all databases within the origin. If
@@ -79,6 +78,7 @@ class CONTENT_EXPORT IndexedDBFactory
// the lifetime of the factory).
virtual void ForceClose(const url::Origin& origin,
bool delete_in_memory_store = false) = 0;
+
virtual void ForceSchemaDowngrade(const url::Origin& origin) = 0;
virtual V2SchemaCorruptionStatus HasV2SchemaCorruption(
const url::Origin& origin) = 0;
@@ -90,10 +90,6 @@ class CONTENT_EXPORT IndexedDBFactory
virtual void ReportOutstandingBlobs(const url::Origin& origin,
bool blobs_outstanding) = 0;
- // Called by an IndexedDBDatabase when it is actually deleted.
- virtual void DatabaseDeleted(
- const IndexedDBDatabase::Identifier& identifier) = 0;
-
// Called by IndexedDBBackingStore when blob files have been cleaned.
virtual void BlobFilesCleaned(const url::Origin& origin) = 0;
@@ -109,17 +105,7 @@ class CONTENT_EXPORT IndexedDBFactory
const base::string16& object_store_name) = 0;
protected:
- friend class base::RefCountedThreadSafe<IndexedDBFactory>;
-
IndexedDBFactory() {}
- virtual ~IndexedDBFactory() {}
-
- virtual std::tuple<scoped_refptr<IndexedDBBackingStore>,
- leveldb::Status,
- IndexedDBDataLossInfo,
- bool /* disk_full */>
- OpenBackingStore(const url::Origin& origin,
- const base::FilePath& data_directory) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(IndexedDBFactory);
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 416401a4182..2d0f9b10b9c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -13,19 +13,21 @@
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/feature_list.h"
+#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
-#include "base/rand_util.h"
+#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/timer/timer.h"
-#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_class_factory.h"
+#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_leveldb_operations.h"
#include "content/browser/indexed_db/indexed_db_metadata_coding.h"
+#include "content/browser/indexed_db/indexed_db_origin_state.h"
#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
#include "content/browser/indexed_db/indexed_db_tombstone_sweeper.h"
#include "content/browser/indexed_db/indexed_db_tracing.h"
@@ -39,48 +41,6 @@ namespace content {
namespace {
-using PreCloseTask = IndexedDBPreCloseTaskQueue::PreCloseTask;
-
-// Time after the last connection to a database is closed and when we destroy
-// the backing store.
-const int64_t kBackingStoreGracePeriodSeconds = 2;
-// Total time we let pre-close tasks run.
-const int64_t kPreCloseTasksMaxRunPeriodSeconds = 60;
-// The number of iterations for every 'round' of the tombstone sweeper.
-const int kTombstoneSweeperRoundIterations = 1000;
-// The maximum total iterations for the tombstone sweeper.
-const int kTombstoneSweeperMaxIterations = 10 * 1000 * 1000;
-
-constexpr const base::TimeDelta kMinEarliestOriginSweepFromNow =
- base::TimeDelta::FromDays(1);
-static_assert(kMinEarliestOriginSweepFromNow <
- IndexedDBFactoryImpl::kMaxEarliestOriginSweepFromNow,
- "Min < Max");
-
-constexpr const base::TimeDelta kMinEarliestGlobalSweepFromNow =
- base::TimeDelta::FromMinutes(10);
-static_assert(kMinEarliestGlobalSweepFromNow <
- IndexedDBFactoryImpl::kMaxEarliestGlobalSweepFromNow,
- "Min < Max");
-
-base::Time GenerateNextOriginSweepTime(base::Time now) {
- uint64_t range =
- IndexedDBFactoryImpl::kMaxEarliestOriginSweepFromNow.InMilliseconds() -
- kMinEarliestOriginSweepFromNow.InMilliseconds();
- int64_t rand_millis = kMinEarliestOriginSweepFromNow.InMilliseconds() +
- static_cast<int64_t>(base::RandGenerator(range));
- return now + base::TimeDelta::FromMilliseconds(rand_millis);
-}
-
-base::Time GenerateNextGlobalSweepTime(base::Time now) {
- uint64_t range =
- IndexedDBFactoryImpl::kMaxEarliestGlobalSweepFromNow.InMilliseconds() -
- kMinEarliestGlobalSweepFromNow.InMilliseconds();
- int64_t rand_millis = kMinEarliestGlobalSweepFromNow.InMilliseconds() +
- static_cast<int64_t>(base::RandGenerator(range));
- return now + base::TimeDelta::FromMilliseconds(rand_millis);
-}
-
leveldb::Status GetDBSizeFromEnv(leveldb::Env* env,
const std::string& path,
int64_t* total_size_out) {
@@ -107,129 +67,99 @@ leveldb::Status GetDBSizeFromEnv(leveldb::Env* env,
return s;
}
-} // namespace
-
-const base::Feature kIDBTombstoneStatistics{"IDBTombstoneStatistics",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
-const base::Feature kIDBTombstoneDeletion{"IDBTombstoneDeletion",
- base::FEATURE_ENABLED_BY_DEFAULT};
+IndexedDBDatabaseError CreateDefaultError() {
+ return IndexedDBDatabaseError(
+ blink::kWebIDBDatabaseExceptionUnknownError,
+ ASCIIToUTF16("Internal error opening backing store"
+ " for indexedDB.open."));
+}
-constexpr const base::TimeDelta
- IndexedDBFactoryImpl::kMaxEarliestGlobalSweepFromNow;
-constexpr const base::TimeDelta
- IndexedDBFactoryImpl::kMaxEarliestOriginSweepFromNow;
+} // namespace
IndexedDBFactoryImpl::IndexedDBFactoryImpl(
IndexedDBContextImpl* context,
indexed_db::LevelDBFactory* leveldb_factory,
base::Clock* clock)
- : context_(context),
- leveldb_factory_(leveldb_factory),
- clock_(clock),
- earliest_sweep_(GenerateNextGlobalSweepTime(clock_->Now())) {}
+ : context_(context), leveldb_factory_(leveldb_factory), clock_(clock) {}
IndexedDBFactoryImpl::~IndexedDBFactoryImpl() {
-}
-
-void IndexedDBFactoryImpl::ReleaseDatabase(
- const IndexedDBDatabase::Identifier& identifier,
- bool forced_close) {
- DCHECK(!database_map_.find(identifier)->second->backing_store());
-
- RemoveDatabaseFromMaps(identifier);
-
- // No grace period on a forced-close, as the initiator is
- // assuming the backing store will be released once all
- // connections are closed.
- ReleaseBackingStore(identifier.first, forced_close);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void IndexedDBFactoryImpl::GetDatabaseInfo(
scoped_refptr<IndexedDBCallbacks> callbacks,
const Origin& origin,
const base::FilePath& data_directory) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
IDB_TRACE("IndexedDBFactoryImpl::GetDatabaseInfo");
- // TODO(dmurph): Plumb data_loss back to script eventually?
- IndexedDBDataLossInfo data_loss_info;
- bool disk_full;
+ IndexedDBOriginStateHandle origin_state_handle;
leveldb::Status s;
- scoped_refptr<IndexedDBBackingStore> backing_store;
- std::tie(backing_store, s, data_loss_info, disk_full) =
- OpenBackingStore(origin, data_directory);
- if (!backing_store.get()) {
- IndexedDBDatabaseError error(
- blink::kWebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16("Internal error opening backing store for "
- "indexedDB.databases()."));
+ IndexedDBDatabaseError error;
+ // Note: Any data loss information here is not piped up to the renderer, and
+ // will be lost.
+ std::tie(origin_state_handle, s, error, std::ignore) =
+ GetOrOpenOriginFactory(origin, data_directory);
+ if (!origin_state_handle.IsHeld() || !origin_state_handle.origin_state()) {
callbacks->OnError(error);
if (s.IsCorruption())
HandleBackingStoreCorruption(origin, error);
return;
}
+ IndexedDBOriginState* factory = origin_state_handle.origin_state();
IndexedDBMetadataCoding metadata_coding;
std::vector<blink::mojom::IDBNameAndVersionPtr> names_and_versions;
s = metadata_coding.ReadDatabaseNamesAndVersions(
- backing_store->db(), backing_store->origin_identifier(),
- &names_and_versions);
+ factory->backing_store_->db(),
+ factory->backing_store_->origin_identifier(), &names_and_versions);
if (!s.ok()) {
- DLOG(ERROR) << "Internal error getting database info";
- IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError,
- "Internal error opening backing store for "
- "indexedDB.databases().");
+ error = IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionUnknownError,
+ "Internal error opening backing store for "
+ "indexedDB.databases().");
callbacks->OnError(error);
- backing_store = nullptr;
if (s.IsCorruption())
HandleBackingStoreCorruption(origin, error);
return;
}
callbacks->OnSuccess(std::move(names_and_versions));
- backing_store = nullptr;
- ReleaseBackingStore(origin, false /* immediate */);
}
void IndexedDBFactoryImpl::GetDatabaseNames(
scoped_refptr<IndexedDBCallbacks> callbacks,
const Origin& origin,
const base::FilePath& data_directory) {
- IDB_TRACE("IndexedDBFactoryImpl::GetDatabaseNames");
- // TODO(dmurph): Plumb data_loss back to script eventually?
- IndexedDBDataLossInfo data_loss_info;
- bool disk_full;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ IDB_TRACE("IndexedDBFactoryImpl::GetDatabaseInfo");
+ IndexedDBOriginStateHandle origin_state_handle;
leveldb::Status s;
- scoped_refptr<IndexedDBBackingStore> backing_store;
- std::tie(backing_store, s, data_loss_info, disk_full) =
- OpenBackingStore(origin, data_directory);
- if (!backing_store.get()) {
- IndexedDBDatabaseError error(
- blink::kWebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16("Internal error opening backing store for "
- "indexedDB.webkitGetDatabaseNames."));
+ IndexedDBDatabaseError error;
+ // Note: Any data loss information here is not piped up to the renderer, and
+ // will be lost.
+ std::tie(origin_state_handle, s, error, std::ignore) =
+ GetOrOpenOriginFactory(origin, data_directory);
+ if (!origin_state_handle.IsHeld() || !origin_state_handle.origin_state()) {
callbacks->OnError(error);
if (s.IsCorruption())
HandleBackingStoreCorruption(origin, error);
return;
}
+ IndexedDBOriginState* factory = origin_state_handle.origin_state();
IndexedDBMetadataCoding metadata_coding;
std::vector<base::string16> names;
s = metadata_coding.ReadDatabaseNames(
- backing_store->db(), backing_store->origin_identifier(), &names);
+ factory->backing_store_->db(),
+ factory->backing_store_->origin_identifier(), &names);
if (!s.ok()) {
- DLOG(ERROR) << "Internal error getting database names";
- IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError,
- "Internal error opening backing store for "
- "indexedDB.webkitGetDatabaseNames.");
+ error = IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionUnknownError,
+ "Internal error opening backing store for "
+ "indexedDB.webkitGetDatabaseNames.");
callbacks->OnError(error);
- backing_store = nullptr;
if (s.IsCorruption())
HandleBackingStoreCorruption(origin, error);
return;
}
callbacks->OnSuccess(names);
- backing_store = nullptr;
- ReleaseBackingStore(origin, false /* immediate */);
}
void IndexedDBFactoryImpl::Open(
@@ -237,61 +167,52 @@ void IndexedDBFactoryImpl::Open(
std::unique_ptr<IndexedDBPendingConnection> connection,
const Origin& origin,
const base::FilePath& data_directory) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
IDB_TRACE("IndexedDBFactoryImpl::Open");
IndexedDBDatabase::Identifier unique_identifier(origin, name);
- auto it = database_map_.find(unique_identifier);
- if (it != database_map_.end()) {
- it->second->OpenConnection(std::move(connection));
- return;
- }
+ IndexedDBOriginStateHandle origin_state_handle;
leveldb::Status s;
- scoped_refptr<IndexedDBBackingStore> backing_store;
- bool disk_full;
- std::tie(backing_store, s, connection->data_loss_info, disk_full) =
- OpenBackingStore(origin, data_directory);
- if (!backing_store) {
- if (disk_full) {
- connection->callbacks->OnError(IndexedDBDatabaseError(
- blink::kWebIDBDatabaseExceptionQuotaError,
- ASCIIToUTF16("Encountered full disk while opening "
- "backing store for indexedDB.open.")));
- return;
- }
- IndexedDBDatabaseError error(
- blink::kWebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16("Internal error opening backing store"
- " for indexedDB.open."));
+ IndexedDBDatabaseError error;
+ std::tie(origin_state_handle, s, error, connection->data_loss_info) =
+ GetOrOpenOriginFactory(origin, data_directory);
+ if (!origin_state_handle.IsHeld() || !origin_state_handle.origin_state()) {
connection->callbacks->OnError(error);
- if (s.IsCorruption()) {
+ if (s.IsCorruption())
HandleBackingStoreCorruption(origin, error);
- }
return;
}
-
- scoped_refptr<IndexedDBDatabase> database;
+ IndexedDBOriginState* factory = origin_state_handle.origin_state();
+ auto it = factory->databases().find(name);
+ if (it != factory->databases().end()) {
+ it->second->ScheduleOpenConnection(std::move(origin_state_handle),
+ std::move(connection));
+ return;
+ }
+ std::unique_ptr<IndexedDBDatabase> database;
std::tie(database, s) = IndexedDBDatabase::Create(
- name, backing_store.get(), this,
- std::make_unique<IndexedDBMetadataCoding>(), unique_identifier,
- backing_store->lock_manager());
+ name, factory->backing_store(), this,
+ base::BindRepeating(&IndexedDBFactoryImpl::OnDatabaseError,
+ weak_factory_.GetWeakPtr(), origin),
+ factory->CreateDatabaseDeleteClosure(name),
+ std::make_unique<IndexedDBMetadataCoding>(), std::move(unique_identifier),
+ factory->lock_manager());
if (!database.get()) {
- DLOG(ERROR) << "Unable to create the database";
- IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16("Internal error creating "
- "database backend for "
- "indexedDB.open."));
+ error = IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionUnknownError,
+ ASCIIToUTF16("Internal error creating "
+ "database backend for "
+ "indexedDB.open."));
connection->callbacks->OnError(error);
- if (s.IsCorruption()) {
- backing_store = nullptr; // Closes the LevelDB so that it can be deleted
+ if (s.IsCorruption())
HandleBackingStoreCorruption(origin, error);
- }
return;
}
- database->OpenConnection(std::move(connection));
- if (database->ConnectionCount() > 0) {
- database_map_[unique_identifier] = database.get();
- origin_dbs_.insert(std::make_pair(origin, database.get()));
- }
+ // The database must be added before the schedule call, as the
+ // CreateDatabaseDeleteClosure can be called synchronously.
+ auto* database_ptr = database.get();
+ factory->AddDatabase(name, std::move(database));
+ database_ptr->ScheduleOpenConnection(std::move(origin_state_handle),
+ std::move(connection));
}
void IndexedDBFactoryImpl::DeleteDatabase(
@@ -300,116 +221,118 @@ void IndexedDBFactoryImpl::DeleteDatabase(
const Origin& origin,
const base::FilePath& data_directory,
bool force_close) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
IDB_TRACE("IndexedDBFactoryImpl::DeleteDatabase");
IndexedDBDatabase::Identifier unique_identifier(origin, name);
- auto it = database_map_.find(unique_identifier);
- if (it != database_map_.end()) {
- // If there are any connections to the database, directly delete the
- // database.
- it->second->DeleteDatabase(callbacks, force_close);
- return;
- }
-
- // TODO(dmurph): Plumb data_loss back to script eventually?
- IndexedDBDataLossInfo data_loss_info;
- bool disk_full;
+ IndexedDBOriginStateHandle origin_state_handle;
leveldb::Status s;
- scoped_refptr<IndexedDBBackingStore> backing_store;
- std::tie(backing_store, s, data_loss_info, disk_full) =
- OpenBackingStore(origin, data_directory);
- if (!backing_store.get()) {
- IndexedDBDatabaseError error(
- blink::kWebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16("Internal error opening backing store "
- "for indexedDB.deleteDatabase."));
+ IndexedDBDatabaseError error;
+ // Note: Any data loss information here is not piped up to the renderer, and
+ // will be lost.
+ std::tie(origin_state_handle, s, error, std::ignore) =
+ GetOrOpenOriginFactory(origin, data_directory);
+ if (!origin_state_handle.IsHeld() || !origin_state_handle.origin_state()) {
callbacks->OnError(error);
- if (s.IsCorruption()) {
+ if (s.IsCorruption())
HandleBackingStoreCorruption(origin, error);
- }
+ return;
+ }
+ IndexedDBOriginState* factory = origin_state_handle.origin_state();
+
+ auto it = factory->databases().find(name);
+ if (it != factory->databases().end()) {
+ base::WeakPtr<IndexedDBDatabase> database = it->second->AsWeakPtr();
+ database->ScheduleDeleteDatabase(
+ std::move(origin_state_handle), callbacks,
+ base::BindOnce(&IndexedDBFactoryImpl::OnDatabaseDeleted,
+ weak_factory_.GetWeakPtr(), origin));
+ if (force_close && database)
+ database->ForceClose();
return;
}
+ // TODO(dmurph): Get rid of on-demand metadata loading, and store metadata
+ // in-memory in the backing store.
IndexedDBMetadataCoding metadata_coding;
std::vector<base::string16> names;
s = metadata_coding.ReadDatabaseNames(
- backing_store->db(), backing_store->origin_identifier(), &names);
+ factory->backing_store()->db(),
+ factory->backing_store()->origin_identifier(), &names);
if (!s.ok()) {
- DLOG(ERROR) << "Internal error getting database names";
- IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError,
- "Internal error opening backing store for "
- "indexedDB.deleteDatabase.");
+ error = IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionUnknownError,
+ "Internal error opening backing store for "
+ "indexedDB.deleteDatabase.");
callbacks->OnError(error);
- backing_store = nullptr;
if (s.IsCorruption())
HandleBackingStoreCorruption(origin, error);
return;
}
+
if (!base::ContainsValue(names, name)) {
const int64_t version = 0;
callbacks->OnSuccess(version);
- backing_store = nullptr;
- ReleaseBackingStore(origin, false /* immediate */);
return;
}
- scoped_refptr<IndexedDBDatabase> database;
+ std::unique_ptr<IndexedDBDatabase> database;
std::tie(database, s) = IndexedDBDatabase::Create(
- name, backing_store.get(), this,
+ name, factory->backing_store(), this,
+ base::BindRepeating(&IndexedDBFactoryImpl::OnDatabaseError,
+ weak_factory_.GetWeakPtr(), origin),
+ factory->CreateDatabaseDeleteClosure(name),
std::make_unique<IndexedDBMetadataCoding>(), unique_identifier,
- backing_store->lock_manager());
+ factory->lock_manager());
if (!database.get()) {
- IndexedDBDatabaseError error(
+ error = IndexedDBDatabaseError(
blink::kWebIDBDatabaseExceptionUnknownError,
ASCIIToUTF16("Internal error creating database backend for "
"indexedDB.deleteDatabase."));
callbacks->OnError(error);
- if (s.IsCorruption()) {
- backing_store = nullptr;
+ if (s.IsCorruption())
HandleBackingStoreCorruption(origin, error);
- }
return;
}
- database_map_[unique_identifier] = database.get();
- origin_dbs_.insert(std::make_pair(origin, database.get()));
- database->DeleteDatabase(callbacks, force_close);
- RemoveDatabaseFromMaps(unique_identifier);
- database = nullptr;
- backing_store = nullptr;
- ReleaseBackingStore(origin, false /* immediate */);
+ base::WeakPtr<IndexedDBDatabase> database_ptr =
+ factory->AddDatabase(name, std::move(database))->AsWeakPtr();
+ database_ptr->ScheduleDeleteDatabase(
+ std::move(origin_state_handle), std::move(callbacks),
+ base::BindOnce(&IndexedDBFactoryImpl::OnDatabaseDeleted,
+ weak_factory_.GetWeakPtr(), origin));
+ if (force_close && database_ptr)
+ database_ptr->ForceClose();
}
void IndexedDBFactoryImpl::AbortTransactionsAndCompactDatabase(
base::OnceCallback<void(leveldb::Status)> callback,
const Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
IDB_TRACE("IndexedDBFactoryImpl::AbortTransactionsAndCompactDatabase");
- auto it = backing_store_map_.find(origin);
- if (it == backing_store_map_.end()) {
- std::move(callback).Run(leveldb::Status::IOError(
- "Internal error opening backing store for "
- "indexedDB.abortTransactionsAndCompactDatabase."));
+ auto it = factories_per_origin_.find(origin);
+ if (it == factories_per_origin_.end()) {
+ std::move(callback).Run(leveldb::Status::OK());
return;
}
- IndexedDBBackingStore* backing_store = it->second.get();
- leveldb::Status status = AbortTransactions(origin);
- backing_store->Compact();
- std::move(callback).Run(status);
+ it->second->AbortAllTransactions(true);
+ std::move(callback).Run(leveldb::Status::OK());
}
void IndexedDBFactoryImpl::AbortTransactionsForDatabase(
base::OnceCallback<void(leveldb::Status)> callback,
const Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
IDB_TRACE("IndexedDBFactoryImpl::AbortTransactionsForDatabase");
- if (!base::ContainsKey(backing_store_map_, origin)) {
- std::move(callback).Run(
- leveldb::Status::IOError("Internal error opening backing store for "
- "indexedDB.abortTransactionsForDatabase."));
+ auto it = factories_per_origin_.find(origin);
+ if (it == factories_per_origin_.end()) {
+ std::move(callback).Run(leveldb::Status::OK());
return;
}
- std::move(callback).Run(AbortTransactions(origin));
+ it->second->AbortAllTransactions(false);
+ std::move(callback).Run(leveldb::Status::OK());
}
void IndexedDBFactoryImpl::HandleBackingStoreFailure(const Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// NULL after ContextDestroyed() called, and in some unit tests.
if (!context_)
return;
@@ -420,6 +343,7 @@ void IndexedDBFactoryImpl::HandleBackingStoreFailure(const Origin& origin) {
void IndexedDBFactoryImpl::HandleBackingStoreCorruption(
const Origin& origin,
const IndexedDBDatabaseError& error) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Make a copy of origin as this is likely a reference to a member of a
// backing store which this function will be deleting.
Origin saved_origin(origin);
@@ -446,94 +370,86 @@ void IndexedDBFactoryImpl::HandleBackingStoreCorruption(
leveldb_env::LEVELDB_STATUS_MAX);
}
-std::pair<IndexedDBFactoryImpl::OriginDBMapIterator,
- IndexedDBFactoryImpl::OriginDBMapIterator>
-IndexedDBFactoryImpl::GetOpenDatabasesForOrigin(const Origin& origin) const {
- return origin_dbs_.equal_range(origin);
+std::vector<IndexedDBDatabase*> IndexedDBFactoryImpl::GetOpenDatabasesForOrigin(
+ const Origin& origin) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = factories_per_origin_.find(origin);
+ if (it == factories_per_origin_.end()) {
+ return std::vector<IndexedDBDatabase*>();
+ }
+ IndexedDBOriginState* factory = it->second.get();
+ std::vector<IndexedDBDatabase*> out;
+ out.reserve(factory->databases().size());
+ std::for_each(factory->databases().begin(), factory->databases().end(),
+ [&out](const auto& p) { out.push_back(p.second.get()); });
+ return out;
}
void IndexedDBFactoryImpl::ForceClose(const Origin& origin,
bool delete_in_memory_store) {
- OriginDBs range = GetOpenDatabasesForOrigin(origin);
-
- while (range.first != range.second) {
- IndexedDBDatabase* db = range.first->second;
- ++range.first;
- db->ForceClose();
- }
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = factories_per_origin_.find(origin);
+ if (it == factories_per_origin_.end())
+ return;
- auto it = backing_store_map_.find(origin);
- if (it != backing_store_map_.end()) {
- if (delete_in_memory_store)
- in_memory_backing_stores_.erase(it->second);
+ IndexedDBOriginStateHandle origin_state_handle = it->second->CreateHandle();
- ReleaseBackingStore(origin, true /* immediate */);
- }
+ if (delete_in_memory_store)
+ origin_state_handle.origin_state()->StopPersistingForIncognito();
+ origin_state_handle.origin_state()->ForceClose();
}
void IndexedDBFactoryImpl::ForceSchemaDowngrade(const Origin& origin) {
- auto it = backing_store_map_.find(origin);
- if (it == backing_store_map_.end())
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = factories_per_origin_.find(origin);
+ if (it == factories_per_origin_.end())
return;
- IndexedDBBackingStore* backing_store = it->second.get();
+ IndexedDBBackingStore* backing_store = it->second->backing_store();
leveldb::Status s = backing_store->RevertSchemaToV2();
DLOG_IF(ERROR, !s.ok()) << "Unable to force downgrade: " << s.ToString();
}
V2SchemaCorruptionStatus IndexedDBFactoryImpl::HasV2SchemaCorruption(
const Origin& origin) {
- auto it = backing_store_map_.find(origin);
- if (it == backing_store_map_.end())
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = factories_per_origin_.find(origin);
+ if (it == factories_per_origin_.end())
return V2SchemaCorruptionStatus::kUnknown;
- IndexedDBBackingStore* backing_store = it->second.get();
+ IndexedDBBackingStore* backing_store = it->second->backing_store();
return backing_store->HasV2SchemaCorruption();
}
void IndexedDBFactoryImpl::ContextDestroyed() {
- // Timers on backing stores hold a reference to this factory. When the
- // context (which nominally owns this factory) is destroyed during thread
- // termination the timers must be stopped so that this factory and the
- // stores can be disposed of.
- for (const auto& origin_backing_store_pair : backing_store_map_) {
- origin_backing_store_pair.second->close_timer()->Stop();
- origin_backing_store_pair.second->SetPreCloseTaskList(nullptr);
- }
- backing_store_map_.clear();
- backing_stores_with_active_blobs_.clear();
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // Set |context_| to nullptr first to ensure no re-entry into the |cotext_|
+ // object during shutdown. This can happen in methods like BlobFilesCleaned.
context_ = nullptr;
+ // Invalidate the weak factory that is used by the IndexedDBOriginStates to
+ // destruct themselves. This prevents modification of the
+ // |factories_per_origin_| map while it is iterated below, and allows us to
+ // avoid holding a handle to call ForceClose();
+ origin_state_destruction_weak_factory_.InvalidateWeakPtrs();
+ for (const auto& pair : factories_per_origin_) {
+ pair.second->ForceClose();
+ }
+ factories_per_origin_.clear();
}
void IndexedDBFactoryImpl::ReportOutstandingBlobs(const Origin& origin,
bool blobs_outstanding) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!context_)
return;
- if (blobs_outstanding) {
- DCHECK(!backing_stores_with_active_blobs_.count(origin));
- auto it = backing_store_map_.find(origin);
- if (it != backing_store_map_.end())
- backing_stores_with_active_blobs_.insert(*it);
- else
- DCHECK(false);
- } else {
- auto it = backing_stores_with_active_blobs_.find(origin);
- if (it != backing_stores_with_active_blobs_.end()) {
- backing_stores_with_active_blobs_.erase(it);
- ReleaseBackingStore(origin, false /* immediate */);
- }
- }
-}
+ auto it = factories_per_origin_.find(origin);
+ DCHECK(it != factories_per_origin_.end());
-void IndexedDBFactoryImpl::DatabaseDeleted(
- const IndexedDBDatabase::Identifier& identifier) {
- // NULL after ContextDestroyed() called, and in some unit tests.
- if (!context_)
- return;
- context_->DatabaseDeleted(identifier.first);
+ it->second->ReportOutstandingBlobs(blobs_outstanding);
}
void IndexedDBFactoryImpl::BlobFilesCleaned(const url::Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// NULL after ContextDestroyed() called, and in some unit tests.
if (!context_)
return;
@@ -541,11 +457,14 @@ void IndexedDBFactoryImpl::BlobFilesCleaned(const url::Origin& origin) {
}
size_t IndexedDBFactoryImpl::GetConnectionCount(const Origin& origin) const {
- size_t count(0);
-
- OriginDBs range = GetOpenDatabasesForOrigin(origin);
- for (auto it = range.first; it != range.second; ++it)
- count += it->second->ConnectionCount();
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = factories_per_origin_.find(origin);
+ if (it == factories_per_origin_.end())
+ return 0;
+ size_t count = 0;
+ for (const auto& name_database_pair : it->second->databases()) {
+ count += name_database_pair.second->ConnectionCount();
+ }
return count;
}
@@ -554,6 +473,7 @@ void IndexedDBFactoryImpl::NotifyIndexedDBContentChanged(
const url::Origin& origin,
const base::string16& database_name,
const base::string16& object_store_name) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!context_)
return;
context_->NotifyIndexedDBContentChanged(origin, database_name,
@@ -561,12 +481,11 @@ void IndexedDBFactoryImpl::NotifyIndexedDBContentChanged(
}
int64_t IndexedDBFactoryImpl::GetInMemoryDBSize(const Origin& origin) const {
- auto it = backing_store_map_.find(origin);
- // Origin won't be present in map if it has been deleted.
- if (it == backing_store_map_.end())
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = factories_per_origin_.find(origin);
+ if (it == factories_per_origin_.end())
return 0;
-
- IndexedDBBackingStore* backing_store = it->second.get();
+ IndexedDBBackingStore* backing_store = it->second->backing_store();
int64_t level_db_size = 0;
leveldb::Status s =
GetDBSizeFromEnv(backing_store->db()->env(), "/", &level_db_size);
@@ -578,32 +497,44 @@ int64_t IndexedDBFactoryImpl::GetInMemoryDBSize(const Origin& origin) const {
base::Time IndexedDBFactoryImpl::GetLastModified(
const url::Origin& origin) const {
- auto it = backing_store_map_.find(origin);
- if (it == backing_store_map_.end())
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = factories_per_origin_.find(origin);
+ if (it == factories_per_origin_.end())
return base::Time();
- IndexedDBBackingStore* backing_store = it->second.get();
+ IndexedDBBackingStore* backing_store = it->second->backing_store();
return backing_store->db()->LastModified();
}
-std::tuple<scoped_refptr<IndexedDBBackingStore>,
+std::vector<url::Origin> IndexedDBFactoryImpl::GetOpenOrigins() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ std::vector<url::Origin> output;
+ for (const auto& pair : factories_per_origin_) {
+ output.push_back(pair.first);
+ }
+ return output;
+}
+
+IndexedDBOriginState* IndexedDBFactoryImpl::GetOriginFactory(
+ const url::Origin& origin) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = factories_per_origin_.find(origin);
+ if (it != factories_per_origin_.end())
+ return it->second.get();
+ return nullptr;
+}
+
+std::tuple<IndexedDBOriginStateHandle,
leveldb::Status,
- IndexedDBDataLossInfo,
- bool /* disk_full */>
-IndexedDBFactoryImpl::OpenBackingStore(const Origin& origin,
- const base::FilePath& data_directory) {
- auto it2 = backing_store_map_.find(origin);
- scoped_refptr<IndexedDBBackingStore> backing_store;
- if (it2 != backing_store_map_.end()) {
- // Grab a refptr so the completion of the preclose task list doesn't close
- // the backing store.
- backing_store = it2->second;
- backing_store->close_timer()->Stop();
- if (it2->second->pre_close_task_queue()) {
- backing_store->pre_close_task_queue()->StopForNewConnection();
- backing_store->SetPreCloseTaskList(nullptr);
- }
- return {std::move(backing_store), leveldb::Status::OK(),
- IndexedDBDataLossInfo(), false};
+ IndexedDBDatabaseError,
+ IndexedDBDataLossInfo>
+IndexedDBFactoryImpl::GetOrOpenOriginFactory(
+ const Origin& origin,
+ const base::FilePath& data_directory) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = factories_per_origin_.find(origin);
+ if (it != factories_per_origin_.end()) {
+ return {it->second->CreateHandle(), leveldb::Status::OK(),
+ IndexedDBDatabaseError(), IndexedDBDataLossInfo()};
}
base::FilePath blob_path;
@@ -614,7 +545,8 @@ IndexedDBFactoryImpl::OpenBackingStore(const Origin& origin,
std::tie(database_path, blob_path, s) =
indexed_db::CreateDatabaseDirectories(data_directory, origin);
if (!s.ok())
- return {std::move(backing_store), s, IndexedDBDataLossInfo(), false};
+ return {IndexedDBOriginStateHandle(), s, CreateDefaultError(),
+ IndexedDBDataLossInfo()};
}
std::unique_ptr<LevelDBDatabase> database;
IndexedDBDataLossInfo data_loss_info;
@@ -623,254 +555,114 @@ IndexedDBFactoryImpl::OpenBackingStore(const Origin& origin,
indexed_db::OpenAndVerifyLevelDBDatabase(origin, data_directory,
database_path, leveldb_factory_,
context_->TaskRunner());
- if (!s.ok())
- return {std::move(backing_store), s, data_loss_info, disk_full};
-
+ if (!s.ok()) {
+ if (disk_full) {
+ return {IndexedDBOriginStateHandle(), s,
+ IndexedDBDatabaseError(
+ blink::kWebIDBDatabaseExceptionQuotaError,
+ ASCIIToUTF16("Encountered full disk while opening "
+ "backing store for indexedDB.open.")),
+ data_loss_info};
+
+ } else {
+ return {IndexedDBOriginStateHandle(), s, CreateDefaultError(),
+ data_loss_info};
+ }
+ }
+ bool is_in_memory = data_directory.empty();
IndexedDBBackingStore::Mode backing_store_mode =
- data_directory.empty() ? IndexedDBBackingStore::Mode::kInMemory
- : IndexedDBBackingStore::Mode::kOnDisk;
- backing_store =
+ is_in_memory ? IndexedDBBackingStore::Mode::kInMemory
+ : IndexedDBBackingStore::Mode::kOnDisk;
+ std::unique_ptr<IndexedDBBackingStore> backing_store =
CreateBackingStore(backing_store_mode, origin, blob_path,
std::move(database), context_->TaskRunner());
+
bool first_open_since_startup =
backends_opened_since_startup_.insert(origin).second;
s = backing_store->Initialize(
/*cleanup_live_journal=*/!database_path.empty() &&
first_open_since_startup);
- if (!s.ok()) {
- backing_store.reset();
- return {std::move(backing_store), s, data_loss_info, disk_full};
- }
- // If an in-memory database, bind lifetime to this factory instance.
- if (database_path.empty())
- in_memory_backing_stores_.insert(backing_store);
- backing_store_map_[origin] = backing_store;
-
- // All backing stores associated with this factory should be of the same
- // type.
- DCHECK_EQ(!in_memory_backing_stores_.empty(), database_path.empty());
- DCHECK(backing_store);
- return {std::move(backing_store), s, data_loss_info, disk_full};
-}
-scoped_refptr<IndexedDBBackingStore> IndexedDBFactoryImpl::CreateBackingStore(
+ if (!s.ok())
+ return {IndexedDBOriginStateHandle(), s, CreateDefaultError(),
+ data_loss_info};
+
+ it = factories_per_origin_
+ .emplace(origin,
+ std::make_unique<IndexedDBOriginState>(
+ is_in_memory, clock_, &earliest_sweep_,
+ base::BindOnce(
+ &IndexedDBFactoryImpl::RemoveOriginState,
+ origin_state_destruction_weak_factory_.GetWeakPtr(),
+ origin),
+ std::move(backing_store)))
+ .first;
+ context_->FactoryOpened(origin);
+ return {it->second->CreateHandle(), s, IndexedDBDatabaseError(),
+ data_loss_info};
+}
+
+std::unique_ptr<IndexedDBBackingStore> IndexedDBFactoryImpl::CreateBackingStore(
IndexedDBBackingStore::Mode backing_store_mode,
const url::Origin& origin,
const base::FilePath& blob_path,
std::unique_ptr<LevelDBDatabase> db,
base::SequencedTaskRunner* task_runner) {
- return base::MakeRefCounted<IndexedDBBackingStore>(
+ return std::make_unique<IndexedDBBackingStore>(
backing_store_mode, this, origin, blob_path, std::move(db), task_runner);
}
-void IndexedDBFactoryImpl::ReleaseBackingStore(const Origin& origin,
- bool immediate) {
- if (!base::ContainsKey(backing_store_map_, origin))
- return;
- if (immediate) {
- auto it = backing_stores_with_active_blobs_.find(origin);
- if (it != backing_stores_with_active_blobs_.end()) {
- it->second->active_blob_registry()->ForceShutdown();
- backing_stores_with_active_blobs_.erase(it);
- }
- }
-
- // Only close if this is the last reference.
- if (!HasLastBackingStoreReference(origin))
- return;
-
- // If this factory does hold the last reference to the backing store, it can
- // be closed - but unless requested to close it immediately, keep it around
- // for a short period so that a re-open is fast.
- if (immediate) {
- CloseBackingStore(origin);
- 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());
- backing_store_map_[origin]->close_timer()->Start(
- FROM_HERE, base::TimeDelta::FromSeconds(kBackingStoreGracePeriodSeconds),
- base::BindOnce(&IndexedDBFactoryImpl::MaybeStartPreCloseTasks, this,
- origin));
-}
-
-void IndexedDBFactoryImpl::CloseBackingStore(const Origin& origin) {
- auto it = backing_store_map_.find(origin);
- if (it == backing_store_map_.end())
- return;
- // Stop the timer and pre close tasks (if they are running) - this may happen
- // if the timer was started and then a forced close occurs.
- IndexedDBBackingStore* backing_store = it->second.get();
- backing_store->close_timer()->Stop();
- backing_store->SetPreCloseTaskList(nullptr);
-
- if (backing_store->IsBlobCleanupPending())
- backing_store->ForceRunBlobCleanup();
-
- backing_store_map_.erase(it);
-}
-
-leveldb::Status IndexedDBFactoryImpl::AbortTransactions(const Origin& origin) {
- auto it = backing_store_map_.find(origin);
- if (it == backing_store_map_.end()) {
- return leveldb::Status::IOError(
- "Internal error opening backing store for "
- "indexedDB.abortTransactions.");
- }
- IndexedDBBackingStore* backing_store = it->second.get();
-
- leveldb::Status get_names_status;
- IndexedDBMetadataCoding metadata_coding;
- std::vector<base::string16> db_names;
- get_names_status = metadata_coding.ReadDatabaseNames(
- backing_store->db(), backing_store->origin_identifier(), &db_names);
- if (!get_names_status.ok()) {
- return leveldb::Status::IOError(
- "Internal error getting origin database names for "
- "indexedDB.abortTransactions.");
- }
-
- for (base::string16& name : db_names) {
- auto database_it = database_map_.find(std::make_pair(origin, name));
- if (database_it != database_map_.end())
- database_it->second->AbortAllTransactionsForConnections();
+void IndexedDBFactoryImpl::RemoveOriginState(const url::Origin& origin) {
+ factories_per_origin_.erase(origin);
+}
+
+void IndexedDBFactoryImpl::OnDatabaseError(const url::Origin& origin,
+ leveldb::Status status,
+ const char* message) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!status.ok());
+ if (status.IsCorruption()) {
+ IndexedDBDatabaseError error =
+ message != nullptr
+ ? IndexedDBDatabaseError(
+ blink::kWebIDBDatabaseExceptionUnknownError, message)
+ : IndexedDBDatabaseError(
+ blink::kWebIDBDatabaseExceptionUnknownError,
+ base::ASCIIToUTF16(status.ToString()));
+ HandleBackingStoreCorruption(origin, error);
+ } else {
+ HandleBackingStoreFailure(origin);
}
-
- return leveldb::Status::OK();
}
-void IndexedDBFactoryImpl::MaybeStartPreCloseTasks(const Origin& origin) {
- if (!base::ContainsKey(backing_store_map_, origin))
- return;
- // Another reference may have been created since the maybe-close was posted,
- // so it is necessary to check again.
- if (!HasLastBackingStoreReference(origin))
- return;
-
- base::ScopedClosureRunner maybe_close_backing_store_runner(
- base::BindOnce(&IndexedDBFactoryImpl::MaybeCloseBackingStore,
- base::Unretained(this), origin));
-
- base::Time now = clock_->Now();
-
- // Check that the last sweep hasn't run too recently.
- if (earliest_sweep_ > now)
- return;
-
- bool tombstone_stats_enabled =
- base::FeatureList::IsEnabled(kIDBTombstoneStatistics);
- bool tombstone_deletion_enabled =
- base::FeatureList::IsEnabled(kIDBTombstoneDeletion);
-
- // After this check, exactly one of the flags must be true.
- if (tombstone_stats_enabled == tombstone_deletion_enabled)
- return;
-
- scoped_refptr<IndexedDBBackingStore> store = backing_store_map_[origin];
-
- base::Time origin_earliest_sweep;
- leveldb::Status s =
- indexed_db::GetEarliestSweepTime(store->db(), &origin_earliest_sweep);
- // TODO(dmurph): Log this or report to UMA.
- if (!s.ok())
- return;
-
- // This origin hasn't been swept too recently.
- if (origin_earliest_sweep > now)
- return;
-
- // A sweep will happen now, so reset the sweep timers.
- earliest_sweep_ = GenerateNextGlobalSweepTime(now);
- scoped_refptr<LevelDBTransaction> txn =
- IndexedDBClassFactory::Get()->CreateLevelDBTransaction(store->db());
- indexed_db::SetEarliestSweepTime(txn.get(), GenerateNextOriginSweepTime(now));
- s = txn->Commit();
-
- // TODO(dmurph): Log this or report to UMA.
- if (!s.ok())
- return;
-
- std::list<std::unique_ptr<PreCloseTask>> tasks;
- IndexedDBTombstoneSweeper::Mode mode =
- tombstone_stats_enabled ? IndexedDBTombstoneSweeper::Mode::STATISTICS
- : IndexedDBTombstoneSweeper::Mode::DELETION;
- tasks.push_back(std::make_unique<IndexedDBTombstoneSweeper>(
- mode, kTombstoneSweeperRoundIterations, kTombstoneSweeperMaxIterations,
- store->db()->db()));
- // TODO(dmurph): Add compaction task that compacts all indexes if we have
- // more than X deletions.
-
- store->SetPreCloseTaskList(std::make_unique<IndexedDBPreCloseTaskQueue>(
- std::move(tasks), maybe_close_backing_store_runner.Release(),
- base::TimeDelta::FromSeconds(kPreCloseTasksMaxRunPeriodSeconds),
- std::make_unique<base::OneShotTimer>()));
- store->StartPreCloseTasks();
-}
-
-void IndexedDBFactoryImpl::MaybeCloseBackingStore(const Origin& origin) {
- auto it = backing_store_map_.find(origin);
- if (it == backing_store_map_.end())
+void IndexedDBFactoryImpl::OnDatabaseDeleted(const url::Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!context_)
return;
-
- IndexedDBBackingStore* backing_store = it->second.get();
- backing_store->SetPreCloseTaskList(nullptr);
- // Another reference may have opened since the maybe-close was posted, so it
- // is necessary to check again.
- if (HasLastBackingStoreReference(origin))
- CloseBackingStore(origin);
-}
-
-bool IndexedDBFactoryImpl::HasLastBackingStoreReference(
- const Origin& origin) const {
- auto it = backing_store_map_.find(origin);
- if (it == backing_store_map_.end())
- return false;
- return it->second->HasOneRef();
+ context_->DatabaseDeleted(origin);
}
bool IndexedDBFactoryImpl::IsDatabaseOpen(const Origin& origin,
const base::string16& name) const {
- return base::ContainsKey(database_map_,
- IndexedDBDatabase::Identifier(origin, name));
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = factories_per_origin_.find(origin);
+ if (it == factories_per_origin_.end())
+ return false;
+ return base::ContainsKey(it->second->databases(), name);
}
bool IndexedDBFactoryImpl::IsBackingStoreOpen(const Origin& origin) const {
- return base::ContainsKey(backing_store_map_, origin);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return base::ContainsKey(factories_per_origin_, origin);
}
bool IndexedDBFactoryImpl::IsBackingStorePendingClose(
const Origin& origin) const {
- auto it = backing_store_map_.find(origin);
- if (it == backing_store_map_.end())
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = factories_per_origin_.find(origin);
+ if (it == factories_per_origin_.end())
return false;
- return it->second->close_timer()->IsRunning() ||
- it->second->pre_close_task_queue();
-}
-
-void IndexedDBFactoryImpl::RemoveDatabaseFromMaps(
- const IndexedDBDatabase::Identifier& identifier) {
- auto it = database_map_.find(identifier);
- DCHECK(it != database_map_.end());
- IndexedDBDatabase* database = it->second;
- database_map_.erase(it);
-
- std::pair<OriginDBMap::iterator, OriginDBMap::iterator> range =
- origin_dbs_.equal_range(database->identifier().first);
- DCHECK(range.first != range.second);
- for (auto it2 = range.first; it2 != range.second; ++it2) {
- if (it2->second == database) {
- origin_dbs_.erase(it2);
- break;
- }
- }
+ return it->second->IsClosing();
}
} // namespace content
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 46a6df8c390..6455764cf8a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -7,56 +7,50 @@
#include <stddef.h>
-#include <map>
#include <memory>
#include <set>
#include <tuple>
#include <utility>
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
#include "base/time/clock.h"
#include "base/time/time.h"
+#include "content/browser/indexed_db/indexed_db_backing_store.h"
+#include "content/browser/indexed_db/indexed_db_data_loss_info.h"
+#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_factory.h"
+#include "content/browser/indexed_db/indexed_db_origin_state_handle.h"
#include "content/browser/indexed_db/leveldb/leveldb_env.h"
+#include "third_party/leveldatabase/src/include/leveldb/status.h"
+#include "url/origin.h"
namespace base {
-struct Feature;
+class FilePath;
+class SequencedTaskRunner;
}
-
namespace url {
class Origin;
}
namespace content {
-
+class LevelDBDatabase;
class IndexedDBContextImpl;
-
-CONTENT_EXPORT extern const base::Feature kIDBTombstoneStatistics;
-CONTENT_EXPORT extern const base::Feature kIDBTombstoneDeletion;
-
-constexpr const char kIDBCloseImmediatelySwitch[] = "idb-close-immediately";
+class IndexedDBFactoryImpl;
+class IndexedDBOriginState;
class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
public:
- // Maximum time interval between runs of the IndexedDBSweeper. Sweeping only
- // occurs after backing store close.
- // Visible for testing.
- static constexpr const base::TimeDelta kMaxEarliestGlobalSweepFromNow =
- base::TimeDelta::FromHours(2);
- // Maximum time interval between runs of the IndexedDBSweeper for a given
- // origin. Sweeping only occurs after backing store close.
- // Visible for testing.
- static constexpr const base::TimeDelta kMaxEarliestOriginSweepFromNow =
- base::TimeDelta::FromDays(7);
-
IndexedDBFactoryImpl(IndexedDBContextImpl* context,
indexed_db::LevelDBFactory* leveldb_factory,
base::Clock* clock);
+ ~IndexedDBFactoryImpl() override;
// content::IndexedDBFactory overrides:
- void ReleaseDatabase(const IndexedDBDatabase::Identifier& identifier,
- bool forced_close) override;
void GetDatabaseInfo(scoped_refptr<IndexedDBCallbacks> callbacks,
const url::Origin& origin,
const base::FilePath& data_directory) override;
@@ -68,12 +62,11 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
const url::Origin& origin,
const base::FilePath& data_directory) override;
- void DeleteDatabase(
- const base::string16& name,
- scoped_refptr<IndexedDBCallbacks> callbacks,
- const url::Origin& origin,
- const base::FilePath& data_directory,
- bool force_close) override;
+ void DeleteDatabase(const base::string16& name,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ const url::Origin& origin,
+ const base::FilePath& data_directory,
+ bool force_close) override;
void AbortTransactionsAndCompactDatabase(
base::OnceCallback<void(leveldb::Status)> callback,
@@ -87,10 +80,14 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
const url::Origin& origin,
const IndexedDBDatabaseError& error) override;
- OriginDBs GetOpenDatabasesForOrigin(const url::Origin& origin) const override;
+ std::vector<IndexedDBDatabase*> GetOpenDatabasesForOrigin(
+ const url::Origin& origin) const override;
+ // TODO(dmurph): This eventually needs to be async, to support scopes
+ // multithreading.
void ForceClose(const url::Origin& origin,
bool delete_in_memory_store) override;
+
void ForceSchemaDowngrade(const url::Origin& origin) override;
V2SchemaCorruptionStatus HasV2SchemaCorruption(
const url::Origin& origin) override;
@@ -102,10 +99,6 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
void ReportOutstandingBlobs(const url::Origin& origin,
bool blobs_outstanding) override;
- // Called by an IndexedDBDatabase when it is actually deleted.
- void DatabaseDeleted(
- const IndexedDBDatabase::Identifier& identifier) override;
-
// Called by IndexedDBBackingStore when blob files have been cleaned.
void BlobFilesCleaned(const url::Origin& origin) override;
@@ -120,29 +113,34 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
base::Time GetLastModified(const url::Origin& origin) const override;
- protected:
- ~IndexedDBFactoryImpl() override;
+ std::vector<url::Origin> GetOpenOrigins() const;
- std::tuple<scoped_refptr<IndexedDBBackingStore>,
+ IndexedDBOriginState* GetOriginFactory(const url::Origin& origin) const;
+
+ // On an OK status, the factory handle is populated. Otherwise (when status is
+ // not OK), the |IndexedDBDatabaseError| will be populated. If the status was
+ // corruption, the |IndexedDBDataLossInfo| will also be populated.
+ std::tuple<IndexedDBOriginStateHandle,
leveldb::Status,
- IndexedDBDataLossInfo,
- bool /* disk_full */>
- OpenBackingStore(const url::Origin& origin,
- const base::FilePath& data_directory) override;
+ IndexedDBDatabaseError,
+ IndexedDBDataLossInfo>
+ GetOrOpenOriginFactory(const url::Origin& origin,
+ const base::FilePath& data_directory);
+ protected:
// Used by unittests to allow subclassing of IndexedDBBackingStore.
- virtual scoped_refptr<IndexedDBBackingStore> CreateBackingStore(
+ virtual std::unique_ptr<IndexedDBBackingStore> CreateBackingStore(
IndexedDBBackingStore::Mode backing_store_mode,
const url::Origin& origin,
const base::FilePath& blob_path,
std::unique_ptr<LevelDBDatabase> db,
base::SequencedTaskRunner* task_runner);
- void ReleaseBackingStore(const url::Origin& origin, bool immediate);
- void CloseBackingStore(const url::Origin& origin);
IndexedDBContextImpl* context() const { return context_; }
private:
+ friend IndexedDBOriginState;
+
FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
BackingStoreReleasedOnForcedClose);
FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
@@ -161,42 +159,40 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
FRIEND_TEST_ALL_PREFIXES(IndexedDBTest,
ForceCloseOpenDatabasesOnCommitFailure);
- leveldb::Status AbortTransactions(const url::Origin& origin);
+ void RemoveOriginState(const url::Origin& origin);
- // Called internally after a database is closed, with some delay. If this
- // factory has the last reference it will start running pre-close tasks.
- void MaybeStartPreCloseTasks(const url::Origin& origin);
- // Called internally after pre-close tasks. If this factory has the last
- // reference it will be released.
- void MaybeCloseBackingStore(const url::Origin& origin);
- bool HasLastBackingStoreReference(const url::Origin& origin) const;
+ void OnDatabaseError(const url::Origin& origin,
+ leveldb::Status s,
+ const char* message);
- // Testing helpers, so unit tests don't need to grovel through internal state.
+ // Called when the database has been deleted on disk.
+ void OnDatabaseDeleted(const url::Origin& origin);
+
+ // Testing helpers, so unit tests don't need to grovel through internal
+ // state.
bool IsDatabaseOpen(const url::Origin& origin,
const base::string16& name) const;
bool IsBackingStoreOpen(const url::Origin& origin) const;
bool IsBackingStorePendingClose(const url::Origin& origin) const;
- void RemoveDatabaseFromMaps(const IndexedDBDatabase::Identifier& identifier);
+ SEQUENCE_CHECKER(sequence_checker_);
IndexedDBContextImpl* context_;
indexed_db::LevelDBFactory* leveldb_factory_;
-
- std::map<IndexedDBDatabase::Identifier, IndexedDBDatabase*> database_map_;
- OriginDBMap origin_dbs_;
- std::map<url::Origin, scoped_refptr<IndexedDBBackingStore>>
- backing_store_map_;
-
- // In-memory (incognito) backing stores should live as long as the
- // StoragePartition which owns the IndexedDBContext which owns this
- // IndexedDBFactory.
- std::set<scoped_refptr<IndexedDBBackingStore>> in_memory_backing_stores_;
- std::map<url::Origin, scoped_refptr<IndexedDBBackingStore>>
- backing_stores_with_active_blobs_;
- std::set<url::Origin> backends_opened_since_startup_;
-
base::Clock* clock_;
base::Time earliest_sweep_;
+ base::flat_map<url::Origin, std::unique_ptr<IndexedDBOriginState>>
+ factories_per_origin_;
+
+ std::set<url::Origin> backends_opened_since_startup_;
+
+ // Weak pointers from this factory are used to bind the RemoveOriginState()
+ // function, which deletes the IndexedDBOriginState object. This allows those
+ // weak pointers to be invalidated during force close & shutdown to prevent
+ // re-entry (see ContextDestroyed()).
+ base::WeakPtrFactory<IndexedDBFactoryImpl>
+ origin_state_destruction_weak_factory_{this};
+ base::WeakPtrFactory<IndexedDBFactoryImpl> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(IndexedDBFactoryImpl);
};
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 c31a0dd6665..133a6de6501 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -6,11 +6,13 @@
#include <utility>
#include "base/auto_reset.h"
+#include "base/barrier_closure.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
@@ -22,9 +24,14 @@
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_data_format_version.h"
#include "content/browser/indexed_db/indexed_db_factory_impl.h"
+#include "content/browser/indexed_db/indexed_db_origin_state.h"
+#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
+#include "content/browser/indexed_db/indexed_db_transaction.h"
+#include "content/browser/indexed_db/leveldb/fake_leveldb_factory.h"
#include "content/browser/indexed_db/leveldb/leveldb_env.h"
#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
+#include "content/public/browser/storage_usage_info.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "storage/browser/test/mock_quota_manager_proxy.h"
@@ -50,64 +57,144 @@ base::FilePath CreateAndReturnTempDir(base::ScopedTempDir* temp_dir) {
void CreateAndBindTransactionPlaceholder(
base::WeakPtr<IndexedDBTransaction> transaction) {}
-class MockIDBFactory : public IndexedDBFactoryImpl {
+} // namespace
+
+class IndexedDBFactoryTest : public testing::Test {
public:
- explicit MockIDBFactory(IndexedDBContextImpl* context)
- : MockIDBFactory(context, base::DefaultClock::GetInstance()) {}
- MockIDBFactory(IndexedDBContextImpl* context, base::Clock* clock)
- : IndexedDBFactoryImpl(context,
- indexed_db::GetDefaultLevelDBFactory(),
- clock) {}
- scoped_refptr<IndexedDBBackingStore> TestOpenBackingStore(
- const Origin& origin,
- const base::FilePath& data_directory) {
- IndexedDBDataLossInfo data_loss_info;
- bool disk_full;
- leveldb::Status s;
- scoped_refptr<IndexedDBBackingStore> backing_store;
- std::tie(backing_store, s, data_loss_info, disk_full) =
- OpenBackingStore(origin, data_directory);
- EXPECT_EQ(blink::mojom::IDBDataLoss::None, data_loss_info.status);
- return backing_store;
- }
+ IndexedDBFactoryTest()
+ : thread_bundle_(std::make_unique<TestBrowserThreadBundle>()),
+ quota_manager_proxy_(
+ base::MakeRefCounted<MockQuotaManagerProxy>(nullptr, nullptr)) {}
+
+ IndexedDBFactoryTest(std::unique_ptr<TestBrowserThreadBundle> thread_bundle)
+ : thread_bundle_(std::move(thread_bundle)),
+ quota_manager_proxy_(
+ base::MakeRefCounted<MockQuotaManagerProxy>(nullptr, nullptr)) {}
- void TestCloseBackingStore(IndexedDBBackingStore* backing_store) {
- CloseBackingStore(backing_store->origin());
+ void TearDown() override {
+ quota_manager_proxy_->SimulateQuotaManagerDestroyed();
+
+ if (context_ && !context_->IsInMemoryContext()) {
+ IndexedDBFactoryImpl* factory = context_->GetIDBFactory();
+
+ // Loop through all open origins, and force close them, and request the
+ // deletion of the leveldb state. Once the states are no longer around,
+ // delete all of the databases on disk.
+ auto open_factory_origins = factory->GetOpenOrigins();
+ base::RunLoop loop;
+ auto callback = base::BarrierClosure(
+ open_factory_origins.size(), base::BindLambdaForTesting([&]() {
+ // All leveldb databases are closed, and they can be deleted.
+ for (auto origin : context_->GetAllOrigins()) {
+ context_->DeleteForOrigin(origin);
+ }
+ loop.Quit();
+ }));
+ for (auto origin : open_factory_origins) {
+ IndexedDBOriginState* per_origin_factory =
+ factory->GetOriginFactory(origin);
+ per_origin_factory->backing_store()
+ ->db()
+ ->leveldb_state()
+ ->RequestDestruction(callback,
+ base::SequencedTaskRunnerHandle::Get());
+ context_->ForceClose(origin,
+ IndexedDBContextImpl::FORCE_CLOSE_DELETE_ORIGIN);
+ }
+ loop.Run();
+ }
+ if (temp_dir_.IsValid())
+ ASSERT_TRUE(temp_dir_.Delete());
}
- void TestReleaseBackingStore(IndexedDBBackingStore* backing_store,
- bool immediate) {
- ReleaseBackingStore(backing_store->origin(), immediate);
+ void SetupContext() {
+ context_ = base::MakeRefCounted<IndexedDBContextImpl>(
+ CreateAndReturnTempDir(&temp_dir_),
+ /*special_storage_policy=*/nullptr, quota_manager_proxy_.get(),
+ indexed_db::GetDefaultLevelDBFactory(),
+ base::DefaultClock::GetInstance());
+ context_->SetTaskRunnerForTesting(base::SequencedTaskRunnerHandle::Get());
}
- private:
- ~MockIDBFactory() override {}
+ void SetupInMemoryContext() {
+ context_ = base::MakeRefCounted<IndexedDBContextImpl>(
+ base::FilePath(),
+ /*special_storage_policy=*/nullptr, quota_manager_proxy_.get(),
+ indexed_db::GetDefaultLevelDBFactory(),
+ base::DefaultClock::GetInstance());
+ context_->SetTaskRunnerForTesting(base::SequencedTaskRunnerHandle::Get());
+ }
- DISALLOW_COPY_AND_ASSIGN(MockIDBFactory);
-};
+ void SetupContextWithFactories(indexed_db::LevelDBFactory* factory,
+ base::Clock* clock) {
+ context_ = base::MakeRefCounted<IndexedDBContextImpl>(
+ CreateAndReturnTempDir(&temp_dir_),
+ /*special_storage_policy=*/nullptr, quota_manager_proxy_.get(), factory,
+ clock);
+ context_->SetTaskRunnerForTesting(base::SequencedTaskRunnerHandle::Get());
+ }
-} // namespace
+ // Runs through the upgrade flow to create a basic database connection. There
+ // is no actual data in the database.
+ std::tuple<std::unique_ptr<IndexedDBConnection>,
+ scoped_refptr<MockIndexedDBDatabaseCallbacks>>
+ CreateConnectionForDatatabase(const Origin& origin,
+ const base::string16& name) {
+ auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>();
+ auto db_callbacks = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
+ const int64_t transaction_id = 1;
+ auto create_transaction_callback =
+ base::BindOnce(&CreateAndBindTransactionPlaceholder);
+ auto connection = std::make_unique<IndexedDBPendingConnection>(
+ callbacks, db_callbacks, /*child_process_id=*/0, transaction_id,
+ IndexedDBDatabaseMetadata::NO_VERSION,
+ std::move(create_transaction_callback));
+
+ // Do the first half of the upgrade, and request the upgrade from renderer.
+ {
+ base::RunLoop loop;
+ callbacks->CallOnUpgradeNeeded(
+ base::BindLambdaForTesting([&]() { loop.Quit(); }));
+ factory()->Open(name, std::move(connection), origin,
+ context()->data_path());
+ loop.Run();
+ }
-class IndexedDBFactoryTest : public testing::Test {
- public:
- IndexedDBFactoryTest()
- : quota_manager_proxy_(
- base::MakeRefCounted<MockQuotaManagerProxy>(nullptr, nullptr)),
- context_(base::MakeRefCounted<IndexedDBContextImpl>(
- CreateAndReturnTempDir(&temp_dir_),
- /*special_storage_policy=*/nullptr,
- quota_manager_proxy_.get(),
- indexed_db::GetDefaultLevelDBFactory())) {}
+ EXPECT_TRUE(callbacks->upgrade_called());
+ EXPECT_TRUE(callbacks->connection());
+ EXPECT_TRUE(callbacks->connection()->database());
+ if (!callbacks->connection())
+ return {nullptr, nullptr};
- void TearDown() override {
- quota_manager_proxy_->SimulateQuotaManagerDestroyed();
+ // Finish the upgrade by committing the transaction.
+ {
+ base::RunLoop loop;
+ callbacks->CallOnDBSuccess(
+ base::BindLambdaForTesting([&]() { loop.Quit(); }));
+ callbacks->connection()
+ ->transactions()
+ .find(transaction_id)
+ ->second->Commit();
+ loop.Run();
+ }
+ return {callbacks->TakeConnection(), db_callbacks};
}
protected:
IndexedDBContextImpl* context() const { return context_.get(); }
+ IndexedDBFactoryImpl* factory() const { return context_->GetIDBFactory(); }
+
+ TestBrowserThreadBundle* thread_bundle() const {
+ return thread_bundle_.get();
+ }
+ IndexedDBOriginState* OriginStateFromHandle(
+ IndexedDBOriginStateHandle& handle) {
+ return handle.origin_state();
+ }
+
private:
- TestBrowserThreadBundle thread_bundle_;
+ std::unique_ptr<TestBrowserThreadBundle> thread_bundle_;
base::ScopedTempDir temp_dir_;
scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
@@ -116,598 +203,519 @@ class IndexedDBFactoryTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(IndexedDBFactoryTest);
};
-TEST_F(IndexedDBFactoryTest, BackingStoreLifetime) {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- auto factory = base::MakeRefCounted<MockIDBFactory>(context());
+class IndexedDBFactoryTestWithMockTime : public IndexedDBFactoryTest {
+ public:
+ IndexedDBFactoryTestWithMockTime()
+ : IndexedDBFactoryTest(std::make_unique<TestBrowserThreadBundle>(
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME)) {}
- const Origin origin1 = Origin::Create(GURL("http://localhost:81"));
- const Origin origin2 = Origin::Create(GURL("http://localhost:82"));
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBFactoryTestWithMockTime);
+};
- auto disk_store1 =
- factory->TestOpenBackingStore(origin1, context()->data_path());
+TEST_F(IndexedDBFactoryTest, BasicFactoryCreationAndTearDown) {
+ SetupContext();
- auto disk_store2 =
- factory->TestOpenBackingStore(origin1, context()->data_path());
- EXPECT_EQ(disk_store1.get(), disk_store2.get());
+ const Origin origin1 = Origin::Create(GURL("http://localhost:81"));
+ const Origin origin2 = Origin::Create(GURL("http://localhost:82"));
- auto disk_store3 =
- factory->TestOpenBackingStore(origin2, context()->data_path());
+ IndexedDBOriginStateHandle origin_state1_handle;
+ IndexedDBOriginStateHandle origin_state2_handle;
+ leveldb::Status s;
- factory->TestCloseBackingStore(disk_store1.get());
- factory->TestCloseBackingStore(disk_store3.get());
+ std::tie(origin_state1_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(origin1, context()->data_path());
+ EXPECT_TRUE(origin_state1_handle.IsHeld()) << s.ToString();
- EXPECT_FALSE(disk_store1->HasOneRef());
- EXPECT_FALSE(disk_store2->HasOneRef());
- EXPECT_TRUE(disk_store3->HasOneRef());
+ std::tie(origin_state2_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(origin2, context()->data_path());
+ EXPECT_TRUE(origin_state2_handle.IsHeld()) << s.ToString();
- disk_store2 = nullptr;
- EXPECT_TRUE(disk_store1->HasOneRef());
- loop.Quit();
- }));
- loop.Run();
+ std::vector<StorageUsageInfo> origin_info = context()->GetAllOriginsInfo();
+ EXPECT_EQ(2ul, origin_info.size());
+ EXPECT_EQ(2ul, factory()->GetOpenOrigins().size());
}
-TEST_F(IndexedDBFactoryTest, BackingStoreLazyClose) {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- auto factory = base::MakeRefCounted<MockIDBFactory>(context());
-
- const Origin origin = Origin::Create(GURL("http://localhost:81"));
-
- auto 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_TRUE(store_ptr->close_timer()->IsRunning());
-
- factory->TestOpenBackingStore(origin, context()->data_path());
- EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
- factory->TestReleaseBackingStore(store_ptr, false);
- EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
-
- // Take back a ref ptr and ensure that the actual close
- // stops a running timer.
- store = store_ptr;
- factory->TestCloseBackingStore(store_ptr);
- EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
- loop.Quit();
- }));
- loop.Run();
+TEST_F(IndexedDBFactoryTest, CloseSequenceStarts) {
+ SetupContext();
+
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
+
+ IndexedDBOriginStateHandle origin_state_handle;
+ leveldb::Status s;
+
+ std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(origin, context()->data_path());
+ EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
+ origin_state_handle.Release();
+
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_TRUE(factory()->GetOriginFactory(origin)->IsClosing());
+
+ factory()->ForceClose(origin, false);
+ EXPECT_FALSE(factory()->GetOriginFactory(origin));
}
-TEST_F(IndexedDBFactoryTest, BackingStoreNoSweeping) {
+TEST_F(IndexedDBFactoryTest, ImmediateClose) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ kIDBCloseImmediatelySwitch);
+ SetupContext();
+
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
+
+ IndexedDBOriginStateHandle origin_state_handle;
+ leveldb::Status s;
+
+ std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(origin, context()->data_path());
+ EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
+ origin_state_handle.Release();
+
+ EXPECT_FALSE(factory()->GetOriginFactory(origin));
+ EXPECT_EQ(0ul, factory()->GetOpenOrigins().size());
+}
+
+TEST_F(IndexedDBFactoryTestWithMockTime, CloseWithoutSweeping) {
base::test::ScopedFeatureList feature_list;
feature_list.InitWithFeatures(
{}, {kIDBTombstoneDeletion, kIDBTombstoneStatistics});
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- base::SimpleTestClock clock;
- clock.SetNow(base::Time::Now());
-
- auto factory = base::MakeRefCounted<MockIDBFactory>(context(), &clock);
-
- const Origin origin = Origin::Create(GURL("http://localhost:81"));
-
- auto 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_TRUE(store_ptr->close_timer()->IsRunning());
- EXPECT_EQ(nullptr, store_ptr->pre_close_task_queue());
-
- // Reset the timer & stop the closing.
- factory->TestOpenBackingStore(origin, context()->data_path());
- EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
- factory->TestReleaseBackingStore(store_ptr, false);
- EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
- store_ptr->close_timer()->FireNow();
-
- // Backing store should be totally closed.
- EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
-
- store = factory->TestOpenBackingStore(origin, context()->data_path());
- store_ptr = store.get();
- store = nullptr;
- EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
-
- // Move the clock to start the next sweep.
- clock.Advance(IndexedDBFactoryImpl::kMaxEarliestGlobalSweepFromNow);
- factory->TestReleaseBackingStore(store_ptr, false);
-
- // Sweep should NOT be occurring.
- EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
- store_ptr->close_timer()->FireNow();
-
- // Backing store should be totally closed.
- EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
- loop.Quit();
- }));
- loop.Run();
-}
+ SetupContext();
-TEST_F(IndexedDBFactoryTest, BackingStoreRunPreCloseTasks) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitWithFeatures({kIDBTombstoneStatistics},
- {kIDBTombstoneDeletion});
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- base::SimpleTestClock clock;
- clock.SetNow(base::Time::Now());
-
- auto factory = base::MakeRefCounted<MockIDBFactory>(context(), &clock);
-
- const Origin origin = Origin::Create(GURL("http://localhost:81"));
-
- auto 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_TRUE(store_ptr->close_timer()->IsRunning());
- EXPECT_EQ(nullptr, store_ptr->pre_close_task_queue());
-
- // Reset the timer & stop the closing.
- factory->TestOpenBackingStore(origin, context()->data_path());
- EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
- factory->TestReleaseBackingStore(store_ptr, false);
- EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
- store_ptr->close_timer()->FireNow();
-
- // Backing store should be totally closed.
- EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
-
- store = factory->TestOpenBackingStore(origin, context()->data_path());
- store_ptr = store.get();
- store = nullptr;
- EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
-
- // Move the clock to start the next sweep.
- clock.Advance(IndexedDBFactoryImpl::kMaxEarliestGlobalSweepFromNow);
- factory->TestReleaseBackingStore(store_ptr, false);
-
- // Sweep should be occuring.
- EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
- store_ptr->close_timer()->FireNow();
- ASSERT_NE(nullptr, store_ptr->pre_close_task_queue());
- EXPECT_TRUE(store_ptr->pre_close_task_queue()->started());
-
- // Stop sweep by opening a connection.
- factory->TestOpenBackingStore(origin, context()->data_path());
- EXPECT_EQ(nullptr, store_ptr->pre_close_task_queue());
-
- // Move clock forward to trigger next sweep, but origin has longer
- // sweep minimum, so nothing happens.
- clock.Advance(IndexedDBFactoryImpl::kMaxEarliestGlobalSweepFromNow);
-
- factory->TestReleaseBackingStore(store_ptr, false);
- EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
- EXPECT_EQ(nullptr, store_ptr->pre_close_task_queue());
-
- // Reset, and move clock forward so the origin should allow a sweep.
- factory->TestOpenBackingStore(origin, context()->data_path());
- EXPECT_EQ(nullptr, store_ptr->pre_close_task_queue());
- clock.Advance(IndexedDBFactoryImpl::kMaxEarliestOriginSweepFromNow);
- factory->TestReleaseBackingStore(store_ptr, false);
-
- // Sweep should be occuring.
- EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
- store_ptr->close_timer()->FireNow();
- ASSERT_NE(nullptr, store_ptr->pre_close_task_queue());
- EXPECT_TRUE(store_ptr->pre_close_task_queue()->started());
-
- // Take back a ref ptr and ensure that the actual close
- // stops a running timer.
- store = store_ptr;
- factory->TestCloseBackingStore(store_ptr);
- loop.Quit();
- }));
- loop.Run();
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
+
+ IndexedDBOriginStateHandle origin_state_handle;
+ leveldb::Status s;
+
+ std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(origin, context()->data_path());
+ EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
+ origin_state_handle.Release();
+
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_TRUE(factory()->GetOriginFactory(origin)->IsClosing());
+
+ thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(2));
+
+ EXPECT_FALSE(factory()->GetOriginFactory(origin));
}
-TEST_F(IndexedDBFactoryTest, BackingStoreCloseImmediatelySwitch) {
+TEST_F(IndexedDBFactoryTestWithMockTime, PreCloseTasksStart) {
base::test::ScopedFeatureList feature_list;
- feature_list.InitWithFeatures({kIDBTombstoneStatistics},
- {kIDBTombstoneDeletion});
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- kIDBCloseImmediatelySwitch);
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- base::SimpleTestClock clock;
- clock.SetNow(base::Time::Now());
-
- auto factory = base::MakeRefCounted<MockIDBFactory>(context(), &clock);
-
- const Origin origin = Origin::Create(GURL("http://localhost:81"));
-
- auto 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));
- loop.Quit();
- }));
- loop.Run();
-}
+ feature_list.InitWithFeatures({kIDBTombstoneDeletion},
+ {kIDBTombstoneStatistics});
+ base::SimpleTestClock clock;
+ clock.SetNow(base::Time::Now());
+ SetupContextWithFactories(indexed_db::GetDefaultLevelDBFactory(), &clock);
-TEST_F(IndexedDBFactoryTest, MemoryBackingStoreLifetime) {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- auto factory = base::MakeRefCounted<MockIDBFactory>(context());
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
- const Origin origin1 = Origin::Create(GURL("http://localhost:81"));
- const Origin origin2 = Origin::Create(GURL("http://localhost:82"));
+ IndexedDBOriginStateHandle origin_state_handle;
+ leveldb::Status s;
+
+ // Open a connection & immediately release it to cause the closing sequence to
+ // start.
+ std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(origin, context()->data_path());
+ EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
+ origin_state_handle.Release();
+
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_TRUE(factory()->GetOriginFactory(origin)->IsClosing());
+
+ EXPECT_EQ(IndexedDBOriginState::ClosingState::kPreCloseGracePeriod,
+ factory()->GetOriginFactory(origin)->closing_stage());
+
+ thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(2));
+
+ // The factory should be closed, as the pre close tasks are delayed.
+ EXPECT_FALSE(factory()->GetOriginFactory(origin));
+
+ // Move the clock to run the tasks in the next close sequence.
+ clock.Advance(IndexedDBOriginState::kMaxEarliestGlobalSweepFromNow);
+
+ // Open a connection & immediately release it to cause the closing sequence to
+ // start again.
+ std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(origin, context()->data_path());
+ EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
+ origin_state_handle.Release();
+
+ // Manually execute the timer so that the PreCloseTaskList task doesn't also
+ // run.
+ factory()->GetOriginFactory(origin)->close_timer()->FireNow();
+
+ // The pre-close tasks should be running now.
+ ASSERT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_EQ(IndexedDBOriginState::ClosingState::kRunningPreCloseTasks,
+ factory()->GetOriginFactory(origin)->closing_stage());
+ ASSERT_TRUE(factory()->GetOriginFactory(origin)->pre_close_task_queue());
+ EXPECT_TRUE(
+ factory()->GetOriginFactory(origin)->pre_close_task_queue()->started());
+
+ // Stop sweep by opening a connection.
+ std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(origin, context()->data_path());
+ EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
+ EXPECT_FALSE(
+ OriginStateFromHandle(origin_state_handle)->pre_close_task_queue());
+ origin_state_handle.Release();
+
+ // Move clock forward to trigger next sweep, but origin has longer
+ // sweep minimum, so no tasks should execute.
+ clock.Advance(IndexedDBOriginState::kMaxEarliestGlobalSweepFromNow);
+
+ origin_state_handle.Release();
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_EQ(IndexedDBOriginState::ClosingState::kPreCloseGracePeriod,
+ factory()->GetOriginFactory(origin)->closing_stage());
+
+ // Manually execute the timer so that the PreCloseTaskList task doesn't also
+ // run.
+ factory()->GetOriginFactory(origin)->close_timer()->FireNow();
+
+ EXPECT_FALSE(factory()->GetOriginFactory(origin));
+
+ // Finally, move the clock forward so the origin should allow a sweep.
+ clock.Advance(IndexedDBOriginState::kMaxEarliestOriginSweepFromNow);
+ std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(origin, context()->data_path());
+ origin_state_handle.Release();
+ factory()->GetOriginFactory(origin)->close_timer()->FireNow();
+
+ ASSERT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_EQ(IndexedDBOriginState::ClosingState::kRunningPreCloseTasks,
+ factory()->GetOriginFactory(origin)->closing_stage());
+ ASSERT_TRUE(factory()->GetOriginFactory(origin)->pre_close_task_queue());
+ EXPECT_TRUE(
+ factory()->GetOriginFactory(origin)->pre_close_task_queue()->started());
+}
- auto mem_store1 =
- factory->TestOpenBackingStore(origin1, base::FilePath());
+TEST_F(IndexedDBFactoryTest, InMemoryFactoriesStay) {
+ SetupInMemoryContext();
+ ASSERT_TRUE(context()->IsInMemoryContext());
- auto mem_store2 =
- factory->TestOpenBackingStore(origin1, base::FilePath());
- EXPECT_EQ(mem_store1.get(), mem_store2.get());
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
- auto mem_store3 =
- factory->TestOpenBackingStore(origin2, base::FilePath());
+ IndexedDBOriginStateHandle origin_state_handle;
+ leveldb::Status s;
- factory->TestCloseBackingStore(mem_store1.get());
- factory->TestCloseBackingStore(mem_store3.get());
+ std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(origin, context()->data_path());
+ EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
+ EXPECT_TRUE(OriginStateFromHandle(origin_state_handle)
+ ->backing_store()
+ ->is_incognito());
+ origin_state_handle.Release();
- EXPECT_FALSE(mem_store1->HasOneRef());
- EXPECT_FALSE(mem_store2->HasOneRef());
- EXPECT_FALSE(mem_store3->HasOneRef());
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_FALSE(factory()->GetOriginFactory(origin)->IsClosing());
- factory = nullptr;
- EXPECT_FALSE(mem_store1->HasOneRef()); // mem_store1 and 2
- EXPECT_FALSE(mem_store2->HasOneRef()); // mem_store1 and 2
- EXPECT_TRUE(mem_store3->HasOneRef());
+ factory()->ForceClose(origin, false);
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
- mem_store2 = nullptr;
- EXPECT_TRUE(mem_store1->HasOneRef());
- loop.Quit();
- }));
- loop.Run();
+ factory()->ForceClose(origin, true);
+ EXPECT_FALSE(factory()->GetOriginFactory(origin));
}
-TEST_F(IndexedDBFactoryTest, MemoryBackingStoreDetectedAsIncognito) {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- auto factory = base::MakeRefCounted<MockIDBFactory>(context());
- const Origin origin1 = Origin::Create(GURL("http://localhost:81"));
- auto mem_store1 =
- factory->TestOpenBackingStore(origin1, base::FilePath());
- EXPECT_TRUE(mem_store1->is_incognito());
- loop.Quit();
- }));
- loop.Run();
-}
+TEST_F(IndexedDBFactoryTest, TooLongOrigin) {
+ SetupContext();
-TEST_F(IndexedDBFactoryTest, RejectLongOrigins) {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- base::FilePath temp_dir = context()->data_path().DirName();
- int limit = base::GetMaximumPathComponentLength(temp_dir);
- EXPECT_GT(limit, 0);
-
- auto factory = base::MakeRefCounted<MockIDBFactory>(context());
-
- std::string origin(limit + 1, 'x');
- Origin too_long_origin =
- Origin::Create(GURL("http://" + origin + ":81/"));
- auto diskStore1 = factory->TestOpenBackingStore(too_long_origin,
- context()->data_path());
- EXPECT_FALSE(diskStore1.get());
-
- Origin ok_origin = Origin::Create(GURL("http://someorigin.com:82/"));
- auto diskStore2 =
- factory->TestOpenBackingStore(ok_origin, context()->data_path());
- EXPECT_TRUE(diskStore2.get());
- // We need a manual close or Windows can't delete the temp
- // directory.
- factory->TestCloseBackingStore(diskStore2.get());
- loop.Quit();
- }));
+ base::FilePath temp_dir = context()->data_path().DirName();
+ int limit = base::GetMaximumPathComponentLength(temp_dir);
+ EXPECT_GT(limit, 0);
+
+ std::string origin(limit + 1, 'x');
+ Origin too_long_origin = Origin::Create(GURL("http://" + origin + ":81/"));
- loop.Run();
+ IndexedDBOriginStateHandle origin_state_handle;
+ leveldb::Status s;
+
+ std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(too_long_origin,
+ context()->data_path());
+ EXPECT_FALSE(origin_state_handle.IsHeld());
+ EXPECT_TRUE(s.IsIOError());
}
-class DiskFullFactory : public IndexedDBFactoryImpl {
- public:
- explicit DiskFullFactory(IndexedDBContextImpl* context)
- : IndexedDBFactoryImpl(context,
- indexed_db::GetDefaultLevelDBFactory(),
- base::DefaultClock::GetInstance()) {}
+TEST_F(IndexedDBFactoryTest, ContextDestructionClosesConnections) {
+ SetupContext();
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
- private:
- ~DiskFullFactory() override {}
-
- std::tuple<scoped_refptr<IndexedDBBackingStore>,
- leveldb::Status,
- IndexedDBDataLossInfo,
- bool /* disk_full */>
- OpenBackingStore(const url::Origin& origin,
- const base::FilePath& data_directory) override {
- return std::make_tuple(nullptr, leveldb::Status::IOError("Disk is full"),
- IndexedDBDataLossInfo(), true);
- }
+ auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>();
+ auto db_callbacks = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
- DISALLOW_COPY_AND_ASSIGN(DiskFullFactory);
-};
+ const int64_t transaction_id = 1;
+ auto create_transaction_callback =
+ base::BindOnce(&CreateAndBindTransactionPlaceholder);
+ auto connection = std::make_unique<IndexedDBPendingConnection>(
+ callbacks, db_callbacks, /*child_process_id=*/0, transaction_id,
+ IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+ std::move(create_transaction_callback));
+ factory()->Open(ASCIIToUTF16("db"), std::move(connection), origin,
+ context()->data_path());
+
+ // Now simulate shutdown, which should clear all factories.
+ factory()->ContextDestroyed();
+ EXPECT_TRUE(db_callbacks->forced_close_called());
+}
-class LookingForQuotaErrorMockCallbacks : public IndexedDBCallbacks {
- public:
- LookingForQuotaErrorMockCallbacks()
- : IndexedDBCallbacks(nullptr,
- url::Origin(),
- nullptr,
- base::SequencedTaskRunnerHandle::Get()),
- error_called_(false) {}
- void OnError(const IndexedDBDatabaseError& error) override {
- error_called_ = true;
- EXPECT_EQ(blink::kWebIDBDatabaseExceptionQuotaError, error.code());
- }
- bool error_called() const { return error_called_; }
+TEST_F(IndexedDBFactoryTest, ContextDestructionClosesHandles) {
+ SetupContext();
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
- private:
- ~LookingForQuotaErrorMockCallbacks() override {}
- bool error_called_;
+ IndexedDBOriginStateHandle origin_state_handle;
+ leveldb::Status s;
- DISALLOW_COPY_AND_ASSIGN(LookingForQuotaErrorMockCallbacks);
-};
+ std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(origin, context()->data_path());
+ EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
-TEST_F(IndexedDBFactoryTest, QuotaErrorOnDiskFull) {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- auto callbacks =
- base::MakeRefCounted<LookingForQuotaErrorMockCallbacks>();
- auto dummy_database_callbacks =
- base::MakeRefCounted<IndexedDBDatabaseCallbacks>(
- nullptr, nullptr, context()->TaskRunner());
- const Origin origin = Origin::Create(GURL("http://localhost:81"));
- auto factory = base::MakeRefCounted<DiskFullFactory>(context());
- const base::string16 name(ASCIIToUTF16("name"));
- auto create_transaction_callback =
- base::BindOnce(&CreateAndBindTransactionPlaceholder);
- auto connection = std::make_unique<IndexedDBPendingConnection>(
- callbacks, dummy_database_callbacks, /*child_process_id=*/0,
- /*transaction_id=*/2, /*version=*/1,
- std::move(create_transaction_callback));
- factory->Open(name, std::move(connection), origin,
- context()->data_path());
- EXPECT_TRUE(callbacks->error_called());
- loop.Quit();
- }));
- loop.Run();
+ // Now simulate shutdown, which should clear all factories.
+ factory()->ContextDestroyed();
+ EXPECT_FALSE(OriginStateFromHandle(origin_state_handle));
+ EXPECT_FALSE(factory()->GetOriginFactory(origin));
}
-TEST_F(IndexedDBFactoryTest, BackingStoreReleasedOnForcedClose) {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- auto factory = base::MakeRefCounted<MockIDBFactory>(context());
- auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>();
- auto db_callbacks =
- base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
-
- const Origin origin = Origin::Create(GURL("http://localhost:81"));
- const int64_t transaction_id = 1;
- auto create_transaction_callback =
- base::BindOnce(&CreateAndBindTransactionPlaceholder);
- auto connection = std::make_unique<IndexedDBPendingConnection>(
- callbacks, db_callbacks, /*child_process_id=*/0, transaction_id,
- IndexedDBDatabaseMetadata::DEFAULT_VERSION,
- std::move(create_transaction_callback));
- factory->Open(ASCIIToUTF16("db"), std::move(connection), origin,
- context()->data_path());
+TEST_F(IndexedDBFactoryTest, FactoryForceClose) {
+ SetupContext();
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
- EXPECT_TRUE(callbacks->connection());
+ IndexedDBOriginStateHandle origin_state_handle;
+ leveldb::Status s;
- EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
- EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+ std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+ factory()->GetOrOpenOriginFactory(origin, context()->data_path());
+ EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
- callbacks->connection()->ForceClose();
+ OriginStateFromHandle(origin_state_handle)->ForceClose();
+ origin_state_handle.Release();
- EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
- EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
- loop.Quit();
- }));
- loop.Run();
+ EXPECT_FALSE(factory()->GetOriginFactory(origin));
}
-TEST_F(IndexedDBFactoryTest, BackingStoreReleaseDelayedOnClose) {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- auto factory = base::MakeRefCounted<MockIDBFactory>(context());
- auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>();
- auto db_callbacks =
- base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
-
- const Origin origin = Origin::Create(GURL("http://localhost:81"));
- const int64_t transaction_id = 1;
- auto create_transaction_callback =
- base::BindOnce(&CreateAndBindTransactionPlaceholder);
- auto connection = std::make_unique<IndexedDBPendingConnection>(
- callbacks, db_callbacks, /*child_process_id=*/0, transaction_id,
- IndexedDBDatabaseMetadata::DEFAULT_VERSION,
- std::move(create_transaction_callback));
- factory->Open(ASCIIToUTF16("db"), std::move(connection), origin,
- context()->data_path());
+TEST_F(IndexedDBFactoryTest, ConnectionForceClose) {
+ SetupContext();
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
- EXPECT_TRUE(callbacks->connection());
- IndexedDBBackingStore* store =
- callbacks->connection()->database()->backing_store();
- EXPECT_FALSE(store->HasOneRef()); // Factory and database.
-
- EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
- callbacks->connection()->Close();
- EXPECT_TRUE(store->HasOneRef()); // Factory.
- EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
- EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
- EXPECT_TRUE(store->close_timer()->IsRunning());
-
- // Take a ref so it won't be destroyed out from under the test.
- scoped_refptr<IndexedDBBackingStore> store_ref = store;
-
- // Now simulate shutdown, which should stop the timer.
- factory->ContextDestroyed();
- EXPECT_TRUE(store->HasOneRef()); // Local.
- EXPECT_FALSE(store->close_timer()->IsRunning());
- EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
- EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
- loop.Quit();
- }));
- loop.Run();
-}
+ auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>();
+ auto db_callbacks = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
-TEST_F(IndexedDBFactoryTest, DeleteDatabaseClosesBackingStore) {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- auto factory = base::MakeRefCounted<MockIDBFactory>(context());
- auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>(
- /*expect_connection=*/false);
+ const int64_t transaction_id = 1;
+ auto create_transaction_callback =
+ base::BindOnce(&CreateAndBindTransactionPlaceholder);
+ auto connection = std::make_unique<IndexedDBPendingConnection>(
+ callbacks, db_callbacks, /*child_process_id=*/0, transaction_id,
+ IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+ std::move(create_transaction_callback));
+ factory()->Open(ASCIIToUTF16("db"), std::move(connection), origin,
+ context()->data_path());
- const Origin origin = Origin::Create(GURL("http://localhost:81"));
- EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
+ EXPECT_TRUE(callbacks->connection());
- factory->DeleteDatabase(ASCIIToUTF16("db"), callbacks, origin,
- context()->data_path(),
- /*force_close=*/false);
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_FALSE(factory()->GetOriginFactory(origin)->IsClosing());
- EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
- EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
+ callbacks->connection()->CloseAndReportForceClose();
- // Now simulate shutdown, which should stop the timer.
- factory->ContextDestroyed();
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_TRUE(factory()->GetOriginFactory(origin)->IsClosing());
- EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
- EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+ EXPECT_TRUE(db_callbacks->forced_close_called());
+}
- loop.Quit();
- }));
- loop.Run();
+TEST_F(IndexedDBFactoryTest, DatabaseForceCloseDuringUpgrade) {
+ SetupContext();
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
+
+ auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>();
+ auto db_callbacks = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
+
+ const int64_t transaction_id = 1;
+ auto create_transaction_callback =
+ base::BindOnce(&CreateAndBindTransactionPlaceholder);
+ auto connection = std::make_unique<IndexedDBPendingConnection>(
+ callbacks, db_callbacks, /*child_process_id=*/0, transaction_id,
+ IndexedDBDatabaseMetadata::NO_VERSION,
+ std::move(create_transaction_callback));
+
+ // Do the first half of the upgrade, and request the upgrade from renderer.
+ {
+ base::RunLoop loop;
+ callbacks->CallOnUpgradeNeeded(
+ base::BindLambdaForTesting([&]() { loop.Quit(); }));
+ factory()->Open(ASCIIToUTF16("db"), std::move(connection), origin,
+ context()->data_path());
+ loop.Run();
+ }
+
+ EXPECT_TRUE(callbacks->upgrade_called());
+ ASSERT_TRUE(callbacks->connection());
+ ASSERT_TRUE(callbacks->connection()->database());
+
+ callbacks->connection()->database()->ForceClose();
+
+ EXPECT_TRUE(db_callbacks->forced_close_called());
+ // Since there are no more references the factory should be closing.
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_TRUE(factory()->GetOriginFactory(origin)->IsClosing());
}
-TEST_F(IndexedDBFactoryTest, GetDatabaseNamesClosesBackingStore) {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- auto factory = base::MakeRefCounted<MockIDBFactory>(context());
- auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>(
- /*expect_connection=*/false);
+TEST_F(IndexedDBFactoryTest, ConnectionCloseDuringUpgrade) {
+ SetupContext();
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
+
+ auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>();
+ auto db_callbacks = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
- const Origin origin = Origin::Create(GURL("http://localhost:81"));
- EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
+ const int64_t transaction_id = 1;
+ auto create_transaction_callback =
+ base::BindOnce(&CreateAndBindTransactionPlaceholder);
+ auto connection = std::make_unique<IndexedDBPendingConnection>(
+ callbacks, db_callbacks, /*child_process_id=*/0, transaction_id,
+ IndexedDBDatabaseMetadata::NO_VERSION,
+ std::move(create_transaction_callback));
+
+ // Do the first half of the upgrade, and request the upgrade from renderer.
+ {
+ base::RunLoop loop;
+ callbacks->CallOnUpgradeNeeded(
+ base::BindLambdaForTesting([&]() { loop.Quit(); }));
+ factory()->Open(ASCIIToUTF16("db"), std::move(connection), origin,
+ context()->data_path());
+ loop.Run();
+ }
- factory->GetDatabaseNames(callbacks, origin, context()->data_path());
+ EXPECT_TRUE(callbacks->upgrade_called());
+ ASSERT_TRUE(callbacks->connection());
- EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
- EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
+ // Close the connection.
+ callbacks->connection()->Close();
- // Now simulate shutdown, which should stop the timer.
- factory->ContextDestroyed();
+ // Since there are no more references the factory should be closing.
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_TRUE(factory()->GetOriginFactory(origin)->IsClosing());
+}
- EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
- EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+TEST_F(IndexedDBFactoryTest, DatabaseForceCloseWithFullConnection) {
+ SetupContext();
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
- loop.Quit();
- }));
- loop.Run();
+ std::unique_ptr<IndexedDBConnection> connection;
+ scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks;
+ std::tie(connection, db_callbacks) =
+ CreateConnectionForDatatabase(origin, ASCIIToUTF16("db"));
+
+ // Force close the database.
+ connection->database()->ForceClose();
+
+ EXPECT_TRUE(db_callbacks->forced_close_called());
+ // Since there are no more references the factory should be closing.
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_TRUE(factory()->GetOriginFactory(origin)->IsClosing());
}
-TEST_F(IndexedDBFactoryTest, ForceCloseReleasesBackingStore) {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- auto factory = base::MakeRefCounted<MockIDBFactory>(context());
- auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>();
- auto db_callbacks =
- base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
-
- const Origin origin = Origin::Create(GURL("http://localhost:81"));
- const int64_t transaction_id = 1;
- auto create_transaction_callback =
- base::BindOnce(&CreateAndBindTransactionPlaceholder);
- auto connection = std::make_unique<IndexedDBPendingConnection>(
- callbacks, db_callbacks, /*child_process_id=*/0, transaction_id,
- IndexedDBDatabaseMetadata::DEFAULT_VERSION,
- std::move(create_transaction_callback));
- factory->Open(ASCIIToUTF16("db"), std::move(connection), origin,
- context()->data_path());
+TEST_F(IndexedDBFactoryTest, DeleteDatabase) {
+ SetupContext();
- EXPECT_TRUE(callbacks->connection());
- EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
- EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+ auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>(
+ /*expect_connection=*/false);
+
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
+
+ factory()->DeleteDatabase(ASCIIToUTF16("db"), callbacks, origin,
+ context()->data_path(),
+ /*force_close=*/false);
- callbacks->connection()->Close();
+ // Since there are no more references the factory should be closing.
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_TRUE(factory()->GetOriginFactory(origin)->IsClosing());
+}
- EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
- EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
+TEST_F(IndexedDBFactoryTest, DeleteDatabaseWithForceClose) {
+ SetupContext();
- factory->ForceClose(origin, /*delete_in_memory_store=*/false);
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
+ const base::string16 name = ASCIIToUTF16("db");
- EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
- EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+ std::unique_ptr<IndexedDBConnection> connection;
+ scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks;
+ std::tie(connection, db_callbacks) =
+ CreateConnectionForDatatabase(origin, name);
- // Ensure it is safe if the store is not open.
- factory->ForceClose(origin, /*delete_in_memory_store=*/false);
+ auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>(
+ /*expect_connection=*/false);
- loop.Quit();
- })),
- loop.Run();
+ factory()->DeleteDatabase(name, callbacks, origin, context()->data_path(),
+ /*force_close=*/true);
+
+ // Force close means the connection has been force closed, but the factory
+ // isn't force closed, and instead is going through it's shutdown sequence.
+ EXPECT_FALSE(connection->IsConnected());
+ EXPECT_TRUE(db_callbacks->forced_close_called());
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_TRUE(factory()->GetOriginFactory(origin)->IsClosing());
}
-class UpgradeNeededCallbacks : public MockIndexedDBCallbacks {
- public:
- UpgradeNeededCallbacks() {}
+TEST_F(IndexedDBFactoryTest, GetDatabaseNames) {
+ SetupContext();
- void OnSuccess(std::unique_ptr<IndexedDBConnection> connection,
- const IndexedDBDatabaseMetadata& metadata) override {
- EXPECT_TRUE(connection_.get());
- EXPECT_FALSE(connection.get());
- }
+ auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>(
+ /*expect_connection=*/false);
- void OnUpgradeNeeded(int64_t old_version,
- std::unique_ptr<IndexedDBConnection> connection,
- const IndexedDBDatabaseMetadata& metadata,
- const IndexedDBDataLossInfo& data_loss_info) override {
- connection_ = std::move(connection);
- }
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
- protected:
- ~UpgradeNeededCallbacks() override {}
+ factory()->GetDatabaseInfo(callbacks, origin, context()->data_path());
+
+ EXPECT_TRUE(callbacks->info_called());
+ // Since there are no more references the factory should be closing.
+ EXPECT_TRUE(factory()->GetOriginFactory(origin));
+ EXPECT_TRUE(factory()->GetOriginFactory(origin)->IsClosing());
+}
+
+class LookingForQuotaErrorMockCallbacks : public IndexedDBCallbacks {
+ public:
+ LookingForQuotaErrorMockCallbacks()
+ : IndexedDBCallbacks(nullptr,
+ url::Origin(),
+ nullptr,
+ base::SequencedTaskRunnerHandle::Get()),
+ error_called_(false) {}
+ void OnError(const IndexedDBDatabaseError& error) override {
+ error_called_ = true;
+ EXPECT_EQ(blink::kWebIDBDatabaseExceptionQuotaError, error.code());
+ }
+ bool error_called() const { return error_called_; }
private:
- DISALLOW_COPY_AND_ASSIGN(UpgradeNeededCallbacks);
+ ~LookingForQuotaErrorMockCallbacks() override {}
+ bool error_called_;
+
+ DISALLOW_COPY_AND_ASSIGN(LookingForQuotaErrorMockCallbacks);
};
+TEST_F(IndexedDBFactoryTest, QuotaErrorOnDiskFull) {
+ indexed_db::FakeLevelDBFactory fake_ldb_factory;
+ fake_ldb_factory.EnqueueNextOpenLevelDBStateResult(
+ nullptr, leveldb::Status::IOError("Disk is full."), true);
+ SetupContextWithFactories(&fake_ldb_factory,
+ base::DefaultClock::GetInstance());
+
+ auto callbacks = base::MakeRefCounted<LookingForQuotaErrorMockCallbacks>();
+ auto dummy_database_callbacks =
+ base::MakeRefCounted<IndexedDBDatabaseCallbacks>(nullptr, nullptr,
+ context()->TaskRunner());
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
+ const base::string16 name(ASCIIToUTF16("name"));
+ auto create_transaction_callback =
+ base::BindOnce(&CreateAndBindTransactionPlaceholder);
+ auto connection = std::make_unique<IndexedDBPendingConnection>(
+ callbacks, dummy_database_callbacks, /*child_process_id=*/0,
+ /*transaction_id=*/1, /*version=*/1,
+ std::move(create_transaction_callback));
+ factory()->Open(name, std::move(connection), origin, context()->data_path());
+ EXPECT_TRUE(callbacks->error_called());
+}
+
class ErrorCallbacks : public MockIndexedDBCallbacks {
public:
ErrorCallbacks() : MockIndexedDBCallbacks(false), saw_error_(false) {}
@@ -724,89 +732,63 @@ class ErrorCallbacks : public MockIndexedDBCallbacks {
DISALLOW_COPY_AND_ASSIGN(ErrorCallbacks);
};
-// Disabled due to flakiness: see https://crbug.com/947667.
-TEST_F(IndexedDBFactoryTest, DISABLED_DatabaseFailedOpen) {
+TEST_F(IndexedDBFactoryTest, DatabaseFailedOpen) {
+ SetupContext();
const Origin origin = Origin::Create(GURL("http://localhost:81"));
const base::string16 db_name(ASCIIToUTF16("db"));
const int64_t transaction_id = 1;
- // These objects are retained across posted tasks, so despite being used
- // exclusively on the IDB sequence.
+ auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>();
+ auto db_callbacks = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
+ auto failed_open_callbacks = base::MakeRefCounted<ErrorCallbacks>();
+ auto db_callbacks2 = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
- // Created and used on IDB sequence.
- scoped_refptr<MockIDBFactory> factory;
- scoped_refptr<UpgradeNeededCallbacks> upgrade_callbacks;
- scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks;
- scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks2;
- scoped_refptr<ErrorCallbacks> failed_open_callbacks;
+ // Open at version 2.
+ const int64_t db_version = 2;
+ auto create_transaction_callback =
+ base::BindOnce(&CreateAndBindTransactionPlaceholder);
+ auto connection = std::make_unique<IndexedDBPendingConnection>(
+ callbacks, db_callbacks,
+ /*child_process_id=*/0, transaction_id, db_version,
+ std::move(create_transaction_callback));
{
base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- factory = base::MakeRefCounted<MockIDBFactory>(context());
- upgrade_callbacks = base::MakeRefCounted<UpgradeNeededCallbacks>();
- db_callbacks = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
- failed_open_callbacks = base::MakeRefCounted<ErrorCallbacks>();
- db_callbacks2 =
- base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
- // Open at version 2.
- const int64_t db_version = 2;
- auto create_transaction_callback =
- base::BindOnce(&CreateAndBindTransactionPlaceholder);
- auto connection = std::make_unique<IndexedDBPendingConnection>(
- upgrade_callbacks, db_callbacks,
- /*child_process_id=*/0, transaction_id, db_version,
- std::move(create_transaction_callback));
- factory->Open(db_name, std::move(connection), origin,
- context()->data_path());
- EXPECT_TRUE(factory->IsDatabaseOpen(origin, db_name));
- loop.Quit();
- }));
+ callbacks->CallOnUpgradeNeeded(
+ base::BindLambdaForTesting([&]() { loop.Quit(); }));
+ factory()->Open(db_name, std::move(connection), origin,
+ context()->data_path());
loop.Run();
}
+ EXPECT_TRUE(callbacks->upgrade_called());
+ EXPECT_TRUE(factory()->IsDatabaseOpen(origin, db_name));
+ // Finish connecting, then close the connection.
{
base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- // Close the connection.
- {
- EXPECT_TRUE(upgrade_callbacks->connection());
- upgrade_callbacks->connection()->database()->Commit(
- upgrade_callbacks->connection()->GetTransaction(
- transaction_id));
- upgrade_callbacks->connection()->Close();
- EXPECT_FALSE(factory->IsDatabaseOpen(origin, db_name));
- }
-
- // Open at version < 2, which will fail; ensure factory doesn't
- // retain the database object.
- {
- const int64_t db_version = 1;
- auto create_transaction_callback =
- base::BindOnce(&CreateAndBindTransactionPlaceholder);
- auto connection = std::make_unique<IndexedDBPendingConnection>(
- failed_open_callbacks, db_callbacks2,
- /*child_process_id=*/0, transaction_id, db_version,
- std::move(create_transaction_callback));
- factory->Open(db_name, std::move(connection), origin,
- context()->data_path());
- EXPECT_TRUE(failed_open_callbacks->saw_error());
- EXPECT_FALSE(factory->IsDatabaseOpen(origin, db_name));
- }
-
- // Terminate all pending-close timers.
- factory->ForceClose(origin, /*delete_in_memory_store=*/false);
- loop.Quit();
-
- // These need to be deleted on the IDB task runner.
- upgrade_callbacks.reset();
- db_callbacks.reset();
- db_callbacks2.reset();
- failed_open_callbacks.reset();
- }));
+ callbacks->CallOnDBSuccess(
+ base::BindLambdaForTesting([&]() { loop.Quit(); }));
+ EXPECT_TRUE(callbacks->connection());
+ callbacks->connection()->database()->Commit(
+ callbacks->connection()->GetTransaction(transaction_id));
loop.Run();
+ callbacks->connection()->Close();
+ EXPECT_FALSE(factory()->IsDatabaseOpen(origin, db_name));
+ }
+
+ // Open at version < 2, which will fail.
+ {
+ const int64_t db_version = 1;
+ auto create_transaction_callback =
+ base::BindOnce(&CreateAndBindTransactionPlaceholder);
+ auto connection = std::make_unique<IndexedDBPendingConnection>(
+ failed_open_callbacks, db_callbacks2,
+ /*child_process_id=*/0, transaction_id, db_version,
+ std::move(create_transaction_callback));
+ factory()->Open(db_name, std::move(connection), origin,
+ context()->data_path());
+ EXPECT_TRUE(failed_open_callbacks->saw_error());
+ EXPECT_FALSE(factory()->IsDatabaseOpen(origin, db_name));
}
}
@@ -815,11 +797,7 @@ namespace {
class DataLossCallbacks final : public MockIndexedDBCallbacks {
public:
blink::mojom::IDBDataLoss data_loss() const { return data_loss_; }
- void OnSuccess(std::unique_ptr<IndexedDBConnection> connection,
- const IndexedDBDatabaseMetadata& metadata) override {
- if (!connection_)
- connection_ = std::move(connection);
- }
+
void OnError(const IndexedDBDatabaseError& error) final {
ADD_FAILURE() << "Unexpected IDB error: " << error.message();
}
@@ -827,8 +805,9 @@ class DataLossCallbacks final : public MockIndexedDBCallbacks {
std::unique_ptr<IndexedDBConnection> connection,
const IndexedDBDatabaseMetadata& metadata,
const IndexedDBDataLossInfo& data_loss) final {
- connection_ = std::move(connection);
data_loss_ = data_loss.status;
+ MockIndexedDBCallbacks::OnUpgradeNeeded(old_version, std::move(connection),
+ metadata, data_loss);
}
private:
@@ -837,67 +816,58 @@ class DataLossCallbacks final : public MockIndexedDBCallbacks {
};
TEST_F(IndexedDBFactoryTest, DataFormatVersion) {
+ SetupContext();
auto try_open = [this](const Origin& origin,
const IndexedDBDataFormatVersion& version) {
base::AutoReset<IndexedDBDataFormatVersion> override_version(
&IndexedDBDataFormatVersion::GetMutableCurrentForTesting(), version);
- // These objects are retained across posted tasks, so despite being used
- // exclusively on the IDB sequence.
-
- // Created and used on IDB sequence.
- scoped_refptr<MockIDBFactory> factory;
- scoped_refptr<DataLossCallbacks> callbacks;
-
const int64_t transaction_id = 1;
- blink::mojom::IDBDataLoss result;
+ auto callbacks = base::MakeRefCounted<DataLossCallbacks>();
+ auto db_callbacks = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
+ auto create_transaction_callback =
+ base::BindOnce(&CreateAndBindTransactionPlaceholder);
+ auto pending_connection = std::make_unique<IndexedDBPendingConnection>(
+ callbacks, db_callbacks, /*child_process_id=*/0, transaction_id,
+ /*version=*/1, std::move(create_transaction_callback));
{
base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- factory = base::MakeRefCounted<MockIDBFactory>(context());
- callbacks = base::MakeRefCounted<DataLossCallbacks>();
- auto db_callbacks =
- base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
- auto create_transaction_callback =
- base::BindOnce(&CreateAndBindTransactionPlaceholder);
- auto connection = std::make_unique<IndexedDBPendingConnection>(
- callbacks, db_callbacks, /*child_process_id=*/0, transaction_id,
- /*version=*/1, std::move(create_transaction_callback));
- factory->Open(ASCIIToUTF16("test_db"), std::move(connection),
- origin, context()->data_path());
- loop.Quit();
- }));
- loop.Run();
- }
- {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- auto* connection = callbacks->connection();
- EXPECT_TRUE(connection);
- connection->database()->Commit(
- connection->GetTransaction(transaction_id));
- connection->Close();
- factory->ForceClose(origin, /*delete_in_memory_store=*/false);
- result = callbacks->data_loss();
- loop.Quit();
- callbacks.reset();
- }));
- loop.Run();
- }
- {
- base::RunLoop loop;
- context()->TaskRunner()->PostTask(FROM_HERE,
- base::BindLambdaForTesting([&]() {
- callbacks.reset();
- factory.reset();
- loop.Quit();
- }));
+ bool upgraded = false;
+ // The database might already exist. Wait until either a success or an
+ // ugprade request.
+ callbacks->CallOnUpgradeNeeded(base::BindLambdaForTesting([&]() {
+ upgraded = true;
+ loop.Quit();
+ }));
+ callbacks->CallOnDBSuccess(
+ base::BindLambdaForTesting([&]() { loop.Quit(); }));
+
+ this->factory()->Open(ASCIIToUTF16("test_db"),
+ std::move(pending_connection), origin,
+ context()->data_path());
loop.Run();
+
+ // If an upgrade was requested, then commit the upgrade transaction.
+ if (upgraded) {
+ EXPECT_TRUE(callbacks->upgrade_called());
+ EXPECT_TRUE(callbacks->connection());
+ EXPECT_TRUE(callbacks->connection()->database());
+ // Finish the upgrade by committing the transaction.
+ auto* connection = callbacks->connection();
+ {
+ base::RunLoop inner_loop;
+ callbacks->CallOnDBSuccess(
+ base::BindLambdaForTesting([&]() { inner_loop.Quit(); }));
+ connection->database()->Commit(
+ connection->GetTransaction(transaction_id));
+ inner_loop.Run();
+ }
+ }
}
- return result;
+
+ factory()->ForceClose(origin, false);
+ return callbacks->data_loss();
};
static const struct {
diff --git a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
index df2a1198a04..2217816cd23 100644
--- a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
@@ -154,9 +154,9 @@ IndexedDBFakeBackingStore::FakeTransaction::FakeTransaction(
: IndexedDBBackingStore::Transaction(nullptr), result_(result) {}
void IndexedDBFakeBackingStore::FakeTransaction::Begin() {}
leveldb::Status IndexedDBFakeBackingStore::FakeTransaction::CommitPhaseOne(
- scoped_refptr<BlobWriteCallback> callback) {
- callback->Run(IndexedDBBackingStore::BlobWriteResult::SUCCESS_SYNC);
- return leveldb::Status::OK();
+ BlobWriteCallback callback) {
+ return std::move(callback).Run(
+ IndexedDBBackingStore::BlobWriteResult::SUCCESS_SYNC);
}
leveldb::Status IndexedDBFakeBackingStore::FakeTransaction::CommitPhaseTwo() {
return result_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
index 2239fecab2a..6a2ad294733 100644
--- a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
@@ -31,6 +31,8 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
IndexedDBFakeBackingStore();
IndexedDBFakeBackingStore(IndexedDBFactory* factory,
base::SequencedTaskRunner* task_runner);
+ ~IndexedDBFakeBackingStore() override;
+
leveldb::Status DeleteDatabase(const base::string16& name) override;
leveldb::Status PutRecord(IndexedDBBackingStore::Transaction* transaction,
@@ -112,7 +114,7 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
public:
explicit FakeTransaction(leveldb::Status phase_two_result);
void Begin() override;
- leveldb::Status CommitPhaseOne(scoped_refptr<BlobWriteCallback>) override;
+ leveldb::Status CommitPhaseOne(BlobWriteCallback) override;
leveldb::Status CommitPhaseTwo() override;
uint64_t GetTransactionSize() override;
void Rollback() override;
@@ -123,10 +125,6 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
DISALLOW_COPY_AND_ASSIGN(FakeTransaction);
};
- protected:
- friend class base::RefCounted<IndexedDBFakeBackingStore>;
- ~IndexedDBFakeBackingStore() override;
-
private:
DISALLOW_COPY_AND_ASSIGN(IndexedDBFakeBackingStore);
};
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 2c41c778a19..d280fa2f093 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -78,7 +78,6 @@ IndexedDBInternalsUI::IndexedDBInternalsUI(WebUI* web_ui)
source->AddResourcePath("indexeddb_internals.css",
IDR_INDEXED_DB_INTERNALS_CSS);
source->SetDefaultResource(IDR_INDEXED_DB_INTERNALS_HTML);
- source->UseGzip();
BrowserContext* browser_context =
web_ui->GetWebContents()->GetBrowserContext();
diff --git a/chromium/content/browser/indexed_db/indexed_db_origin_state.cc b/chromium/content/browser/indexed_db/indexed_db_origin_state.cc
new file mode 100644
index 00000000000..27ad7cfc54a
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_origin_state.cc
@@ -0,0 +1,341 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/indexed_db/indexed_db_origin_state.h"
+
+#include "base/bind.h"
+#include "base/feature_list.h"
+#include "base/rand_util.h"
+#include "base/stl_util.h"
+#include "content/browser/indexed_db/indexed_db_backing_store.h"
+#include "content/browser/indexed_db/indexed_db_class_factory.h"
+#include "content/browser/indexed_db/indexed_db_connection.h"
+#include "content/browser/indexed_db/indexed_db_database.h"
+#include "content/browser/indexed_db/indexed_db_factory_impl.h"
+#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
+#include "content/browser/indexed_db/indexed_db_leveldb_operations.h"
+#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
+#include "content/browser/indexed_db/indexed_db_tombstone_sweeper.h"
+#include "content/browser/indexed_db/indexed_db_transaction.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
+
+namespace content {
+namespace {
+// Time after the last connection to a database is closed and when we destroy
+// the backing store.
+const int64_t kBackingStoreGracePeriodSeconds = 2;
+// Total time we let pre-close tasks run.
+const int64_t kRunningPreCloseTasksMaxRunPeriodSeconds = 60;
+// The number of iterations for every 'round' of the tombstone sweeper.
+const int kTombstoneSweeperRoundIterations = 1000;
+// The maximum total iterations for the tombstone sweeper.
+const int kTombstoneSweeperMaxIterations = 10 * 1000 * 1000;
+
+constexpr const base::TimeDelta kMinEarliestOriginSweepFromNow =
+ base::TimeDelta::FromDays(1);
+static_assert(kMinEarliestOriginSweepFromNow <
+ IndexedDBOriginState::kMaxEarliestOriginSweepFromNow,
+ "Min < Max");
+
+constexpr const base::TimeDelta kMinEarliestGlobalSweepFromNow =
+ base::TimeDelta::FromMinutes(10);
+static_assert(kMinEarliestGlobalSweepFromNow <
+ IndexedDBOriginState::kMaxEarliestGlobalSweepFromNow,
+ "Min < Max");
+
+base::Time GenerateNextOriginSweepTime(base::Time now) {
+ uint64_t range =
+ IndexedDBOriginState::kMaxEarliestOriginSweepFromNow.InMilliseconds() -
+ kMinEarliestOriginSweepFromNow.InMilliseconds();
+ int64_t rand_millis = kMinEarliestOriginSweepFromNow.InMilliseconds() +
+ static_cast<int64_t>(base::RandGenerator(range));
+ return now + base::TimeDelta::FromMilliseconds(rand_millis);
+}
+
+base::Time GenerateNextGlobalSweepTime(base::Time now) {
+ uint64_t range =
+ IndexedDBOriginState::kMaxEarliestGlobalSweepFromNow.InMilliseconds() -
+ kMinEarliestGlobalSweepFromNow.InMilliseconds();
+ int64_t rand_millis = kMinEarliestGlobalSweepFromNow.InMilliseconds() +
+ static_cast<int64_t>(base::RandGenerator(range));
+ return now + base::TimeDelta::FromMilliseconds(rand_millis);
+}
+
+} // namespace
+
+const base::Feature kIDBTombstoneStatistics{"IDBTombstoneStatistics",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kIDBTombstoneDeletion{"IDBTombstoneDeletion",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+constexpr const base::TimeDelta
+ IndexedDBOriginState::kMaxEarliestGlobalSweepFromNow;
+constexpr const base::TimeDelta
+ IndexedDBOriginState::kMaxEarliestOriginSweepFromNow;
+
+IndexedDBOriginState::IndexedDBOriginState(
+ bool persist_for_incognito,
+ base::Clock* clock,
+ base::Time* earliest_global_sweep_time,
+ base::OnceClosure destruct_myself,
+ std::unique_ptr<IndexedDBBackingStore> backing_store)
+ : persist_for_incognito_(persist_for_incognito),
+ clock_(clock),
+ earliest_global_sweep_time_(earliest_global_sweep_time),
+ lock_manager_(kIndexedDBLockLevelCount),
+ backing_store_(std::move(backing_store)),
+ destruct_myself_(std::move(destruct_myself)) {
+ DCHECK(clock_);
+ DCHECK(earliest_global_sweep_time_);
+ if (*earliest_global_sweep_time_ == base::Time())
+ *earliest_global_sweep_time_ = GenerateNextGlobalSweepTime(clock_->Now());
+}
+
+IndexedDBOriginState::~IndexedDBOriginState() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void IndexedDBOriginState::AbortAllTransactions(bool compact) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // Because finishing all transactions could cause a database to be destructed
+ // (which would mutate the database_ map), save the keys beforehand and use
+ // those.
+ std::vector<base::string16> origins;
+ origins.reserve(databases_.size());
+ for (const auto& pair : databases_) {
+ origins.push_back(pair.first);
+ }
+
+ for (const base::string16& origin : origins) {
+ auto it = databases_.find(origin);
+ if (it == databases_.end())
+ continue;
+
+ // Calling FinishAllTransactions can destruct the IndexedDBConnection &
+ // modify the IndexedDBDatabase::connection() list. To prevent UAFs, start
+ // by taking a WeakPtr of all connections, and then iterate that list.
+ std::vector<base::WeakPtr<IndexedDBConnection>> weak_connections;
+ weak_connections.reserve(it->second->connections().size());
+ for (IndexedDBConnection* connection : it->second->connections())
+ weak_connections.push_back(connection->GetWeakPtr());
+
+ for (base::WeakPtr<IndexedDBConnection> connection : weak_connections) {
+ if (connection) {
+ connection->FinishAllTransactions(IndexedDBDatabaseError(
+ blink::kWebIDBDatabaseExceptionUnknownError,
+ "Aborting all transactions for the origin."));
+ }
+ }
+ }
+ if (compact)
+ backing_store_->Compact();
+}
+
+void IndexedDBOriginState::ForceClose() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // To avoid re-entry, the |db_destruction_weak_factory_| is invalidated so
+ // that of the deletions closures returned by CreateDatabaseDeleteClosure will
+ // no-op. This allows force closing all of the databases without having the
+ // map mutate. Afterwards the map is manually deleted.
+ IndexedDBOriginStateHandle handle = CreateHandle();
+ db_destruction_weak_factory_.InvalidateWeakPtrs();
+ for (const auto& pair : databases_) {
+ pair.second->ForceClose();
+ }
+ databases_.clear();
+ if (has_blobs_outstanding_) {
+ backing_store_->active_blob_registry()->ForceShutdown();
+ has_blobs_outstanding_ = false;
+ }
+ skip_closing_sequence_ = true;
+}
+
+void IndexedDBOriginState::ReportOutstandingBlobs(bool blobs_outstanding) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ has_blobs_outstanding_ = blobs_outstanding;
+ MaybeStartClosing();
+}
+
+void IndexedDBOriginState::StopPersistingForIncognito() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ persist_for_incognito_ = false;
+ MaybeStartClosing();
+}
+
+IndexedDBDatabase* IndexedDBOriginState::AddDatabase(
+ const base::string16& name,
+ std::unique_ptr<IndexedDBDatabase> database) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!base::ContainsKey(databases_, name));
+ return databases_.emplace(name, std::move(database)).first->second.get();
+}
+
+base::OnceClosure IndexedDBOriginState::CreateDatabaseDeleteClosure(
+ const base::string16& name) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return base::BindOnce(
+ [](base::WeakPtr<IndexedDBOriginState> factory,
+ const base::string16& name) {
+ if (!factory)
+ return;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(factory->sequence_checker_);
+ size_t delete_size = factory->databases_.erase(name);
+ DCHECK(delete_size) << "Database " << name << " did not exist.";
+ },
+ db_destruction_weak_factory_.GetWeakPtr(), name);
+}
+
+IndexedDBOriginStateHandle IndexedDBOriginState::CreateHandle() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ ++open_handles_;
+ if (closing_stage_ != ClosingState::kNotClosing) {
+ closing_stage_ = ClosingState::kNotClosing;
+ close_timer_.AbandonAndStop();
+ if (pre_close_task_queue_) {
+ pre_close_task_queue_->StopForNewConnection();
+ pre_close_task_queue_.reset();
+ }
+ }
+ return IndexedDBOriginStateHandle(weak_factory_.GetWeakPtr());
+}
+
+void IndexedDBOriginState::OnHandleDestruction() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_GT(open_handles_, 0ll);
+ --open_handles_;
+ MaybeStartClosing();
+}
+
+bool IndexedDBOriginState::CanCloseFactory() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_GE(open_handles_, 0);
+ return !has_blobs_outstanding_ && open_handles_ <= 0 &&
+ !persist_for_incognito_;
+}
+
+void IndexedDBOriginState::MaybeStartClosing() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!IsClosing() && CanCloseFactory())
+ StartClosing();
+}
+
+void IndexedDBOriginState::StartClosing() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(CanCloseFactory());
+ DCHECK(!IsClosing());
+
+ if (skip_closing_sequence_ ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ kIDBCloseImmediatelySwitch)) {
+ closing_stage_ = ClosingState::kClosed;
+ CloseAndDestruct();
+ return;
+ }
+
+ // Start a timer to close the backing store, unless something else opens it
+ // in the mean time.
+ DCHECK(!close_timer_.IsRunning());
+ closing_stage_ = ClosingState::kPreCloseGracePeriod;
+ close_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromSeconds(kBackingStoreGracePeriodSeconds),
+ base::BindOnce(
+ [](base::WeakPtr<IndexedDBOriginState> factory) {
+ if (!factory ||
+ factory->closing_stage_ != ClosingState::kPreCloseGracePeriod)
+ return;
+ factory->StartPreCloseTasks();
+ },
+ weak_factory_.GetWeakPtr()));
+}
+
+void IndexedDBOriginState::StartPreCloseTasks() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(closing_stage_ == ClosingState::kPreCloseGracePeriod);
+ closing_stage_ = ClosingState::kRunningPreCloseTasks;
+
+ // The callback will run on all early returns in this function.
+ base::ScopedClosureRunner maybe_close_backing_store_runner(base::BindOnce(
+ [](base::WeakPtr<IndexedDBOriginState> factory) {
+ if (!factory ||
+ factory->closing_stage_ != ClosingState::kRunningPreCloseTasks)
+ return;
+ factory->closing_stage_ = ClosingState::kClosed;
+ factory->pre_close_task_queue_.reset();
+ factory->CloseAndDestruct();
+ },
+ weak_factory_.GetWeakPtr()));
+
+ base::Time now = clock_->Now();
+
+ // Check that the last sweep hasn't run too recently.
+ if (*earliest_global_sweep_time_ > now)
+ return;
+
+ bool tombstone_stats_enabled =
+ base::FeatureList::IsEnabled(kIDBTombstoneStatistics);
+ bool tombstone_deletion_enabled =
+ base::FeatureList::IsEnabled(kIDBTombstoneDeletion);
+
+ // After this check, exactly one of the flags must be true.
+ if (tombstone_stats_enabled == tombstone_deletion_enabled)
+ return;
+
+ base::Time origin_earliest_sweep;
+ leveldb::Status s = indexed_db::GetEarliestSweepTime(backing_store_->db(),
+ &origin_earliest_sweep);
+ // TODO(dmurph): Log this or report to UMA.
+ if (!s.ok() && !s.IsNotFound())
+ return;
+
+ // This origin hasn't been swept too recently.
+ if (origin_earliest_sweep > now)
+ return;
+
+ // A sweep will happen now, so reset the sweep timers.
+ *earliest_global_sweep_time_ = GenerateNextGlobalSweepTime(now);
+ scoped_refptr<LevelDBTransaction> txn =
+ IndexedDBClassFactory::Get()->CreateLevelDBTransaction(
+ backing_store_->db());
+ indexed_db::SetEarliestSweepTime(txn.get(), GenerateNextOriginSweepTime(now));
+ s = txn->Commit();
+
+ // TODO(dmurph): Log this or report to UMA.
+ if (!s.ok())
+ return;
+
+ std::list<std::unique_ptr<IndexedDBPreCloseTaskQueue::PreCloseTask>> tasks;
+ IndexedDBTombstoneSweeper::Mode mode =
+ tombstone_stats_enabled ? IndexedDBTombstoneSweeper::Mode::STATISTICS
+ : IndexedDBTombstoneSweeper::Mode::DELETION;
+ tasks.push_back(std::make_unique<IndexedDBTombstoneSweeper>(
+ mode, kTombstoneSweeperRoundIterations, kTombstoneSweeperMaxIterations,
+ backing_store_->db()->db()));
+ // TODO(dmurph): Add compaction task that compacts all indexes if we have
+ // more than X deletions.
+
+ pre_close_task_queue_ = std::make_unique<IndexedDBPreCloseTaskQueue>(
+ std::move(tasks), maybe_close_backing_store_runner.Release(),
+ base::TimeDelta::FromSeconds(kRunningPreCloseTasksMaxRunPeriodSeconds),
+ std::make_unique<base::OneShotTimer>());
+ pre_close_task_queue_->Start(
+ base::BindOnce(&IndexedDBBackingStore::GetCompleteMetadata,
+ base::Unretained(backing_store_.get())));
+}
+
+void IndexedDBOriginState::CloseAndDestruct() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(CanCloseFactory());
+ DCHECK(closing_stage_ == ClosingState::kClosed);
+ close_timer_.AbandonAndStop();
+ pre_close_task_queue_.reset();
+
+ if (backing_store_ && backing_store_->IsBlobCleanupPending())
+ backing_store_->ForceRunBlobCleanup();
+
+ std::move(destruct_myself_).Run();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_origin_state.h b/chromium/content/browser/indexed_db/indexed_db_origin_state.h
new file mode 100644
index 00000000000..654cd935ebb
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_origin_state.h
@@ -0,0 +1,192 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_ORIGIN_STATE_H_
+#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_ORIGIN_STATE_H_
+
+#include <stdint.h>
+#include <memory>
+
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "base/sequence_checker.h"
+#include "base/strings/string16.h"
+#include "base/time/clock.h"
+#include "base/timer/timer.h"
+#include "content/browser/indexed_db/indexed_db_origin_state_handle.h"
+#include "content/browser/indexed_db/scopes/disjoint_range_lock_manager.h"
+#include "content/common/content_export.h"
+
+namespace base {
+struct Feature;
+}
+
+namespace content {
+class IndexedDBBackingStore;
+class IndexedDBDatabase;
+class IndexedDBFactoryImpl;
+class IndexedDBPreCloseTaskQueue;
+
+CONTENT_EXPORT extern const base::Feature kIDBTombstoneStatistics;
+CONTENT_EXPORT extern const base::Feature kIDBTombstoneDeletion;
+
+constexpr const char kIDBCloseImmediatelySwitch[] = "idb-close-immediately";
+
+// IndexedDBOriginState manages the per-origin IndexedDB state, and contains the
+// backing store for the origin.
+//
+// This class is expected to manage its own lifetime by using the
+// |destruct_myself_| closure, which is expected to destroy this object in the
+// parent IndexedDBFactoryImpl (and remove it from any collections, etc).
+// However, IndexedDBOriginState should still handle destruction without the use
+// of that closure when the storage partition is destructed.
+//
+// IndexedDBOriginState will keep itself alive while:
+// * There are handles referencing the factory,
+// * There are outstanding blob references to this database's blob files, and
+// * The factory is in an incognito profile.
+class CONTENT_EXPORT IndexedDBOriginState {
+ public:
+ using OriginDBMap =
+ base::flat_map<base::string16, std::unique_ptr<IndexedDBDatabase>>;
+
+ // Maximum time interval between runs of the IndexedDBSweeper. Sweeping only
+ // occurs after backing store close.
+ // Visible for testing.
+ static constexpr const base::TimeDelta kMaxEarliestGlobalSweepFromNow =
+ base::TimeDelta::FromHours(2);
+ // Maximum time interval between runs of the IndexedDBSweeper for a given
+ // origin. Sweeping only occurs after backing store close.
+ // Visible for testing.
+ static constexpr const base::TimeDelta kMaxEarliestOriginSweepFromNow =
+ base::TimeDelta::FromDays(7);
+
+ enum class ClosingState {
+ // IndexedDBOriginState isn't closing.
+ kNotClosing,
+ // IndexedDBOriginState is pausing for kBackingStoreGracePeriodSeconds
+ // to
+ // allow new references to open before closing the backing store.
+ kPreCloseGracePeriod,
+ // The |pre_close_task_queue| is running any pre-close tasks.
+ kRunningPreCloseTasks,
+ kClosed,
+ };
+
+ // Calling |destruct_myself| should destruct this object.
+ // |earliest_global_sweep_time| is expected to outlive this object.
+ IndexedDBOriginState(bool persist_for_incognito,
+ base::Clock* clock,
+ base::Time* earliest_global_sweep_time,
+ base::OnceClosure destruct_myself,
+ std::unique_ptr<IndexedDBBackingStore> backing_store);
+ ~IndexedDBOriginState();
+
+ void AbortAllTransactions(bool compact);
+
+ void ForceClose();
+
+ bool IsClosing() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return closing_stage_ != ClosingState::kNotClosing;
+ }
+
+ ClosingState closing_stage() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return closing_stage_;
+ }
+
+ void ReportOutstandingBlobs(bool blobs_outstanding);
+
+ void StopPersistingForIncognito();
+
+ IndexedDBBackingStore* backing_store() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return backing_store_.get();
+ }
+ const OriginDBMap& databases() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return databases_;
+ }
+ DisjointRangeLockManager* lock_manager() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return &lock_manager_;
+ }
+ IndexedDBPreCloseTaskQueue* pre_close_task_queue() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return pre_close_task_queue_.get();
+ }
+
+ base::OneShotTimer* close_timer() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return &close_timer_;
+ }
+
+ private:
+ friend IndexedDBFactoryImpl;
+ friend IndexedDBOriginStateHandle;
+
+ IndexedDBDatabase* AddDatabase(const base::string16& name,
+ std::unique_ptr<IndexedDBDatabase> database);
+
+ // Returns a closure that deletes the database object.
+ base::OnceClosure CreateDatabaseDeleteClosure(const base::string16& name);
+
+ // Returns a new handle to this factory. If this object was in its closing
+ // sequence, then that sequence will be halted by this call.
+ IndexedDBOriginStateHandle CreateHandle() WARN_UNUSED_RESULT;
+
+ void OnHandleDestruction();
+
+ // Returns true if this factory can be closed (no references, no blobs, and
+ // not persisting for incognito).
+ bool CanCloseFactory();
+
+ void MaybeStartClosing();
+ void StartClosing();
+ void StartPreCloseTasks();
+
+ void CloseAndDestruct();
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ // True if this factory should be remain alive due to the storage partition
+ // being for incognito mode, and our backing store being in-memory. This is
+ // used as closing criteria for this object, see CanCloseFactory.
+ bool persist_for_incognito_;
+ // True if there are blobs referencing this backing store that are still
+ // alive. This is used as closing criteria for this object, see
+ // CanCloseFactory.
+ bool has_blobs_outstanding_ = false;
+ bool skip_closing_sequence_ = false;
+ base::Clock* clock_;
+ // This is safe because it is owned by IndexedDBFactoryImpl, which owns this
+ // object.
+ base::Time* earliest_global_sweep_time_;
+ ClosingState closing_stage_ = ClosingState::kNotClosing;
+ base::OneShotTimer close_timer_;
+ DisjointRangeLockManager lock_manager_;
+ const std::unique_ptr<IndexedDBBackingStore> backing_store_;
+
+ OriginDBMap databases_;
+ // This is the refcount for the number of IndexedDBOriginStateHandle's given
+ // out for this factory using OpenReference. This is used as closing
+ // criteria for this object, see CanCloseFactory.
+ int64_t open_handles_ = 0;
+
+ std::unique_ptr<IndexedDBPreCloseTaskQueue> pre_close_task_queue_;
+
+ base::OnceClosure destruct_myself_;
+
+ // Weak pointers from this factory are used to bind database deletion in the
+ // ReleaseDatabaseClosure function. This allows those weak pointers to be
+ // invalidated during force close & shutdown to prevent re-entry.
+ base::WeakPtrFactory<IndexedDBOriginState> db_destruction_weak_factory_{this};
+ base::WeakPtrFactory<IndexedDBOriginState> weak_factory_{this};
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBOriginState);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_ORIGIN_STATE_H_
diff --git a/chromium/content/browser/indexed_db/indexed_db_origin_state_handle.cc b/chromium/content/browser/indexed_db/indexed_db_origin_state_handle.cc
new file mode 100644
index 00000000000..a1e502c8240
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_origin_state_handle.cc
@@ -0,0 +1,36 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/indexed_db/indexed_db_origin_state_handle.h"
+
+#include "content/browser/indexed_db/indexed_db_origin_state.h"
+
+namespace content {
+
+IndexedDBOriginStateHandle::IndexedDBOriginStateHandle() = default;
+IndexedDBOriginStateHandle::IndexedDBOriginStateHandle(
+ base::WeakPtr<IndexedDBOriginState> origin_state)
+ : origin_state_(origin_state) {}
+IndexedDBOriginStateHandle::IndexedDBOriginStateHandle(
+ IndexedDBOriginStateHandle&&) = default;
+IndexedDBOriginStateHandle& IndexedDBOriginStateHandle::operator=(
+ IndexedDBOriginStateHandle&&) = default;
+
+IndexedDBOriginStateHandle::~IndexedDBOriginStateHandle() {
+ if (origin_state_)
+ origin_state_->OnHandleDestruction();
+}
+
+void IndexedDBOriginStateHandle::Release() {
+ if (origin_state_) {
+ origin_state_->OnHandleDestruction();
+ origin_state_.reset();
+ }
+}
+
+bool IndexedDBOriginStateHandle::IsHeld() const {
+ return !!origin_state_;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_origin_state_handle.h b/chromium/content/browser/indexed_db/indexed_db_origin_state_handle.h
new file mode 100644
index 00000000000..bfa23262533
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_origin_state_handle.h
@@ -0,0 +1,53 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_ORIGIN_STATE_HANDLE_H_
+#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_ORIGIN_STATE_HANDLE_H_
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+
+namespace content {
+namespace indexed_db_backing_store_unittest {
+class IndexedDBBackingStoreTest;
+}
+class IndexedDBOriginState;
+
+// This handle tells the IndexedDBOriginState that there is still something
+// using the origin, and the IndexedDBOriginState won't close until all
+// handles are destroyed. Destroying this handle can cause the origin state to
+// synchronously destruct, which modifies the |factories_per_origin_| map in
+// IndexedDBFactoryImpl.
+class CONTENT_EXPORT IndexedDBOriginStateHandle {
+ public:
+ IndexedDBOriginStateHandle();
+ explicit IndexedDBOriginStateHandle(
+ base::WeakPtr<IndexedDBOriginState> origin_state);
+ IndexedDBOriginStateHandle(IndexedDBOriginStateHandle&&);
+ IndexedDBOriginStateHandle& operator=(IndexedDBOriginStateHandle&&);
+ ~IndexedDBOriginStateHandle();
+
+ bool IsHeld() const;
+
+ void Release();
+
+ protected:
+ friend class IndexedDBFactoryImpl;
+ friend class IndexedDBFactoryTest;
+ friend class indexed_db_backing_store_unittest::IndexedDBBackingStoreTest;
+
+ // Returns null if the factory was destroyed, which should only happen on
+ // context destruction.
+ IndexedDBOriginState* origin_state() { return origin_state_.get(); }
+
+ private:
+ base::WeakPtr<IndexedDBOriginState> origin_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBOriginStateHandle);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_ORIGIN_STATE_HANDLE_H_
diff --git a/chromium/content/browser/indexed_db/indexed_db_pending_connection.h b/chromium/content/browser/indexed_db/indexed_db_pending_connection.h
index 5d1b8946d1a..fd61559c4d1 100644
--- a/chromium/content/browser/indexed_db/indexed_db_pending_connection.h
+++ b/chromium/content/browser/indexed_db/indexed_db_pending_connection.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_data_loss_info.h"
#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
@@ -37,6 +38,7 @@ struct CONTENT_EXPORT IndexedDBPendingConnection {
IndexedDBDataLossInfo data_loss_info;
base::OnceCallback<void(base::WeakPtr<IndexedDBTransaction>)>
create_transaction_callback;
+ base::WeakPtr<IndexedDBTransaction> transaction;
};
} // namespace content
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 988a941e596..59ec133a7c6 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
@@ -26,7 +26,7 @@ namespace content {
// Holds a queue of PreCloseTask's to be run after an IndexedDBBackingStore no
// longer has any connections.
//
-// There is a special IndexedDBMetadata fetcher task that runs beofre all the
+// There is a special IndexedDBMetadata fetcher task that runs before all the
// other tasks, and whose output is passed to each task before they start.
//
// Owned by IndexedDBBackingStore.
diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
index be0d471ce50..0b44567ba05 100644
--- a/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
@@ -16,6 +16,7 @@
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/default_clock.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_quota_client.h"
#include "content/browser/indexed_db/leveldb/leveldb_env.h"
@@ -58,7 +59,8 @@ class IndexedDBQuotaClientTest : public testing::Test {
idb_context_ = new IndexedDBContextImpl(
browser_context_->GetPath(),
browser_context_->GetSpecialStoragePolicy(), quota_manager->proxy(),
- indexed_db::GetDefaultLevelDBFactory());
+ indexed_db::GetDefaultLevelDBFactory(),
+ base::DefaultClock::GetInstance());
base::RunLoop().RunUntilIdle();
setup_temp_dir();
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction.cc b/chromium/content/browser/indexed_db/indexed_db_transaction.cc
index 9e010f67d33..4e083f08b81 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction.cc
@@ -107,6 +107,7 @@ IndexedDBTransaction::AbortOperation IndexedDBTransaction::TaskStack::pop() {
IndexedDBTransaction::IndexedDBTransaction(
int64_t id,
IndexedDBConnection* connection,
+ ErrorCallback error_callback,
const std::set<int64_t>& object_store_ids,
blink::mojom::IDBTransactionMode mode,
IndexedDBBackingStore::Transaction* backing_store_transaction)
@@ -114,6 +115,7 @@ IndexedDBTransaction::IndexedDBTransaction(
object_store_ids_(object_store_ids),
mode_(mode),
connection_(connection->GetWeakPtr()),
+ error_callback_(std::move(error_callback)),
transaction_(backing_store_transaction),
ptr_factory_(this) {
IDB_ASYNC_TRACE_BEGIN("IndexedDBTransaction::lifetime", this);
@@ -193,7 +195,7 @@ void IndexedDBTransaction::ForcePendingCommit() {
} else {
leveldb::Status result = Commit();
if (!result.ok())
- database_->ReportError(result);
+ error_callback_.Run(result, "Error force committing.");
}
}
@@ -243,18 +245,24 @@ void IndexedDBTransaction::Abort(const IndexedDBDatabaseError& error) {
// Transactions must also be marked as completed before the
// front-end is notified, as the transaction completion unblocks
// operations like closing connections.
- locks_.clear();
+ locks_receiver_.locks.clear();
if (callbacks_.get())
callbacks_->OnAbort(*this, error);
- database_->TransactionFinished(mode_, false);
+ // |TransactionFinished| can delete the database, which owns the connection,
+ // which owns this transaction. Grab a weak pointer to the connection so we
+ // can test it later.
+ base::WeakPtr<IndexedDBConnection> connection = connection_;
+
+ if (database_)
+ database_->TransactionFinished(mode_, false);
// RemoveTransaction will delete |this|.
// Note: During force-close situations, the connection can be destroyed during
// the |IndexedDBDatabase::TransactionFinished| call
- if (connection_)
- connection_->RemoveTransaction(id_);
+ if (connection)
+ connection->RemoveTransaction(id_);
}
bool IndexedDBTransaction::IsTaskQueueEmpty() const {
@@ -273,11 +281,10 @@ void IndexedDBTransaction::UnregisterOpenCursor(IndexedDBCursor* cursor) {
open_cursors_.erase(cursor);
}
-void IndexedDBTransaction::Start(std::vector<ScopeLock> locks) {
- // TransactionCoordinator has started this transaction.
+void IndexedDBTransaction::Start() {
DCHECK_EQ(CREATED, state_);
state_ = STARTED;
- locks_ = std::move(locks);
+ DCHECK(!locks_receiver_.locks.empty());
diagnostics_.start_time = base::Time::Now();
if (!used_) {
@@ -300,25 +307,6 @@ void IndexedDBTransaction::EnsureBackingStoreTransactionBegun() {
}
}
-class BlobWriteCallbackImpl : public IndexedDBBackingStore::BlobWriteCallback {
- public:
- explicit BlobWriteCallbackImpl(
- base::WeakPtr<IndexedDBTransaction> transaction)
- : transaction_(std::move(transaction)) {}
-
- leveldb::Status Run(IndexedDBBackingStore::BlobWriteResult result) override {
- if (!transaction_)
- return leveldb::Status::OK();
- return transaction_->BlobWriteComplete(result);
- }
-
- protected:
- ~BlobWriteCallbackImpl() override {}
-
- private:
- base::WeakPtr<IndexedDBTransaction> transaction_;
-};
-
leveldb::Status IndexedDBTransaction::BlobWriteComplete(
IndexedDBBackingStore::BlobWriteResult result) {
IDB_TRACE("IndexedDBTransaction::BlobWriteComplete");
@@ -335,18 +323,18 @@ leveldb::Status IndexedDBTransaction::BlobWriteComplete(
return leveldb::Status::OK();
case IndexedDBBackingStore::BlobWriteResult::SUCCESS_ASYNC:
case IndexedDBBackingStore::BlobWriteResult::SUCCESS_SYNC: {
- // Save the database as |this| can be destroyed in the next line. We also
- // make
- // sure to handle the error if we're not being called synchronously.
- scoped_refptr<IndexedDBDatabase> database = database_;
+ // Save the callback as|this| can be destroyed in the next line.
+ auto callback_copy = error_callback_;
s = CommitPhaseTwo();
if (!s.ok() &&
- result == IndexedDBBackingStore::BlobWriteResult::SUCCESS_ASYNC)
- database->ReportError(s);
- break;
+ result == IndexedDBBackingStore::BlobWriteResult::SUCCESS_ASYNC) {
+ callback_copy.Run(
+ s, "Unable to finish transaction commit after writing blobs.");
+ }
+ return s;
}
}
- return s;
+ NOTREACHED();
}
leveldb::Status IndexedDBTransaction::Commit() {
@@ -391,11 +379,16 @@ leveldb::Status IndexedDBTransaction::Commit() {
if (!used_) {
s = CommitPhaseTwo();
} else {
- scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback(
- new BlobWriteCallbackImpl(ptr_factory_.GetWeakPtr()));
// CommitPhaseOne will call the callback synchronously if there are no blobs
// to write.
- s = transaction_->CommitPhaseOne(callback);
+ s = transaction_->CommitPhaseOne(base::BindOnce(
+ [](base::WeakPtr<IndexedDBTransaction> transaction,
+ IndexedDBBackingStore::BlobWriteResult result) {
+ if (!transaction)
+ return leveldb::Status::OK();
+ return transaction->BlobWriteComplete(result);
+ },
+ ptr_factory_.GetWeakPtr()));
}
return s;
@@ -457,7 +450,7 @@ leveldb::Status IndexedDBTransaction::CommitPhaseTwo() {
// Transactions must also be marked as completed before the
// front-end is notified, as the transaction completion unblocks
// operations like closing connections.
- locks_.clear();
+ locks_receiver_.locks.clear();
if (committed) {
abort_task_stack_.clear();
@@ -465,7 +458,8 @@ leveldb::Status IndexedDBTransaction::CommitPhaseTwo() {
// SendObservations must be called before OnComplete to ensure consistency
// of callbacks at renderer.
if (!connection_changes_map_.empty()) {
- database_->SendObservations(std::move(connection_changes_map_));
+ if (database_)
+ database_->SendObservations(std::move(connection_changes_map_));
connection_changes_map_.clear();
}
{
@@ -477,7 +471,8 @@ leveldb::Status IndexedDBTransaction::CommitPhaseTwo() {
if (!pending_observers_.empty() && connection_)
connection_->ActivatePendingObservers(std::move(pending_observers_));
- database_->TransactionFinished(mode_, true);
+ if (database_)
+ database_->TransactionFinished(mode_, true);
// RemoveTransaction will delete |this|.
connection_->RemoveTransaction(id_);
return s;
@@ -496,7 +491,8 @@ leveldb::Status IndexedDBTransaction::CommitPhaseTwo() {
"Internal error committing transaction.");
}
callbacks_->OnAbort(*this, error);
- database_->TransactionFinished(mode_, false);
+ if (database_)
+ database_->TransactionFinished(mode_, false);
// RemoveTransaction will delete |this|.
connection_->RemoveTransaction(id_);
}
@@ -531,7 +527,7 @@ void IndexedDBTransaction::ProcessTaskQueue() {
}
if (!result.ok()) {
processing_event_queue_ = false;
- database_->ReportError(result);
+ error_callback_.Run(result, "Error executing transaction tasks.");
return;
}
@@ -547,7 +543,7 @@ void IndexedDBTransaction::ProcessTaskQueue() {
// This can delete |this|.
leveldb::Status result = Commit();
if (!result.ok())
- database_->ReportError(result);
+ error_callback_.Run(result, "ERror committing the transaction.");
return;
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction.h b/chromium/content/browser/indexed_db/indexed_db_transaction.h
index b01ee8cae30..90bafc468a7 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction.h
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction.h
@@ -29,7 +29,6 @@
namespace content {
-class BlobWriteCallbackImpl;
class IndexedDBCursor;
class IndexedDBDatabaseCallbacks;
@@ -50,6 +49,10 @@ class CONTENT_EXPORT IndexedDBTransaction {
public:
using Operation = base::OnceCallback<leveldb::Status(IndexedDBTransaction*)>;
using AbortOperation = base::OnceClosure;
+ // Used to report irrecoverable backend errors. The second argument is
+ // optional.
+ using ErrorCallback =
+ base::RepeatingCallback<void(leveldb::Status, const char*)>;
enum State {
CREATED, // Created, but not yet started by coordinator.
@@ -71,8 +74,8 @@ class CONTENT_EXPORT IndexedDBTransaction {
// This object is destroyed by this method.
void Abort(const IndexedDBDatabaseError& error);
- // Called by the transaction coordinator when this transaction is unblocked.
- void Start(std::vector<ScopeLock> locks);
+ // Called by the scopes lock manager when this transaction is unblocked.
+ void Start();
blink::mojom::IDBTransactionMode mode() const { return mode_; }
const std::set<int64_t>& scope() const { return object_store_ids_; }
@@ -109,7 +112,7 @@ class CONTENT_EXPORT IndexedDBTransaction {
}
int64_t id() const { return id_; }
- IndexedDBDatabase* database() const { return database_.get(); }
+ base::WeakPtr<IndexedDBDatabase> database() const { return database_; }
IndexedDBDatabaseCallbacks* callbacks() const { return callbacks_.get(); }
IndexedDBConnection* connection() const { return connection_.get(); }
bool is_commit_pending() const { return is_commit_pending_; }
@@ -139,12 +142,15 @@ class CONTENT_EXPORT IndexedDBTransaction {
return ptr_factory_.GetWeakPtr();
}
+ ScopesLocksHolder* locks_receiver() { return &locks_receiver_; }
+
protected:
// Test classes may derive, but most creation should be done via
// IndexedDBClassFactory.
IndexedDBTransaction(
int64_t id,
IndexedDBConnection* connection,
+ ErrorCallback error_callback,
const std::set<int64_t>& object_store_ids,
blink::mojom::IDBTransactionMode mode,
IndexedDBBackingStore::Transaction* backing_store_transaction);
@@ -153,7 +159,6 @@ class CONTENT_EXPORT IndexedDBTransaction {
virtual base::TimeDelta GetInactivityTimeout() const;
private:
- friend class BlobWriteCallbackImpl;
friend class IndexedDBClassFactory;
friend class IndexedDBConnection;
friend class base::RefCounted<IndexedDBTransaction>;
@@ -202,13 +207,14 @@ class CONTENT_EXPORT IndexedDBTransaction {
bool used_ = false;
State state_ = CREATED;
- std::vector<ScopeLock> locks_;
+ ScopesLocksHolder locks_receiver_;
bool is_commit_pending_ = false;
// We are owned by the connection object, but during force closes sometimes
// there are issues if there is a pending OpenRequest. So use a WeakPtr.
base::WeakPtr<IndexedDBConnection> connection_;
scoped_refptr<IndexedDBDatabaseCallbacks> callbacks_;
- scoped_refptr<IndexedDBDatabase> database_;
+ base::WeakPtr<IndexedDBDatabase> database_;
+ ErrorCallback error_callback_;
// Observers in pending queue do not listen to changes until activated.
std::vector<std::unique_ptr<IndexedDBObserver>> pending_observers_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
index d277a49cbb4..3621a19fb05 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
@@ -12,9 +12,11 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
#include "content/browser/indexed_db/fake_indexed_db_metadata_coding.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
+#include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/indexed_db_metadata_coding.h"
@@ -47,24 +49,29 @@ class AbortObserver {
class IndexedDBTransactionTest : public testing::Test {
public:
IndexedDBTransactionTest()
- : factory_(new MockIndexedDBFactory()),
- lock_manager_(kIndexedDBLockLevelCount) {
- backing_store_ = new IndexedDBFakeBackingStore();
- CreateDB();
- }
+ : thread_bundle_(std::make_unique<TestBrowserThreadBundle>()),
+ backing_store_(new IndexedDBFakeBackingStore()),
+ factory_(new MockIndexedDBFactory()),
+ lock_manager_(kIndexedDBLockLevelCount) {}
- void CreateDB() {
+ void SetUp() override {
// DB is created here instead of the constructor to workaround a
// "peculiarity of C++". More info at
// https://github.com/google/googletest/blob/master/googletest/docs/FAQ.md#my-compiler-complains-that-a-constructor-or-destructor-cannot-return-a-value-whats-going-on
leveldb::Status s;
std::tie(db_, s) = IndexedDBDatabase::Create(
base::ASCIIToUTF16("db"), backing_store_.get(), factory_.get(),
+ GetErrorCallback(), base::BindLambdaForTesting([&]() { db_.reset(); }),
std::make_unique<FakeIndexedDBMetadataCoding>(),
IndexedDBDatabase::Identifier(), &lock_manager_);
ASSERT_TRUE(s.ok());
}
+ IndexedDBTransaction::ErrorCallback GetErrorCallback() {
+ return base::BindLambdaForTesting(
+ [&](leveldb::Status, const char*) { error_called_ = true; });
+ }
+
void RunPostedTasks() { base::RunLoop().RunUntilIdle(); }
leveldb::Status DummyOperation(leveldb::Status result,
IndexedDBTransaction* transaction) {
@@ -77,13 +84,23 @@ class IndexedDBTransactionTest : public testing::Test {
return leveldb::Status::OK();
}
+ std::unique_ptr<IndexedDBConnection> CreateConnection(int process_id) {
+ return std::unique_ptr<IndexedDBConnection>(
+ std::make_unique<IndexedDBConnection>(
+ kFakeProcessId, IndexedDBOriginStateHandle(), db_->AsWeakPtr(),
+ base::DoNothing(), base::DoNothing(), GetErrorCallback(),
+ new MockIndexedDBDatabaseCallbacks()));
+ }
+
protected:
- scoped_refptr<IndexedDBFakeBackingStore> backing_store_;
- scoped_refptr<IndexedDBDatabase> db_;
- scoped_refptr<MockIndexedDBFactory> factory_;
+ std::unique_ptr<TestBrowserThreadBundle> thread_bundle_;
+ std::unique_ptr<IndexedDBFakeBackingStore> backing_store_;
+ std::unique_ptr<IndexedDBDatabase> db_;
+ std::unique_ptr<MockIndexedDBFactory> factory_;
+
+ bool error_called_ = false;
private:
- TestBrowserThreadBundle thread_bundle_;
DisjointRangeLockManager lock_manager_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBTransactionTest);
@@ -94,6 +111,7 @@ class IndexedDBTransactionTestMode
public testing::WithParamInterface<blink::mojom::IDBTransactionMode> {
public:
IndexedDBTransactionTestMode() {}
+
private:
DISALLOW_COPY_AND_ASSIGN(IndexedDBTransactionTestMode);
};
@@ -102,12 +120,11 @@ TEST_F(IndexedDBTransactionTest, Timeout) {
const int64_t id = 0;
const std::set<int64_t> scope;
const leveldb::Status commit_success = leveldb::Status::OK();
- std::unique_ptr<IndexedDBConnection> connection(
- std::make_unique<IndexedDBConnection>(
- kFakeProcessId, db_, new MockIndexedDBDatabaseCallbacks()));
+ std::unique_ptr<IndexedDBConnection> connection =
+ CreateConnection(kFakeProcessId);
std::unique_ptr<IndexedDBTransaction> transaction =
std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction(
- id, connection.get(), scope,
+ id, connection.get(), GetErrorCallback(), scope,
blink::mojom::IDBTransactionMode::ReadWrite,
new IndexedDBFakeBackingStore::FakeTransaction(commit_success)));
db_->RegisterAndScheduleTransaction(transaction.get());
@@ -149,12 +166,11 @@ TEST_F(IndexedDBTransactionTest, NoTimeoutReadOnly) {
const int64_t id = 0;
const std::set<int64_t> scope;
const leveldb::Status commit_success = leveldb::Status::OK();
- std::unique_ptr<IndexedDBConnection> connection(
- std::make_unique<IndexedDBConnection>(
- kFakeProcessId, db_, new MockIndexedDBDatabaseCallbacks()));
+ std::unique_ptr<IndexedDBConnection> connection =
+ CreateConnection(kFakeProcessId);
std::unique_ptr<IndexedDBTransaction> transaction =
std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction(
- id, connection.get(), scope,
+ id, connection.get(), GetErrorCallback(), scope,
blink::mojom::IDBTransactionMode::ReadOnly,
new IndexedDBFakeBackingStore::FakeTransaction(commit_success)));
db_->RegisterAndScheduleTransaction(transaction.get());
@@ -185,12 +201,11 @@ TEST_P(IndexedDBTransactionTestMode, ScheduleNormalTask) {
const int64_t id = 0;
const std::set<int64_t> scope;
const leveldb::Status commit_success = leveldb::Status::OK();
- std::unique_ptr<IndexedDBConnection> connection(
- std::make_unique<IndexedDBConnection>(
- kFakeProcessId, db_, new MockIndexedDBDatabaseCallbacks()));
+ std::unique_ptr<IndexedDBConnection> connection =
+ CreateConnection(kFakeProcessId);
std::unique_ptr<IndexedDBTransaction> transaction =
std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction(
- id, connection.get(), scope, GetParam(),
+ id, connection.get(), GetErrorCallback(), scope, GetParam(),
new IndexedDBFakeBackingStore::FakeTransaction(commit_success)));
EXPECT_FALSE(transaction->HasPendingTasks());
@@ -247,12 +262,11 @@ TEST_P(IndexedDBTransactionTestMode, TaskFails) {
const int64_t id = 0;
const std::set<int64_t> scope;
const leveldb::Status commit_success = leveldb::Status::OK();
- std::unique_ptr<IndexedDBConnection> connection(
- std::make_unique<IndexedDBConnection>(
- kFakeProcessId, db_, new MockIndexedDBDatabaseCallbacks()));
+ std::unique_ptr<IndexedDBConnection> connection =
+ CreateConnection(kFakeProcessId);
std::unique_ptr<IndexedDBTransaction> transaction =
std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction(
- id, connection.get(), scope, GetParam(),
+ id, connection.get(), GetErrorCallback(), scope, GetParam(),
new IndexedDBFakeBackingStore::FakeTransaction(commit_success)));
EXPECT_FALSE(transaction->HasPendingTasks());
@@ -269,8 +283,6 @@ TEST_P(IndexedDBTransactionTestMode, TaskFails) {
EXPECT_TRUE(transaction->task_queue_.empty());
EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
- EXPECT_CALL(*factory_, HandleBackingStoreFailure(testing::_)).Times(1);
-
transaction->ScheduleTask(
blink::mojom::IDBTaskType::Normal,
base::BindOnce(&IndexedDBTransactionTest::DummyOperation,
@@ -296,6 +308,8 @@ TEST_P(IndexedDBTransactionTestMode, TaskFails) {
EXPECT_EQ(1, transaction->diagnostics().tasks_scheduled);
EXPECT_EQ(1, transaction->diagnostics().tasks_completed);
+ EXPECT_TRUE(error_called_);
+
transaction->Commit();
EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state());
@@ -312,12 +326,11 @@ TEST_F(IndexedDBTransactionTest, SchedulePreemptiveTask) {
const int64_t id = 0;
const std::set<int64_t> scope;
const leveldb::Status commit_failure = leveldb::Status::Corruption("Ouch.");
- std::unique_ptr<IndexedDBConnection> connection(
- std::make_unique<IndexedDBConnection>(
- kFakeProcessId, db_, new MockIndexedDBDatabaseCallbacks()));
+ std::unique_ptr<IndexedDBConnection> connection =
+ CreateConnection(kFakeProcessId);
std::unique_ptr<IndexedDBTransaction> transaction =
std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction(
- id, connection.get(), scope,
+ id, connection.get(), GetErrorCallback(), scope,
blink::mojom::IDBTransactionMode::VersionChange,
new IndexedDBFakeBackingStore::FakeTransaction(commit_failure)));
@@ -374,12 +387,11 @@ TEST_P(IndexedDBTransactionTestMode, AbortTasks) {
const int64_t id = 0;
const std::set<int64_t> scope;
const leveldb::Status commit_failure = leveldb::Status::Corruption("Ouch.");
- std::unique_ptr<IndexedDBConnection> connection(
- std::make_unique<IndexedDBConnection>(
- kFakeProcessId, db_, new MockIndexedDBDatabaseCallbacks()));
+ std::unique_ptr<IndexedDBConnection> connection =
+ CreateConnection(kFakeProcessId);
std::unique_ptr<IndexedDBTransaction> transaction =
std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction(
- id, connection.get(), scope, GetParam(),
+ id, connection.get(), GetErrorCallback(), scope, GetParam(),
new IndexedDBFakeBackingStore::FakeTransaction(commit_failure)));
db_->RegisterAndScheduleTransaction(transaction.get());
@@ -403,12 +415,11 @@ TEST_P(IndexedDBTransactionTestMode, AbortPreemptive) {
const int64_t id = 0;
const std::set<int64_t> scope;
const leveldb::Status commit_success = leveldb::Status::OK();
- std::unique_ptr<IndexedDBConnection> connection(
- std::make_unique<IndexedDBConnection>(
- kFakeProcessId, db_, new MockIndexedDBDatabaseCallbacks()));
+ std::unique_ptr<IndexedDBConnection> connection =
+ CreateConnection(kFakeProcessId);
std::unique_ptr<IndexedDBTransaction> transaction =
std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction(
- id, connection.get(), scope, GetParam(),
+ id, connection.get(), GetErrorCallback(), scope, GetParam(),
new IndexedDBFakeBackingStore::FakeTransaction(commit_success)));
db_->RegisterAndScheduleTransaction(transaction.get());
@@ -457,14 +468,13 @@ TEST_F(IndexedDBTransactionTest, IndexedDBObserver) {
const int64_t id = 0;
const std::set<int64_t> scope;
const leveldb::Status commit_success = leveldb::Status::OK();
- std::unique_ptr<IndexedDBConnection> connection(
- std::make_unique<IndexedDBConnection>(
- kFakeProcessId, db_, new MockIndexedDBDatabaseCallbacks()));
+ std::unique_ptr<IndexedDBConnection> connection =
+ CreateConnection(kFakeProcessId);
base::WeakPtr<IndexedDBTransaction> transaction =
connection->AddTransactionForTesting(
std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction(
- id, connection.get(), scope,
+ id, connection.get(), GetErrorCallback(), scope,
blink::mojom::IDBTransactionMode::ReadWrite,
new IndexedDBFakeBackingStore::FakeTransaction(commit_success))));
ASSERT_TRUE(transaction);
diff --git a/chromium/content/browser/indexed_db/indexed_db_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
index 77b970619f0..53f0fe8d006 100644
--- a/chromium/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
@@ -11,6 +11,7 @@
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/time/default_clock.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_factory_impl.h"
@@ -89,7 +90,8 @@ class IndexedDBTest : public testing::Test {
CreateAndReturnTempDir(&temp_dir_),
/*special_storage_policy=*/special_storage_policy_.get(),
quota_manager_proxy_.get(),
- indexed_db::GetDefaultLevelDBFactory())) {
+ indexed_db::GetDefaultLevelDBFactory(),
+ base::DefaultClock::GetInstance())) {
special_storage_policy_->AddSessionOnly(kSessionOnlyOrigin.GetURL());
}
~IndexedDBTest() override {
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
index 516a8a155d6..e3c97f57fdd 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
@@ -12,6 +12,7 @@
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
@@ -90,12 +91,17 @@ class CONTENT_EXPORT LevelDBDatabase
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
+ LevelDBState* leveldb_state() { return level_db_state_.get(); }
leveldb::DB* db() { return level_db_state_->db(); }
leveldb::Env* env() { return level_db_state_->in_memory_env(); }
base::Time LastModified() const { return last_modified_; }
void SetClockForTesting(std::unique_ptr<base::Clock> clock);
+ base::WeakPtr<LevelDBDatabase> AsWeakPtr() {
+ return weak_factory_for_iterators_.GetWeakPtr();
+ }
+
private:
friend class LevelDBSnapshot;
friend class LevelDBIteratorImpl;
@@ -137,6 +143,8 @@ class CONTENT_EXPORT LevelDBDatabase
uint32_t max_iterators_ = 0;
std::string file_name_for_tracing;
+
+ base::WeakPtrFactory<LevelDBDatabase> weak_factory_for_iterators_{this};
};
} // namespace content
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.cc
index eecc77c6323..ea2a6fffddc 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.cc
@@ -21,13 +21,14 @@ static base::StringPiece MakeStringPiece(const leveldb::Slice& s) {
namespace content {
LevelDBIteratorImpl::~LevelDBIteratorImpl() {
- db_->OnIteratorDestroyed(this);
+ if (db_)
+ db_->OnIteratorDestroyed(this);
}
LevelDBIteratorImpl::LevelDBIteratorImpl(std::unique_ptr<leveldb::Iterator> it,
LevelDBDatabase* db,
const leveldb::Snapshot* snapshot)
- : iterator_(std::move(it)), db_(db), snapshot_(snapshot) {}
+ : iterator_(std::move(it)), db_(db->AsWeakPtr()), snapshot_(snapshot) {}
leveldb::Status LevelDBIteratorImpl::CheckStatus() {
DCHECK(!IsDetached());
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.h b/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.h
index 5ebfdd31663..2db73250362 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
#include "content/common/content_export.h"
#include "third_party/leveldatabase/src/include/leveldb/iterator.h"
@@ -51,8 +52,9 @@ class CONTENT_EXPORT LevelDBIteratorImpl : public content::LevelDBIterator {
std::unique_ptr<leveldb::Iterator> iterator_;
- // State used to facilitate memory purging.
- LevelDBDatabase* db_;
+ // State used to facilitate memory purging. Sometimes this is destroyed before
+ // we are, so use a WeakPtr.
+ base::WeakPtr<LevelDBDatabase> db_;
IteratorState iterator_state_ = IteratorState::ACTIVE;
std::string key_before_eviction_;
const leveldb::Snapshot* snapshot_;
diff --git a/chromium/content/browser/indexed_db/list_set.h b/chromium/content/browser/indexed_db/list_set.h
index 3bbd34d06a1..696e63e9178 100644
--- a/chromium/content/browser/indexed_db/list_set.h
+++ b/chromium/content/browser/indexed_db/list_set.h
@@ -57,6 +57,11 @@ class list_set {
list_.erase(it);
}
+ void clear() {
+ set_.clear();
+ list_.clear();
+ }
+
size_t count(const T& elem) const {
return set_.find(elem) == set_.end() ? 0 : 1;
}
diff --git a/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc b/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc
index d77fe67f4c1..7f7fafb2202 100644
--- a/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc
+++ b/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc
@@ -51,20 +51,24 @@ class IndexedDBTestDatabase : public IndexedDBDatabase {
public:
IndexedDBTestDatabase(
const base::string16& name,
- scoped_refptr<IndexedDBBackingStore> backing_store,
- scoped_refptr<IndexedDBFactory> factory,
+ IndexedDBBackingStore* backing_store,
+ IndexedDBFactory* factory,
+ ErrorCallback error_callback,
+ base::OnceClosure destroy_me,
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
- const IndexedDBDatabase::Identifier& unique_identifier,
+ const Identifier& unique_identifier,
ScopesLockManager* transaction_lock_manager)
: IndexedDBDatabase(name,
backing_store,
factory,
+ std::move(error_callback),
+ std::move(destroy_me),
std::move(metadata_coding),
unique_identifier,
transaction_lock_manager) {}
+ ~IndexedDBTestDatabase() override {}
protected:
- ~IndexedDBTestDatabase() override {}
size_t GetUsableMessageSizeInBytes() const override {
return 10 * 1024 * 1024; // 10MB
@@ -76,18 +80,19 @@ class IndexedDBTestTransaction : public IndexedDBTransaction {
IndexedDBTestTransaction(
int64_t id,
IndexedDBConnection* connection,
+ ErrorCallback error_callback,
const std::set<int64_t>& scope,
blink::mojom::IDBTransactionMode mode,
IndexedDBBackingStore::Transaction* backing_store_transaction)
: IndexedDBTransaction(id,
connection,
+ std::move(error_callback),
scope,
mode,
backing_store_transaction) {}
-
- protected:
~IndexedDBTestTransaction() override {}
+ protected:
// Browser tests run under memory/address sanitizers (etc) may trip the
// default 60s timeout, so relax it during tests.
base::TimeDelta GetInactivityTimeout() const override {
@@ -267,28 +272,33 @@ MockBrowserTestIndexedDBClassFactory::MockBrowserTestIndexedDBClassFactory()
MockBrowserTestIndexedDBClassFactory::~MockBrowserTestIndexedDBClassFactory() {
}
-scoped_refptr<IndexedDBDatabase>
+std::unique_ptr<IndexedDBDatabase>
MockBrowserTestIndexedDBClassFactory::CreateIndexedDBDatabase(
const base::string16& name,
- scoped_refptr<IndexedDBBackingStore> backing_store,
- scoped_refptr<IndexedDBFactory> factory,
+ IndexedDBBackingStore* backing_store,
+ IndexedDBFactory* factory,
+ IndexedDBDatabase::ErrorCallback error_callback,
+ base::OnceClosure destroy_me,
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
const IndexedDBDatabase::Identifier& unique_identifier,
ScopesLockManager* transaction_lock_manager) {
- return new IndexedDBTestDatabase(name, backing_store, factory,
- std::move(metadata_coding),
- unique_identifier, transaction_lock_manager);
+ return std::make_unique<IndexedDBTestDatabase>(
+ name, backing_store, factory, std::move(error_callback),
+ std::move(destroy_me), std::move(metadata_coding), unique_identifier,
+ transaction_lock_manager);
}
std::unique_ptr<IndexedDBTransaction>
MockBrowserTestIndexedDBClassFactory::CreateIndexedDBTransaction(
int64_t id,
IndexedDBConnection* connection,
+ ErrorCallback error_callback,
const std::set<int64_t>& scope,
blink::mojom::IDBTransactionMode mode,
IndexedDBBackingStore::Transaction* backing_store_transaction) {
- return std::unique_ptr<IndexedDBTransaction>(new IndexedDBTestTransaction(
- id, connection, scope, mode, backing_store_transaction));
+ return std::make_unique<IndexedDBTestTransaction>(
+ id, connection, std::move(error_callback), scope, mode,
+ backing_store_transaction);
}
scoped_refptr<LevelDBTransaction>
diff --git a/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h b/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h
index 031459c43bd..381251a6513 100644
--- a/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h
+++ b/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h
@@ -47,16 +47,19 @@ class MockBrowserTestIndexedDBClassFactory : public IndexedDBClassFactory {
MockBrowserTestIndexedDBClassFactory();
~MockBrowserTestIndexedDBClassFactory() override;
- scoped_refptr<IndexedDBDatabase> CreateIndexedDBDatabase(
+ std::unique_ptr<IndexedDBDatabase> CreateIndexedDBDatabase(
const base::string16& name,
- scoped_refptr<IndexedDBBackingStore> backing_store,
- scoped_refptr<IndexedDBFactory> factory,
+ IndexedDBBackingStore* backing_store,
+ IndexedDBFactory* factory,
+ IndexedDBDatabase::ErrorCallback error_callback,
+ base::OnceClosure destroy_me,
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
const IndexedDBDatabase::Identifier& unique_identifier,
ScopesLockManager* transaction_lock_manager) override;
std::unique_ptr<IndexedDBTransaction> CreateIndexedDBTransaction(
int64_t id,
IndexedDBConnection* connection,
+ ErrorCallback error_callback,
const std::set<int64_t>& scope,
blink::mojom::IDBTransactionMode mode,
IndexedDBBackingStore::Transaction* backing_store_transaction) override;
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.cc b/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.cc
index 08cfa5920f1..c41f8778110 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.cc
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.cc
@@ -38,13 +38,20 @@ void MockIndexedDBCallbacks::OnSuccess() {}
void MockIndexedDBCallbacks::OnSuccess(int64_t result) {}
void MockIndexedDBCallbacks::OnSuccess(const std::vector<base::string16>&) {}
+void MockIndexedDBCallbacks::OnSuccess(
+ std::vector<blink::mojom::IDBNameAndVersionPtr> names_and_versions) {
+ info_called_ = true;
+}
void MockIndexedDBCallbacks::OnSuccess(const IndexedDBKey& key) {}
void MockIndexedDBCallbacks::OnSuccess(
std::unique_ptr<IndexedDBConnection> connection,
const IndexedDBDatabaseMetadata& metadata) {
- connection_ = std::move(connection);
+ if (!upgrade_called_)
+ connection_ = std::move(connection);
+ if (call_on_db_success_)
+ std::move(call_on_db_success_).Run();
}
void MockIndexedDBCallbacks::OnUpgradeNeeded(
@@ -54,6 +61,15 @@ void MockIndexedDBCallbacks::OnUpgradeNeeded(
const IndexedDBDataLossInfo& data_loss_info) {
connection_ = std::move(connection);
upgrade_called_ = true;
+ if (call_on_upgrade_needed_)
+ std::move(call_on_upgrade_needed_).Run();
+}
+
+void MockIndexedDBCallbacks::CallOnUpgradeNeeded(base::OnceClosure closure) {
+ call_on_upgrade_needed_ = std::move(closure);
+}
+void MockIndexedDBCallbacks::CallOnDBSuccess(base::OnceClosure closure) {
+ call_on_db_success_ = std::move(closure);
}
} // namespace content
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h b/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h
index bc67121a9cd..24f142b2785 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h
@@ -9,6 +9,7 @@
#include <vector>
+#include "base/callback.h"
#include "base/macros.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
@@ -30,18 +31,29 @@ class MockIndexedDBCallbacks : public IndexedDBCallbacks {
void OnSuccess() override;
void OnSuccess(int64_t result) override;
void OnSuccess(const std::vector<base::string16>& result) override;
+ void OnSuccess(std::vector<blink::mojom::IDBNameAndVersionPtr>
+ names_and_versions) override;
void OnSuccess(const blink::IndexedDBKey& key) override;
void OnSuccess(std::unique_ptr<IndexedDBConnection> connection,
const blink::IndexedDBDatabaseMetadata& metadata) override;
IndexedDBConnection* connection() { return connection_.get(); }
+ std::unique_ptr<IndexedDBConnection> TakeConnection() {
+ expect_connection_ = false;
+ return std::move(connection_);
+ }
+
void OnUpgradeNeeded(int64_t old_version,
std::unique_ptr<IndexedDBConnection> connection,
const blink::IndexedDBDatabaseMetadata& metadata,
const IndexedDBDataLossInfo& data_loss_info) override;
+ void CallOnUpgradeNeeded(base::OnceClosure closure);
+ void CallOnDBSuccess(base::OnceClosure closure);
+
bool error_called() { return error_called_; }
bool upgrade_called() { return upgrade_called_; }
+ bool info_called() { return info_called_; }
protected:
~MockIndexedDBCallbacks() override;
@@ -52,6 +64,9 @@ class MockIndexedDBCallbacks : public IndexedDBCallbacks {
bool expect_connection_ = true;
bool error_called_ = false;
bool upgrade_called_ = false;
+ bool info_called_ = false;
+ base::OnceClosure call_on_upgrade_needed_;
+ base::OnceClosure call_on_db_success_;
DISALLOW_COPY_AND_ASSIGN(MockIndexedDBCallbacks);
};
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc b/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc
index a0dfcee1ee3..2148d04c230 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc
@@ -16,6 +16,9 @@ MockIndexedDBDatabaseCallbacks::MockIndexedDBDatabaseCallbacks()
abort_called_(false),
forced_close_called_(false) {}
+void MockIndexedDBDatabaseCallbacks::OnVersionChange(int64_t old_version,
+ int64_t new_version) {}
+
void MockIndexedDBDatabaseCallbacks::OnForcedClose() {
forced_close_called_ = true;
}
@@ -25,5 +28,7 @@ void MockIndexedDBDatabaseCallbacks::OnAbort(
const IndexedDBDatabaseError& error) {
abort_called_ = true;
}
+void MockIndexedDBDatabaseCallbacks::OnComplete(
+ const IndexedDBTransaction& transaction) {}
} // namespace content
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h b/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h
index a8e52902aab..9ffa0cef04b 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h
@@ -17,11 +17,11 @@ class MockIndexedDBDatabaseCallbacks : public IndexedDBDatabaseCallbacks {
public:
MockIndexedDBDatabaseCallbacks();
- void OnVersionChange(int64_t old_version, int64_t new_version) override {}
+ void OnVersionChange(int64_t old_version, int64_t new_version) override;
void OnForcedClose() override;
void OnAbort(const IndexedDBTransaction& transaction,
const IndexedDBDatabaseError& error) override;
- void OnComplete(const IndexedDBTransaction& transaction) override {}
+ void OnComplete(const IndexedDBTransaction& transaction) override;
bool abort_called() const { return abort_called_; }
bool forced_close_called() const { return forced_close_called_; }
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_factory.cc b/chromium/content/browser/indexed_db/mock_indexed_db_factory.cc
index 8fe76a6db84..2a8b03724e5 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_factory.cc
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_factory.cc
@@ -12,9 +12,9 @@ MockIndexedDBFactory::MockIndexedDBFactory() {
MockIndexedDBFactory::~MockIndexedDBFactory() {
}
-IndexedDBFactory::OriginDBs MockIndexedDBFactory::GetOpenDatabasesForOrigin(
+std::vector<IndexedDBDatabase*> MockIndexedDBFactory::GetOpenDatabasesForOrigin(
const url::Origin& origin) const {
- return OriginDBs();
+ return std::vector<IndexedDBDatabase*>();
}
} // namespace content
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_factory.h b/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
index 25c1d62d0a2..f50653e3e0f 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
@@ -15,12 +15,11 @@
namespace content {
+// TODO(dmurph) Remove this by making classes more testable.
class MockIndexedDBFactory : public IndexedDBFactory {
public:
MockIndexedDBFactory();
- MOCK_METHOD2(ReleaseDatabase,
- void(const IndexedDBDatabase::Identifier& identifier,
- bool forced_close));
+ ~MockIndexedDBFactory() override;
MOCK_METHOD3(GetDatabaseNames,
void(scoped_refptr<IndexedDBCallbacks> callbacks,
const url::Origin& origin,
@@ -73,15 +72,14 @@ class MockIndexedDBFactory : public IndexedDBFactory {
const IndexedDBDatabaseError& error));
// The Android NDK implements a subset of STL, and the gtest templates can't
// deal with std::pair's. This means we can't use GoogleMock for this method
- OriginDBs GetOpenDatabasesForOrigin(const url::Origin& origin) const override;
+ std::vector<IndexedDBDatabase*> GetOpenDatabasesForOrigin(
+ const url::Origin& origin) const override;
MOCK_METHOD2(ForceClose,
void(const url::Origin& origin, bool delete_in_memory_store));
MOCK_METHOD1(ForceSchemaDowngrade, void(const url::Origin& origin));
MOCK_METHOD1(HasV2SchemaCorruption,
V2SchemaCorruptionStatus(const url::Origin& origin));
MOCK_METHOD0(ContextDestroyed, void());
- MOCK_METHOD1(DatabaseDeleted,
- void(const IndexedDBDatabase::Identifier& identifier));
MOCK_METHOD1(BlobFilesCleaned, void(const url::Origin& origin));
@@ -100,17 +98,6 @@ class MockIndexedDBFactory : public IndexedDBFactory {
const base::string16& database_name,
const base::string16& object_store_name));
- protected:
- ~MockIndexedDBFactory() override;
-
- MOCK_METHOD2(
- OpenBackingStore,
- std::tuple<scoped_refptr<IndexedDBBackingStore>,
- leveldb::Status,
- IndexedDBDataLossInfo,
- bool /* disk_full */>(const url::Origin& origin,
- const base::FilePath& data_directory));
-
private:
DISALLOW_COPY_AND_ASSIGN(MockIndexedDBFactory);
};
diff --git a/chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h b/chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h
index bb48207d8ae..49bcd93f69f 100644
--- a/chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h
+++ b/chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h
@@ -82,13 +82,6 @@ class MockMojoIndexedDBCallbacks : public blink::mojom::IDBCallbacks {
MockedSuccessValue(&value);
}
- MOCK_METHOD1(MockedSuccessArray,
- void(std::vector<blink::mojom::IDBReturnValuePtr>* values));
- void SuccessArray(
- std::vector<blink::mojom::IDBReturnValuePtr> values) override {
- MockedSuccessArray(&values);
- }
-
MOCK_METHOD1(SuccessKey, void(const blink::IndexedDBKey& key));
MOCK_METHOD1(SuccessInteger, void(int64_t value));
MOCK_METHOD0(Success, void());
diff --git a/chromium/content/browser/indexed_db/ownership_graph.dot b/chromium/content/browser/indexed_db/ownership_graph.dot
new file mode 100644
index 00000000000..4fb91c43fa1
--- /dev/null
+++ b/chromium/content/browser/indexed_db/ownership_graph.dot
@@ -0,0 +1,113 @@
+digraph IndexedDBOwnershipGraph {
+ graph [pad=".5", nodesep="1", ranksep="1"];
+ node [shape="box"];
+
+ // Solid edge means unique ownership reference
+ // Dashed edge means a weakptr reference
+ // Dotted edge means a raw pointer referencej
+
+ subgraph cluster_1 {
+ style=filled;
+ color=lightgrey;
+ node [style=filled,color=white];
+ label = "PROFILE-OWNED";
+ IndexedDBContextImpl;
+ IndexedDBFactoryImpl;
+ PerOriginFactory;
+ IndexedDBDatabase;
+ IndexedDBBackingStore;
+ UpgradeConnectionRequest;
+ DeleteConnectionRequest;
+ }
+
+ subgraph cluster_2 {
+ node [style=filled];
+ label = "MOJO-OWNED";
+ color=blue;
+ IndexedDBDispatcherHost;
+ DatabaseImpl;
+ CursorImpl;
+ TransactionImpl;
+ IndexedDBConnection;
+ IndexedDBTransaction;
+ IndexedDBCursor;
+ "IndexedDBBackingStore::Transaction";
+ "IndexedDBBackingStore::Cursor";
+ }
+
+ subgraph cluster_3 {
+ style=filled;
+ color=lightgrey;
+ node [style=filled,color=white];
+ label = "LEGEND";
+ ExampleA [shape=oval, label="ExampleA\n(Refcounted)"];
+ ExampleB [label="ExampleA\n(Not Refcounted)"];
+ ExampleA -> ExampleB [style="dotted", label="Raw\nReference"];
+ ExampleA -> ExampleB [style="dashed" label="Weak\nReference"];
+ ExampleA -> ExampleB [label="Strong\nReference"];
+ }
+ edge [style=bold];
+
+ "Other parts of the browser" -> IndexedDBContextImpl;
+ StoragePartitionImpl [shape="Mdiamond"];
+ RenderProcessHostImpl [shape="Mdiamond"];
+ StoragePartitionImpl -> IndexedDBContextImpl;
+
+ RenderProcessHostImpl -> IndexedDBDispatcherHost;
+ IndexedDBContextImpl -> IndexedDBFactoryImpl;
+
+ IndexedDBFactoryImpl -> PerOriginFactory;
+ IndexedDBFactoryImpl -> IndexedDBContextImpl [style="dotted"];
+
+ PerOriginFactory -> IndexedDBFactoryImpl [style="dotted"];
+ PerOriginFactory -> IndexedDBBackingStore;
+ PerOriginFactory -> IndexedDBDatabase;
+
+ IndexedDBFactoryHandle -> PerOriginFactory [style="dashed"];
+
+ IndexedDBDatabase -> IndexedDBBackingStore [style="dotted"];
+ IndexedDBDatabase -> IndexedDBFactoryImpl [style="dotted"];
+ IndexedDBDatabase -> IndexedDBConnection [style="dotted", label="All connections to\nthis database."];
+
+ IndexedDBDatabase -> UpgradeConnectionRequest [label="During or\npending upgrade."];
+ IndexedDBDatabase -> DeleteConnectionRequest [label="During or pending\ndatabase deletion."];
+
+ UpgradeConnectionRequest -> IndexedDBFactoryHandle;
+ UpgradeConnectionRequest -> IndexedDBDatabase [style="dotted"];
+ UpgradeConnectionRequest -> IndexedDBConnection [label="Temporarily during\nupgrade."];
+ DeleteConnectionRequest -> IndexedDBFactoryHandle;
+ DeleteConnectionRequest -> IndexedDBDatabase [style="dotted"];
+
+ IndexedDBDispatcherHost -> DatabaseImpl;
+ IndexedDBDispatcherHost -> CursorImpl;
+ IndexedDBDispatcherHost -> TransactionImpl;
+
+ DatabaseImpl -> IndexedDBDispatcherHost [style="dotted"];
+ DatabaseImpl -> IndexedDBContextImpl;
+ DatabaseImpl -> IndexedDBConnection;
+
+ IndexedDBConnection -> IndexedDBFactoryHandle;
+ IndexedDBConnection -> IndexedDBDatabase [style="dashed"];
+ IndexedDBConnection -> IndexedDBTransaction;
+
+ IndexedDBTransaction -> IndexedDBDatabase [style="dashed"];
+ IndexedDBTransaction -> IndexedDBConnection [style="dashed"];
+ IndexedDBTransaction -> IndexedDBCursor [style="dotted",label="All open cursors in\nthis transaction."];
+ IndexedDBTransaction -> "IndexedDBBackingStore::Transaction";
+
+ CursorImpl -> IndexedDBDispatcherHost [style="dotted"];
+ CursorImpl -> IndexedDBCursor;
+
+ IndexedDBCursor -> IndexedDBTransaction [style="dotted"];
+ IndexedDBCursor -> "IndexedDBBackingStore::Cursor";
+
+ "IndexedDBBackingStore::Transaction" -> IndexedDBBackingStore [style="dotted"];
+ "IndexedDBBackingStore::Cursor" -> "IndexedDBBackingStore::Transaction" [style="dotted"];
+ "IndexedDBBackingStore::Cursor" -> IndexedDBBackingStore [style="dotted"];
+
+ TransactionImpl -> IndexedDBDispatcherHost [style="dotted"];
+ TransactionImpl -> IndexedDBContextImpl;
+ TransactionImpl -> IndexedDBTransaction [style="dashed"];
+
+ IndexedDBContextImpl [shape=oval];
+} \ No newline at end of file
diff --git a/chromium/content/browser/indexed_db/scopes/README.md b/chromium/content/browser/indexed_db/scopes/README.md
index 098eeb16907..03c0d369c8d 100644
--- a/chromium/content/browser/indexed_db/scopes/README.md
+++ b/chromium/content/browser/indexed_db/scopes/README.md
@@ -6,17 +6,35 @@ See LevelDB Scopes general design doc [here](https://docs.google.com/document/d/
# Status / Current State
-The only thing implemented so far is the lock manager interface & discrete implementation.
+* Lock manager - Done
+* Scopes - Done
+* Blob / large value support - Future
+
+Things not covered in this README:
+
+* How iterators & scopes interact to ensure the iterator is operating on fresh data
# Vocabulary
**Scope**
-A scope encompasses a group of changes that can be reverted. It is basically synonymous with a transaction, and would be used for readwrite and versionchange transactions in LevelDB. The scope has a defined list of key ranges where the changes can occur. It operates by keeping an undo log, which is either discarded on commit, or replayed on revert.
+A scope encompasses a group of changes that can be reverted. It is basically synonymous with a transaction, and would be used for readwrite and versionchange transactions in LevelDB. The scope has a defined list of key ranges where the changes can occur. It operates by keeping an undo task log, which is either discarded on commit, or replayed on revert. It also keeps a cleanup task log for specialty operations to happen during log cleanup.
+
+**Task**
+
+A task is something that is executed after a scope has been committed. There are two types of tasks (**undo/revert** tasks and **cleanup** tasks), and they are stored in the separate **log**s.
+
+**Undo Task**
-**Undo Log**
+Undo tasks are used to revert a scope (that is, undo the changes that were written by the scope). An undo task is a single operation that is used to undo one or more of these changes. See the [LevelDBScopesUndoTask in `scopes_metadata.proto`](scopes_metadata.proto). Undo tasks are only executed when a scope is reverted.
-Each scope saves an undo log, which has all the information needed to undo all changes performed in the scope.
+**Cleanup Tasks**
+
+Cleanup tasks are optionally executed when a scopes is cleaned up. They consist of deferred deletions (range deletions that the user doesn't need to happen right away).
+
+**Log**
+
+There are two task logs in a scope, the `undo task log` and the `cleanup task log`. They each have a unique key prefix so they can be iterated easily.
**Scope Number (scope#)**
@@ -24,11 +42,11 @@ Each scope has an identifier unique to the backing store that is auto-incrementi
**Sequence Number (seq#)**
-Every undo log entry has a unique sequence number within the scope. These should start at <max int> (using Fixed64) and decrement. The sequence number '0' is reserved for the commit point
+Every undo log entry has a unique sequence number within the scope. These should start at {max int} (using Fixed64) and decrement.
**Commit Point**
-This signifies that a scope has been committed. It also means that a specific sequence number was written for a scope.
+This signifies that a scope has been committed. The commit point for a scope is the absence of `locks` in the scope's metadata.
**Key Range**
@@ -40,12 +58,12 @@ To prevent reading uncommitted data, IndexedDB 'locks' objects stores when there
## New LevelDB Table Data
-|Purpose|Key |Final format|Value (protobufs)|
+|Purpose|Key |Format|Value (protobufs)|
|---|---|---|---|
-|Metadata|undo-metadata|`prefix-0`|`{version: 1}`|
-|Scope Metadata|undo-scopes-<scope#>|`prefix-1-<scope#>`|key ranges if scope is active, or \<empty\> if committed.|
-|Undo log operations|undo-log-<scope#>-<seq#>|`prefix-2-<scope#>-<seq#>`|undo operation|
-|Commit point|undo-log-<scope#>-0|`prefix-2-<scope#>-0`| \<empty\> OR \<ranges to delete\> |
+|Metadata|metadata|`prefix0`|`LevelDBScopesMetadata`|
+|Scope Metadata|scope-{scope#}|`prefix1{scope#}`|`LevelDBScopesScopeMetadata`|
+|Undo log operations|log-undo-{scope#}-{seq#}|`prefix20{scope#}{seq#}`|`LevelDBScopesUndoTask`|
+|Cleanup log operations|log-cleanup-{scope#}-{seq#}|`prefix21{scope#}{seq#}`|`LevelDBScopesCleanupTask`|
### Key Format
@@ -54,72 +72,82 @@ To prevent reading uncommitted data, IndexedDB 'locks' objects stores when there
* Scope # is a varint
* Sequence # is a Fixed64
+See [`leveldb_scopes_coding.h`](leveldb_scopes_coding.h) for the key encoding implementation.
+
### Value Format
-All values will be protobufs
+All values are protobufs, see [`scopes_metadata.proto`](scopes_metadata.proto).
# Operation Flows
+## Acquiring Locks
+**IndexedDB Sequence**
+
+* Input - lock ranges & types. The lock ranges should correspond to the key ranges that will be read from or written to. The type signifies if the lock range should be requested as exclusive or shared.
+* If any of the key ranges are currently locked, then wait until they are all free. This is the IDB transaction sequencing logic.
+* Output - a list of locks, one per requested lock range.
+
## Creating & Using a Scope
-IndexedDB Sequence
+**IndexedDB Sequence**
-* Input - key ranges for the scope. Eg - the applicable object stores (and indexes) for a readwrite txn, or a whole database for a versionchange txn.
-* If any of the key ranges are currently locked, then wait until they are free. This would replace the IDB transaction sequencing logic.
+* Input - a list of locks for the scope. See [Acquiring Locks](#acquiring-locks) above
* Create the scope
* Use the next available scope # (and increment the next scope #)
- * Signal the locks service that the key ranges for this scope are now locked
- * Write undo-scopes-scope# -> key_ranges to LevelDB
-* Enable operations on the scope (probably eventually by binding it using Mojo)
-* For every operation, the scope must read the database to generate the undo log
+* Enable operations on the scope
+* While the total size of changes is less than X Mb, buffer them in a write batch.
+ * If the scope is committed before reaching X Mb, then just commit the scope without generating an undo log.
+* If the size of the buffer write batch is > X Mb, or the user needs to 'read' in the range that was just written to, then the changes must be written to disk.
+ * For every operation, the scope must read the database and append the undo operation to the undo task log.
* See the [Undo Operation Generation](#undo-operations) section below
+* Deferred operations are written do the cleanup task log.
* Output - a Scope
## Committing a Scope
**IndexedDB Sequence**
* Input - a Scope
-* The scope is marked as 'committed', the commit point is written to the undo log (undo-scope#-0), and the metadata is updated to remove the key ranges (undo-scopes-scope# -> <empty>). This change is flushed to disk.
-* The Cleanup & Revert Sequence is signalled for cleaning up the committed scope #.
+* The scope is marked as 'committed' by writing the `LevelDBScopesScopeMetadata` (at `scope-{scope#}`) to remove the `lock` key ranges. This change is flushed to disk.
+* The Cleanup Sequence is signalled for cleaning up the committed scope #.
* Output - Scope is committed, and lock is released.
## Reverting a Scope
-**Cleanup & Revert Sequence**
+**Revert Sequence**
* Input - revert a given scope number.
-* Opens a cursor to undo-<scope#>-0
+* Opens a cursor to `log-undo-{scope#}-0`
* Cursor should be at the first undo entry
- * If sequence #0 exists (this key exists), then error - reverting a committed scope is an invalid state in this design
-* Iterate through undo log, commiting operations and deleting each undo entry.
-* Delete the lock entry at undo-scopes-<scope#>, and flush this change to disk.
+ * If the scope's commit point exists (in the scope's metadata, if the locks are empty) then error - reverting a committed scope is an invalid state in this design
+* Iterate through undo tasks, committing operations.
+* Update the Scope's `LevelDBScopesScopeMetadata` entry (at `scope-{scope#}`) by cleaning the `locks` and setting `ignore_cleanup_tasks = true`, and flush this change to disk.
+* The Cleanup Sequence is signalled for cleaning up the reverted scope #.
* Output - Scope was successfully reverted, and lock released.
## Startup & Recovery
**IndexedDB Sequence**
* Input - the database
-* Reads undo-metadata (fail for unknown version)
-* Opens a cursor to undo-scopes- & iterates to read in all scopes
- * If the scope metadata has key ranges, then those are considered locked
+* Reads metadata (fail for unknown version)
+* Opens a cursor to scopes- & iterates to read in all scopes
+ * If the scope metadata (`LevelDBScopesScopeMetadata` at `scope-{scope#}`) has `locks`, then those are considered locked
* The maximum scope # is found and used to determine the next scope number (used in scope creation)
-* Signals the lock system which locks are held
+* Requests locks from the lock system
* Signals IndexedDB that it can start accepting operations (IndexedDB can now start running)
-* For every undo-scopes- metadata that is empty
+* For every `LevelDBScopesScopeMetadata` that has no `locks`
* Kick off an [Undo Log Cleanup](#undo-log-cleanup) task to eventually clean this up.
-* For every undo-scopes- metadata with key ranges
- * If there is a commit point for any of these scopes, then that is an invalid state / corruption (as the scopes value should have been emptied in the same writebatch that wrote the commit point).
+* For every `LevelDBScopesScopeMetadata` that has `locks`
* Kick off a [Reverting a Scope](#reverting-a-scope) task. This state indicates a shutdown while a revert was in progress.
* Output - nothing, done
## Undo Log Cleanup
**Cleanup & Revert Sequence**
-* Input - nothing
-* Scan the undo- namespace for commit points. If a undo-scope#-0 is found, then start deleting that undo log
- * This can happen in multiple write batches
-* If ranges are found in the undo-scope#-0 (commit point), then
- * Those ranges are also deleted, in batches.
- * Possibly compact these ranges at the end.
-* The undo-scope#-0 and undo-scopes-scope# entries must be deleted last, in the last deletion write batch, so this scope isn't mistaken later as something to be reverted.
+* Input - scope #
+* Open the `scope-{scope#}` metadata
+ * If the commit point is not there (if the `locks` are not empty), then error.
+* If the 'ignore_cleanup_tasks' value is false, then
+ * Iterate through the `log-cleanup-{scope#}-` cleanup tasks and execute them (range deletes).
+* Delete both the undo tasks log and the cleanup task log
+* Delete the `scope-{scope#}` metadata
* Output - nothing
# Lock Manager
@@ -128,9 +156,11 @@ The scopes feature needs a fairly generic lock manager. This lock manager needs
### API Methods
-#### AcquireLock
+#### AcquireLocks
+
+Accepts a list of lock request and a callback which is given a moveable-only lock object, which releases its lock on destruction. Each lock request consists of a lock type (shared or exclusive), a level number, and a key range. The levels are totally independent from the perspective of the lock manager.
-Accepts a lock type (shared or exclusive), a level number, a key range, and a callback which is given a moveable-only lock object, which releases its lock on destruction. The levels are totally independent from the perspective of the lock manager. IF an application wants to use multiple levels, they should employ an acquisition order (like, always acquire locks in increasing level order) so they don't deadlock.
+To keep the implementation simple, all required locks for a given scope or operation need to be acquired all at once.
### Internal Data Structure
@@ -138,12 +168,16 @@ The lock manager basically holds ranges, and needs to know if a new range inters
# Undo Operations
+Undo operations are generated when the undo tasks are required. Note that for under a certain scope 'size' (where the buffer write batch is small enough), no undo operations are generated.
+
## Types
* `Put(key, value)`
* `Delete(key)`
* `DeleteRange(key_range)`
+See `LevelDBScopesUndoTask` in the [`scopes_metadata.proto`](scopes_metadata.proto)
+
## Generation
### Normal Cases
@@ -154,7 +188,7 @@ Note - all cases where "old_value" is used requires reading the current value fr
* `Delete(key)` if an old value doesn't exist,
* `Put(key, old_value)` if an old value does exist, or
-* Nothing if the old value and new value matches
+* Nothing if the old value and new value matche
**`Add(key, value)`**
@@ -177,8 +211,8 @@ If the values being created are in a key range that is initially empty (we trust
`DeleteRange(key_range)`
-Examples of this are creating new databases or indexes in a versionchange transaction. The scopes system can check to make sure it's range is empty before doing operations. This can either be done as a hint (per-range, per-scope), or always.
+Examples of this are creating new databases or indexes in a versionchange transaction. The scopes system can check to make sure it's range is empty before doing operations in debug builds.
#### Deletion - key range will never be used again.
-This is done by having commit ranges in the value of the commit point. A new scope is created, and committed, with the key ranges never-to-be-used-again will be the value of the commit point record.
+This is done by creating a cleanup task (see `LevelDBScopesCleanupTask` in [`scopes_metadata.proto`](scopes_metadata.proto)). When the scope is cleaned up, these operations are executed. This allows a user to defer the deletion to a later time and a different thread. \ No newline at end of file
diff --git a/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.cc b/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.cc
index 6c27e99614a..478a5c92052 100644
--- a/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.cc
+++ b/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.cc
@@ -6,14 +6,19 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
#include "base/threading/sequenced_task_runner_handle.h"
namespace content {
DisjointRangeLockManager::LockRequest::LockRequest() = default;
-DisjointRangeLockManager::LockRequest::LockRequest(LockType type,
- LockAquiredCallback callback)
- : requested_type(type), callback(std::move(callback)) {}
+DisjointRangeLockManager::LockRequest::LockRequest(
+ LockType type,
+ base::WeakPtr<ScopesLocksHolder> locks_holder,
+ base::OnceClosure acquired_callback)
+ : requested_type(type),
+ locks_holder(std::move(locks_holder)),
+ acquired_callback(std::move(acquired_callback)) {}
DisjointRangeLockManager::LockRequest::LockRequest(LockRequest&&) noexcept =
default;
DisjointRangeLockManager::LockRequest::~LockRequest() = default;
@@ -54,37 +59,48 @@ int64_t DisjointRangeLockManager::RequestsWaitingForTesting() const {
bool DisjointRangeLockManager::AcquireLocks(
base::flat_set<ScopeLockRequest> lock_requests,
+ base::WeakPtr<ScopesLocksHolder> locks_holder,
LocksAquiredCallback callback) {
+ if (!locks_holder)
+ return false;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Since the barrier needs ownership of the locks right away, a simple value
- // type (that is moved into the barrier) cannot be used as it is impossible to
- // grab a pointer from inside the barrier callback. So instead a unique_ptr is
- // used.
- std::unique_ptr<std::vector<ScopeLock>> locks =
- std::make_unique<std::vector<ScopeLock>>();
- auto* locks_ptr = locks.get();
- size_t size = lock_requests.size();
- base::RepeatingClosure barrier = base::BarrierClosure(
- size, base::BindOnce(
- [](LocksAquiredCallback callback,
- std::unique_ptr<std::vector<ScopeLock>> locks) {
- std::move(callback).Run(std::move(*locks));
- },
- std::move(callback), std::move(locks)));
+
+ // Code relies on free locks being granted synchronously. If the locks aren't
+ // free, then the grant must happen as a PostTask to avoid overflowing the
+ // stack (every task would execute in the stack of its parent task,
+ // recursively).
+ scoped_refptr<base::RefCountedData<bool>> run_callback_synchonously =
+ base::MakeRefCounted<base::RefCountedData<bool>>(true);
+
+ locks_holder->locks.reserve(lock_requests.size());
+ size_t num_closure_calls = lock_requests.size();
+ base::RepeatingClosure all_locks_acquired_barrier = base::BarrierClosure(
+ num_closure_calls,
+ base::BindOnce(
+ [](scoped_refptr<base::SequencedTaskRunner> runner,
+ scoped_refptr<base::RefCountedData<bool>> run_synchronously,
+ base::WeakPtr<ScopesLocksHolder> holder,
+ LocksAquiredCallback callback) {
+ // All locks have been acquired.
+ if (!holder || callback.IsCancelled() || callback.is_null())
+ return;
+ if (run_synchronously->data)
+ std::move(callback).Run();
+ else
+ runner->PostTask(FROM_HERE, std::move(callback));
+ },
+ task_runner_, run_callback_synchonously, locks_holder,
+ std::move(callback)));
for (ScopeLockRequest& request : lock_requests) {
- bool success =
- AcquireLock(std::move(request),
- base::BindOnce(
- [](std::vector<ScopeLock>* lock_container,
- base::OnceClosure barrier_closure, ScopeLock lock) {
- // Lock has been acquired.
- lock_container->push_back(std::move(lock));
- std::move(barrier_closure).Run();
- },
- base::Unretained(locks_ptr), barrier));
- if (!success)
+ bool success = AcquireLock(std::move(request), locks_holder,
+ all_locks_acquired_barrier);
+ if (!success) {
+ locks_holder->locks.clear();
return false;
+ }
}
+ // If the barrier wasn't run yet, then it will be run asynchronously.
+ run_callback_synchonously->data = false;
return true;
}
@@ -102,7 +118,9 @@ void DisjointRangeLockManager::RemoveLockRange(int level,
bool DisjointRangeLockManager::AcquireLock(
ScopeLockRequest request,
- LockAquiredCallback acquired_callback) {
+ base::WeakPtr<ScopesLocksHolder> locks_holder,
+ base::OnceClosure acquired_callback) {
+ DCHECK(locks_holder);
if (request.level < 0 || static_cast<size_t>(request.level) >= locks_.size())
return false;
if (request.range.begin >= request.range.end)
@@ -119,8 +137,10 @@ bool DisjointRangeLockManager::AcquireLock(
.first;
}
- if (!IsRangeDisjointFromNeighbors(level_locks, request.range))
+ if (!IsRangeDisjointFromNeighbors(level_locks, request.range)) {
+ level_locks.erase(it);
return false;
+ }
Lock& lock = it->second;
if (lock.CanBeAcquired(request.type)) {
@@ -129,14 +149,15 @@ bool DisjointRangeLockManager::AcquireLock(
auto released_callback = base::BindOnce(
&DisjointRangeLockManager::LockReleased, weak_factory_.GetWeakPtr(),
request.level, std::move(request.range));
- std::move(acquired_callback)
- .Run(ScopeLock(std::move(request.range), request.level,
- std::move(released_callback)));
+ locks_holder->locks.emplace_back(std::move(request.range), request.level,
+ std::move(released_callback));
+ std::move(acquired_callback).Run();
} else {
// The lock cannot be acquired now, so we put it on the queue which will
// grant the given callback the lock when it is acquired in the future in
// the |LockReleased| method.
- lock.queue.emplace_back(request.type, std::move(acquired_callback));
+ lock.queue.emplace_back(request.type, std::move(locks_holder),
+ std::move(acquired_callback));
}
return true;
}
@@ -156,18 +177,26 @@ void DisjointRangeLockManager::LockReleased(int level, ScopeLockRange range) {
while (!lock.queue.empty() &&
(lock.acquired_count == 0 ||
lock.queue.front().requested_type == LockType::kShared)) {
- // Grant the lock to the next requester.
+ // Pop the next requester.
LockRequest requester = std::move(lock.queue.front());
lock.queue.pop_front();
+
+ // Skip the request if the lock holder is already destroyed. This avoids
+ // stack overflows for long chains of released locks.
+ // See https://crbug.com/959743
+ if (!requester.locks_holder) {
+ continue;
+ }
+
++lock.acquired_count;
lock.lock_mode = requester.requested_type;
auto released_callback =
base::BindOnce(&DisjointRangeLockManager::LockReleased,
weak_factory_.GetWeakPtr(), level, range);
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(std::move(requester.callback),
- ScopeLock(std::move(range), level,
- std::move(released_callback))));
+ // Grant the lock.
+ requester.locks_holder->locks.emplace_back(std::move(range), level,
+ std::move(released_callback));
+ std::move(requester.acquired_callback).Run();
// This can only happen if acquired_count was 0.
if (requester.requested_type == LockType::kExclusive)
return;
diff --git a/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.h b/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.h
index 498a2316bed..ed5808e2a0b 100644
--- a/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.h
+++ b/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.h
@@ -53,6 +53,7 @@ class CONTENT_EXPORT DisjointRangeLockManager : public ScopesLockManager {
// * range disjoint from other lock ranges (which is an implementation
// invariant).
bool AcquireLocks(base::flat_set<ScopeLockRequest> lock_requests,
+ base::WeakPtr<ScopesLocksHolder> locks_holder,
LocksAquiredCallback callback) override;
// Remove the given lock range at the given level. The lock range must not be
@@ -60,16 +61,18 @@ class CONTENT_EXPORT DisjointRangeLockManager : public ScopesLockManager {
void RemoveLockRange(int level, const ScopeLockRange& range);
private:
- using LockAquiredCallback = base::OnceCallback<void(ScopeLock)>;
struct LockRequest {
public:
LockRequest();
LockRequest(LockRequest&&) noexcept;
- LockRequest(LockType type, LockAquiredCallback callback);
+ LockRequest(LockType type,
+ base::WeakPtr<ScopesLocksHolder> locks_holder,
+ base::OnceClosure callback);
~LockRequest();
LockType requested_type = LockType::kShared;
- LockAquiredCallback callback;
+ base::WeakPtr<ScopesLocksHolder> locks_holder;
+ base::OnceClosure acquired_callback;
};
// Represents a lock, which has a range and a level. To support shared access,
@@ -98,7 +101,9 @@ class CONTENT_EXPORT DisjointRangeLockManager : public ScopesLockManager {
using LockLevelMap = base::flat_map<ScopeLockRange, Lock>;
- bool AcquireLock(ScopeLockRequest request, LockAquiredCallback callback);
+ bool AcquireLock(ScopeLockRequest request,
+ base::WeakPtr<ScopesLocksHolder> locks_holder,
+ base::OnceClosure acquired_callback);
void LockReleased(int level, ScopeLockRange range);
diff --git a/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager_unittest.cc b/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager_unittest.cc
index 79f9ed14404..8e72d737f07 100644
--- a/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager_unittest.cc
+++ b/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager_unittest.cc
@@ -29,13 +29,6 @@ std::string IntegerKey(size_t num) {
return base::StringPrintf("%010zd", num);
}
-void StoreLocks(std::vector<ScopeLock>* locks_out,
- base::OnceClosure done,
- std::vector<ScopeLock> locks) {
- (*locks_out) = std::move(locks);
- std::move(done).Run();
-}
-
class DisjointRangeLockManagerTest : public testing::Test {
public:
DisjointRangeLockManagerTest() = default;
@@ -53,10 +46,8 @@ TEST_F(DisjointRangeLockManagerTest, BasicAcquisition) {
EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
base::RunLoop loop;
- std::vector<ScopeLock> locks1;
- std::vector<ScopeLock> locks2;
- std::vector<ScopeLock> locks;
- locks.resize(kTotalLocks);
+ ScopesLocksHolder holder1;
+ ScopesLocksHolder holder2;
{
BarrierBuilder barrier(loop.QuitClosure());
@@ -66,9 +57,8 @@ TEST_F(DisjointRangeLockManagerTest, BasicAcquisition) {
locks1_requests.emplace_back(0, std::move(range),
ScopesLockManager::LockType::kExclusive);
}
- EXPECT_TRUE(lock_manager.AcquireLocks(
- locks1_requests,
- base::BindOnce(StoreLocks, &locks1, barrier.AddClosure())));
+ EXPECT_TRUE(lock_manager.AcquireLocks(locks1_requests, holder1.AsWeakPtr(),
+ barrier.AddClosure()));
// Now acquire kTotalLocks/2 locks starting at (kTotalLocks-1) to verify
// they acquire in the correct order.
@@ -78,35 +68,34 @@ TEST_F(DisjointRangeLockManagerTest, BasicAcquisition) {
locks2_requests.emplace_back(0, std::move(range),
ScopesLockManager::LockType::kExclusive);
}
- EXPECT_TRUE(lock_manager.AcquireLocks(
- locks2_requests,
- base::BindOnce(StoreLocks, &locks2, barrier.AddClosure())));
+ EXPECT_TRUE(lock_manager.AcquireLocks(locks2_requests, holder2.AsWeakPtr(),
+ barrier.AddClosure()));
}
loop.Run();
EXPECT_EQ(static_cast<int64_t>(kTotalLocks),
lock_manager.LocksHeldForTesting());
EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
// All locks should be acquired.
- for (const auto& lock : locks1) {
+ for (const auto& lock : holder1.locks) {
EXPECT_TRUE(lock.is_locked());
}
- for (const auto& lock : locks2) {
+ for (const auto& lock : holder2.locks) {
EXPECT_TRUE(lock.is_locked());
}
// Release locks manually
- for (auto& lock : locks1) {
+ for (auto& lock : holder1.locks) {
lock.Release();
EXPECT_FALSE(lock.is_locked());
}
- for (auto& lock : locks2) {
+ for (auto& lock : holder2.locks) {
lock.Release();
EXPECT_FALSE(lock.is_locked());
}
EXPECT_EQ(0ll, lock_manager.LocksHeldForTesting());
- locks1.clear();
- locks2.clear();
+ holder1.locks.clear();
+ holder2.locks.clear();
}
TEST_F(DisjointRangeLockManagerTest, Shared) {
@@ -116,23 +105,23 @@ TEST_F(DisjointRangeLockManagerTest, Shared) {
ScopeLockRange range = {IntegerKey(0), IntegerKey(1)};
- std::vector<ScopeLock> locks1;
- std::vector<ScopeLock> locks2;
+ ScopesLocksHolder locks_holder1;
+ ScopesLocksHolder locks_holder2;
base::RunLoop loop;
{
BarrierBuilder barrier(loop.QuitClosure());
EXPECT_TRUE(lock_manager.AcquireLocks(
{{0, range, ScopesLockManager::LockType::kShared}},
- base::BindOnce(StoreLocks, &locks1, barrier.AddClosure())));
+ locks_holder1.AsWeakPtr(), barrier.AddClosure()));
EXPECT_TRUE(lock_manager.AcquireLocks(
{{0, range, ScopesLockManager::LockType::kShared}},
- base::BindOnce(StoreLocks, &locks2, barrier.AddClosure())));
+ locks_holder2.AsWeakPtr(), barrier.AddClosure()));
}
loop.Run();
EXPECT_EQ(2ll, lock_manager.LocksHeldForTesting());
- EXPECT_TRUE(locks1.begin()->is_locked());
- EXPECT_TRUE(locks2.begin()->is_locked());
+ EXPECT_TRUE(locks_holder1.locks.begin()->is_locked());
+ EXPECT_TRUE(locks_holder2.locks.begin()->is_locked());
}
TEST_F(DisjointRangeLockManagerTest, SharedAndExclusiveQueuing) {
@@ -142,10 +131,10 @@ TEST_F(DisjointRangeLockManagerTest, SharedAndExclusiveQueuing) {
ScopeLockRange range = {IntegerKey(0), IntegerKey(1)};
- std::vector<ScopeLock> shared_lock1;
- std::vector<ScopeLock> shared_lock2;
- std::vector<ScopeLock> exclusive_lock3;
- std::vector<ScopeLock> shared_lock3;
+ ScopesLocksHolder shared_lock1_holder;
+ ScopesLocksHolder shared_lock2_holder;
+ ScopesLocksHolder exclusive_lock3_holder;
+ ScopesLocksHolder shared_lock3_holder;
{
base::RunLoop loop;
@@ -153,10 +142,10 @@ TEST_F(DisjointRangeLockManagerTest, SharedAndExclusiveQueuing) {
BarrierBuilder barrier(loop.QuitClosure());
EXPECT_TRUE(lock_manager.AcquireLocks(
{{0, range, ScopesLockManager::LockType::kShared}},
- base::BindOnce(StoreLocks, &shared_lock1, barrier.AddClosure())));
+ shared_lock1_holder.AsWeakPtr(), barrier.AddClosure()));
EXPECT_TRUE(lock_manager.AcquireLocks(
{{0, range, ScopesLockManager::LockType::kShared}},
- base::BindOnce(StoreLocks, &shared_lock2, barrier.AddClosure())));
+ shared_lock2_holder.AsWeakPtr(), barrier.AddClosure()));
}
loop.Run();
}
@@ -167,10 +156,10 @@ TEST_F(DisjointRangeLockManagerTest, SharedAndExclusiveQueuing) {
// line, then the shared lock will come after it.
EXPECT_TRUE(lock_manager.AcquireLocks(
{{0, range, ScopesLockManager::LockType::kExclusive}},
- base::BindOnce(StoreLocks, &exclusive_lock3, base::DoNothing::Once())));
+ exclusive_lock3_holder.AsWeakPtr(), base::DoNothing::Once()));
EXPECT_TRUE(lock_manager.AcquireLocks(
{{0, range, ScopesLockManager::LockType::kShared}},
- base::BindOnce(StoreLocks, &shared_lock3, base::DoNothing::Once())));
+ shared_lock3_holder.AsWeakPtr(), base::DoNothing::Once()));
// Flush the task queue.
{
base::RunLoop loop;
@@ -178,16 +167,14 @@ TEST_F(DisjointRangeLockManagerTest, SharedAndExclusiveQueuing) {
loop.QuitClosure());
loop.Run();
}
- EXPECT_TRUE(exclusive_lock3.empty());
- EXPECT_TRUE(shared_lock3.empty());
+ EXPECT_TRUE(exclusive_lock3_holder.locks.empty());
+ EXPECT_TRUE(shared_lock3_holder.locks.empty());
EXPECT_EQ(2ll, lock_manager.LocksHeldForTesting());
EXPECT_EQ(2ll, lock_manager.RequestsWaitingForTesting());
// Release the shared locks.
- shared_lock1.clear();
- shared_lock2.clear();
- EXPECT_TRUE(shared_lock1.empty());
- EXPECT_TRUE(shared_lock2.empty());
+ shared_lock1_holder.locks.clear();
+ shared_lock2_holder.locks.clear();
// Flush the task queue to propagate the lock releases and grant the exclusive
// lock.
@@ -197,13 +184,12 @@ TEST_F(DisjointRangeLockManagerTest, SharedAndExclusiveQueuing) {
loop.QuitClosure());
loop.Run();
}
- EXPECT_FALSE(exclusive_lock3.empty());
- EXPECT_TRUE(shared_lock3.empty());
+ EXPECT_FALSE(exclusive_lock3_holder.locks.empty());
+ EXPECT_TRUE(shared_lock3_holder.locks.empty());
EXPECT_EQ(1ll, lock_manager.LocksHeldForTesting());
EXPECT_EQ(1ll, lock_manager.RequestsWaitingForTesting());
- exclusive_lock3.clear();
- EXPECT_TRUE(exclusive_lock3.empty());
+ exclusive_lock3_holder.locks.clear();
// Flush the task queue to propagate the lock releases and grant the exclusive
// lock.
@@ -213,7 +199,7 @@ TEST_F(DisjointRangeLockManagerTest, SharedAndExclusiveQueuing) {
loop.QuitClosure());
loop.Run();
}
- EXPECT_FALSE(shared_lock3.empty());
+ EXPECT_FALSE(shared_lock3_holder.locks.empty());
EXPECT_EQ(1ll, lock_manager.LocksHeldForTesting());
EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
}
@@ -221,57 +207,65 @@ TEST_F(DisjointRangeLockManagerTest, SharedAndExclusiveQueuing) {
TEST_F(DisjointRangeLockManagerTest, LevelsOperateSeparately) {
DisjointRangeLockManager lock_manager(2);
base::RunLoop loop;
- std::vector<ScopeLock> l0_lock;
- std::vector<ScopeLock> l1_lock;
+ ScopesLocksHolder l0_lock_holder;
+ ScopesLocksHolder l1_lock_holder;
{
BarrierBuilder barrier(loop.QuitClosure());
ScopeLockRange range = {IntegerKey(0), IntegerKey(1)};
EXPECT_TRUE(lock_manager.AcquireLocks(
{{0, range, ScopesLockManager::LockType::kExclusive}},
- base::BindOnce(StoreLocks, &l0_lock, barrier.AddClosure())));
+ l0_lock_holder.AsWeakPtr(), barrier.AddClosure()));
EXPECT_TRUE(lock_manager.AcquireLocks(
{{1, range, ScopesLockManager::LockType::kExclusive}},
- base::BindOnce(StoreLocks, &l1_lock, barrier.AddClosure())));
+ l1_lock_holder.AsWeakPtr(), barrier.AddClosure()));
}
loop.Run();
- EXPECT_FALSE(l0_lock.empty());
- EXPECT_FALSE(l1_lock.empty());
+ EXPECT_FALSE(l0_lock_holder.locks.empty());
+ EXPECT_FALSE(l1_lock_holder.locks.empty());
EXPECT_EQ(2ll, lock_manager.LocksHeldForTesting());
EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
- l0_lock.clear();
- l1_lock.clear();
+ l0_lock_holder.locks.clear();
+ l1_lock_holder.locks.clear();
EXPECT_EQ(0ll, lock_manager.LocksHeldForTesting());
}
TEST_F(DisjointRangeLockManagerTest, InvalidRequests) {
DisjointRangeLockManager lock_manager(2);
- std::vector<ScopeLock> locks;
+ ScopesLocksHolder locks_holder;
ScopeLockRange range1 = {IntegerKey(0), IntegerKey(2)};
ScopeLockRange range2 = {IntegerKey(1), IntegerKey(3)};
+
+ // Invalid because the ranges intersect.
EXPECT_FALSE(lock_manager.AcquireLocks(
{{0, range1, ScopesLockManager::LockType::kShared},
{0, range2, ScopesLockManager::LockType::kShared}},
- base::BindOnce(StoreLocks, &locks, base::DoNothing::Once())));
- EXPECT_TRUE(locks.empty());
+ locks_holder.AsWeakPtr(), base::DoNothing::Once()));
+ EXPECT_TRUE(locks_holder.locks.empty());
EXPECT_EQ(0ll, lock_manager.LocksHeldForTesting());
EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
+
+ // Invalid level.
EXPECT_FALSE(lock_manager.AcquireLocks(
{{-1, range1, ScopesLockManager::LockType::kShared}},
- base::BindOnce(StoreLocks, &locks, base::DoNothing::Once())));
- EXPECT_TRUE(locks.empty());
+ locks_holder.AsWeakPtr(), base::DoNothing::Once()));
+ EXPECT_TRUE(locks_holder.locks.empty());
EXPECT_EQ(0ll, lock_manager.LocksHeldForTesting());
EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
+
+ // Invalid level.
EXPECT_FALSE(lock_manager.AcquireLocks(
{{4, range1, ScopesLockManager::LockType::kShared}},
- base::BindOnce(StoreLocks, &locks, base::DoNothing::Once())));
- EXPECT_TRUE(locks.empty());
+ locks_holder.AsWeakPtr(), base::DoNothing::Once()));
+ EXPECT_TRUE(locks_holder.locks.empty());
EXPECT_EQ(0ll, lock_manager.LocksHeldForTesting());
EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
+
+ // Invalid range.
ScopeLockRange range3 = {IntegerKey(2), IntegerKey(1)};
EXPECT_FALSE(lock_manager.AcquireLocks(
- {{0, range1, ScopesLockManager::LockType::kShared}},
- base::BindOnce(StoreLocks, &locks, base::DoNothing::Once())));
- EXPECT_TRUE(locks.empty());
+ {{0, range3, ScopesLockManager::LockType::kShared}},
+ locks_holder.AsWeakPtr(), base::DoNothing::Once()));
+ EXPECT_TRUE(locks_holder.locks.empty());
EXPECT_EQ(0ll, lock_manager.LocksHeldForTesting());
EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
}
diff --git a/chromium/content/browser/indexed_db/scopes/leveldb_scope.cc b/chromium/content/browser/indexed_db/scopes/leveldb_scope.cc
new file mode 100644
index 00000000000..4827e7e7a78
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/leveldb_scope.cc
@@ -0,0 +1,513 @@
+// 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/indexed_db/scopes/leveldb_scope.h"
+
+#include <memory>
+
+#include "base/compiler_specific.h"
+#include "base/debug/stack_trace.h"
+#include "base/memory/ptr_util.h"
+#include "base/optional.h"
+#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
+#include "content/browser/indexed_db/scopes/leveldb_scopes_coding.h"
+#include "third_party/leveldatabase/src/include/leveldb/comparator.h"
+#include "third_party/leveldatabase/src/include/leveldb/db.h"
+
+namespace content {
+namespace {
+
+#if DCHECK_IS_ON()
+leveldb::Slice Uint8VectorToSlice(const std::vector<uint8_t>& vector) {
+ return leveldb::Slice(reinterpret_cast<const char*>(vector.data()),
+ vector.size());
+}
+#endif
+
+// Tests if the given key is before the end of a range.
+bool IsKeyBeforeEndOfRange(const leveldb::Comparator* comparator,
+ const leveldb::Slice& key,
+ const leveldb::Slice& end,
+ bool end_exclusive) {
+ return (end_exclusive ? comparator->Compare(key, end) < 0
+ : comparator->Compare(key, end) <= 0);
+}
+
+} // namespace
+
+// Adds undo log tasks to the given LevelDBScope for every entry found in the
+// WriteBatch that this is iterating.
+// Taken partially, the resulting undo log is technically incorrect. Two
+// operations for the same key, for example Put(K, V1) and Put(K, V2), will
+// result in an undo log containing either Put(K, old_value_for_k) twice or
+// Delete(K) twice. This is OK, because recovery always applies the entire undo
+// log, so it only matters that each key's final operation is correct.
+class LevelDBScope::UndoLogWriter : public leveldb::WriteBatch::Handler {
+ public:
+ UndoLogWriter(LevelDBScope* scope, leveldb::DB* db)
+ : scope_(scope), db_(db) {}
+ ~UndoLogWriter() override = default;
+
+ void Put(const leveldb::Slice& key, const leveldb::Slice& value) override {
+ DCHECK(scope_->IsUndoLogMode());
+ if (UNLIKELY(!error_.ok()))
+ return;
+ if (scope_->CanSkipWritingUndoEntry(key))
+ return;
+ leveldb::ReadOptions read_options;
+ read_options.verify_checksums = true;
+ // Since the values being read here are going to be overwritten as soon as
+ // the write batch is written, the block will basically be obsolete. Thus,
+ // don't bother caching.
+ read_options.fill_cache = false;
+ read_buffer_.clear();
+ leveldb::Status s = db_->Get(read_options, key, &read_buffer_);
+ if (s.IsNotFound()) {
+ scope_->AddUndoDeleteTask(key.ToString());
+ return;
+ }
+ if (UNLIKELY(!s.ok())) {
+ error_ = std::move(s);
+ return;
+ }
+ scope_->AddUndoPutTask(key.ToString(), std::move(read_buffer_));
+ }
+
+ void Delete(const leveldb::Slice& key) override {
+ DCHECK(scope_->IsUndoLogMode());
+ if (UNLIKELY(!error_.ok()))
+ return;
+ if (scope_->CanSkipWritingUndoEntry(key))
+ return;
+ leveldb::ReadOptions read_options;
+ read_options.verify_checksums = true;
+ // Since the values being read here are going to be overwritten as soon as
+ // the write batch is written, the block will basically be obsolete. Thus,
+ // don't bother caching.
+ read_options.fill_cache = false;
+ read_buffer_.clear();
+ leveldb::Status s = db_->Get(read_options, key, &read_buffer_);
+ if (s.IsNotFound())
+ return;
+ if (UNLIKELY(!s.ok())) {
+ error_ = std::move(s);
+ return;
+ }
+ scope_->AddUndoPutTask(key.ToString(), std::move(read_buffer_));
+ }
+
+ const leveldb::Status& error() const { return error_; }
+
+ private:
+ LevelDBScope* const scope_;
+ leveldb::DB* const db_;
+ std::string read_buffer_;
+ leveldb::Status error_ = leveldb::Status::OK();
+};
+
+LevelDBScope::EmptyRangeLessThan::EmptyRangeLessThan() = default;
+LevelDBScope::EmptyRangeLessThan::EmptyRangeLessThan(
+ const leveldb::Comparator* comparator)
+ : comparator_(comparator) {}
+LevelDBScope::EmptyRangeLessThan& LevelDBScope::EmptyRangeLessThan::operator=(
+ const LevelDBScope::EmptyRangeLessThan& other) = default;
+
+// The ranges are expected to be disjoint.
+bool LevelDBScope::EmptyRangeLessThan::operator()(const EmptyRange& lhs,
+ const EmptyRange& rhs) const {
+ return comparator_->Compare(lhs.first, rhs.first) < 0;
+}
+
+LevelDBScope::LevelDBScope(
+ int64_t scope_id,
+ std::vector<uint8_t> prefix,
+ size_t write_batch_size,
+ scoped_refptr<LevelDBState> level_db,
+ std::vector<ScopeLock> locks,
+ std::vector<std::pair<std::string, std::string>> empty_ranges,
+ RollbackCallback rollback_callback)
+ : scope_id_(scope_id),
+ prefix_(std::move(prefix)),
+ write_batch_size_(write_batch_size),
+ level_db_(std::move(level_db)),
+ locks_(std::move(locks)),
+ rollback_callback_(std::move(rollback_callback)) {
+ DCHECK(!locks_.empty());
+ std::vector<std::pair<EmptyRange, bool>> map_values;
+ map_values.reserve(empty_ranges.size());
+ for (EmptyRange& range : empty_ranges) {
+ // Moving the range here technically messes up the sorting order of
+ // empty_ranges, but it's not used again anyways so we don't mind.
+ map_values.emplace_back(std::move(range), false);
+ }
+ empty_ranges_ = base::flat_map<EmptyRange, bool, EmptyRangeLessThan>(
+ std::move(map_values), base::KEEP_FIRST_OF_DUPES,
+ EmptyRangeLessThan(level_db_->comparator()));
+
+#if DCHECK_IS_ON()
+ ValidateEmptyRanges();
+#endif
+}
+
+LevelDBScope::~LevelDBScope() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (UNLIKELY(has_written_to_disk_ && !committed_)) {
+ DCHECK(undo_sequence_number_ < std::numeric_limits<int64_t>::max() ||
+ cleanup_sequence_number_ > 0)
+ << "A reverting scope that has written to disk must have either an "
+ "undo or cleanup task written to it.";
+ std::move(rollback_callback_).Run(scope_id_, std::move(locks_));
+ }
+}
+
+leveldb::Status LevelDBScope::Put(const leveldb::Slice& key,
+ const leveldb::Slice& value) {
+ // This has to be used for IsInDeferredDeletionRange, so it might as well
+ // surround all the DCHECKs.
+#if DCHECK_IS_ON()
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!key.starts_with(Uint8VectorToSlice(prefix_)));
+ DCHECK(!committed_);
+ DCHECK(!locks_.empty());
+ DCHECK(!IsInDeferredDeletionRange(key))
+ << "Cannot put a value in a range that will be deleted later.";
+#endif
+ buffer_batch_.Put(key, value);
+ buffer_batch_empty_ = false;
+ if (GetMemoryUsage() > write_batch_size_)
+ return WriteChangesAndUndoLog();
+ return leveldb::Status::OK();
+}
+
+leveldb::Status LevelDBScope::Delete(const leveldb::Slice& key) {
+ // This has to be used for IsInDeferredDeletionRange, so it might as well
+ // surround all the DCHECKs.
+#if DCHECK_IS_ON()
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!key.starts_with(Uint8VectorToSlice(prefix_)));
+ DCHECK(!committed_);
+ DCHECK(!locks_.empty());
+ DCHECK(!IsInDeferredDeletionRange(key))
+ << "Cannot delete value in a range that will be deleted later.";
+#endif
+ buffer_batch_.Delete(key);
+ buffer_batch_empty_ = false;
+ if (GetMemoryUsage() > write_batch_size_)
+ return WriteChangesAndUndoLog();
+ return leveldb::Status::OK();
+}
+
+leveldb::Status LevelDBScope::DeleteRange(const leveldb::Slice& begin,
+ const leveldb::Slice& end,
+ LevelDBScopeDeletionMode mode) {
+#if DCHECK_IS_ON()
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!begin.starts_with(Uint8VectorToSlice(prefix_)));
+ DCHECK(!end.starts_with(Uint8VectorToSlice(prefix_)));
+ DCHECK(!committed_);
+ DCHECK(!locks_.empty());
+ switch (mode) {
+ case LevelDBScopeDeletionMode::kDeferred:
+ case LevelDBScopeDeletionMode::kDeferredWithCompaction:
+ deferred_delete_ranges_.emplace_back(begin.ToString(), end.ToString());
+ break;
+ default:
+ break;
+ }
+#endif
+ bool end_exclusive = true;
+ switch (mode) {
+ case LevelDBScopeDeletionMode::kDeferred:
+ SetModeToUndoLog();
+ AddCleanupDeleteRangeTask(begin.ToString(), end.ToString());
+ return leveldb::Status::OK();
+ case LevelDBScopeDeletionMode::kDeferredWithCompaction:
+ SetModeToUndoLog();
+ AddCleanupDeleteAndCompactRangeTask(begin.ToString(), end.ToString());
+ return leveldb::Status::OK();
+ case LevelDBScopeDeletionMode::kImmediateWithRangeEndExclusive:
+ break;
+ case LevelDBScopeDeletionMode::kImmediateWithRangeEndInclusive:
+ end_exclusive = false;
+ break;
+ }
+ // This method uses its own algorithm to generate the undo log tasks, so
+ // process any existing changes (and generate any needed undo log tasks).
+ leveldb::Status s = WriteChangesAndUndoLog();
+ DCHECK(!s.IsNotFound());
+ if (UNLIKELY(!s.ok() && !s.IsNotFound()))
+ return s;
+ SetModeToUndoLog();
+ leveldb::ReadOptions options;
+ options.verify_checksums = true;
+ // Since these are keys that are being deleted, this should not fill the
+ // block cache (as the data will be immediately stale).
+ options.fill_cache = false;
+ const std::unique_ptr<leveldb::Iterator> it =
+ base::WrapUnique(level_db_->db()->NewIterator(options));
+
+ const leveldb::Comparator* comparator = level_db_->comparator();
+ for (it->Seek(begin);
+ (s = it->status(), s.ok()) && it->Valid() &&
+ IsKeyBeforeEndOfRange(comparator, it->key(), end, end_exclusive);
+ it->Next()) {
+ // Undo log.
+ AddUndoPutTask(it->key().ToString(), it->value().ToString());
+ // Removal.
+ buffer_batch_.Delete(it->key());
+ buffer_batch_empty_ = false;
+ // Make sure our buffer batch isn't getting too big.
+ if (GetMemoryUsage() > write_batch_size_) {
+ s = WriteBufferBatch(false);
+ DCHECK(!s.IsNotFound());
+ if (UNLIKELY(!s.ok() && !s.IsNotFound()))
+ return s;
+ }
+ }
+ if (UNLIKELY(!s.ok() && !s.IsNotFound()))
+ return s;
+ // This could happen if there were no keys found in the range.
+ if (buffer_batch_empty_)
+ return leveldb::Status::OK();
+ return WriteBufferBatch(false);
+}
+
+leveldb::Status LevelDBScope::WriteChangesAndUndoLog() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (buffer_batch_empty_)
+ return leveldb::Status::OK();
+ SetModeToUndoLog();
+
+ leveldb::WriteBatch changes = buffer_batch_;
+ UndoLogWriter undo_writer(this, level_db_->db());
+ changes.Iterate(&undo_writer);
+ changes.Clear();
+
+ return WriteBufferBatch(false);
+}
+
+std::pair<leveldb::Status, LevelDBScope::Mode> LevelDBScope::Commit() {
+ DCHECK(!locks_.empty());
+ leveldb::Status s;
+ switch (mode_) {
+ case Mode::kInMemory:
+ // Don't bother hitting disk if we don't have anything.
+ if (!buffer_batch_empty_)
+ s = WriteBufferBatch(true);
+ break;
+ case Mode::kUndoLogOnDisk:
+ AddCommitPoint();
+ s = WriteChangesAndUndoLog();
+ break;
+ default:
+ NOTREACHED();
+ return std::make_pair(
+ leveldb::Status::NotSupported("Unknown scopes mode."), mode_);
+ }
+ locks_.clear();
+ committed_ = true;
+ return std::make_pair(s, mode_);
+}
+
+void LevelDBScope::AddUndoPutTask(std::string key, std::string value) {
+ DCHECK(undo_task_buffer_.operation_case() ==
+ LevelDBScopesUndoTask::OPERATION_NOT_SET);
+ auto* const put = undo_task_buffer_.mutable_put();
+ put->set_key(std::move(key));
+ put->set_value(std::move(value));
+ AddBufferedUndoTask();
+}
+
+void LevelDBScope::AddUndoDeleteTask(std::string key) {
+ DCHECK(undo_task_buffer_.operation_case() ==
+ LevelDBScopesUndoTask::OPERATION_NOT_SET);
+ auto* const del = undo_task_buffer_.mutable_delete_();
+ del->set_key(std::move(key));
+ AddBufferedUndoTask();
+}
+
+void LevelDBScope::AddUndoDeleteRangeTask(std::string begin, std::string end) {
+ DCHECK(undo_task_buffer_.operation_case() ==
+ LevelDBScopesUndoTask::OPERATION_NOT_SET);
+ auto* const range = undo_task_buffer_.mutable_delete_range();
+ range->set_begin(std::move(begin));
+ range->set_end(std::move(end));
+ AddBufferedUndoTask();
+}
+
+void LevelDBScope::AddBufferedUndoTask() {
+ undo_task_buffer_.SerializeToString(&value_buffer_);
+ buffer_batch_.Put(
+ key_encoder_.UndoTaskKey(prefix_, scope_id_, undo_sequence_number_),
+ value_buffer_);
+ DCHECK_GT(cleanup_sequence_number_, std::numeric_limits<int64_t>::min());
+ --undo_sequence_number_;
+ buffer_batch_empty_ = false;
+ undo_task_buffer_.Clear();
+}
+
+void LevelDBScope::AddCleanupDeleteRangeTask(std::string begin,
+ std::string end) {
+ DCHECK(cleanup_task_buffer_.operation_case() ==
+ LevelDBScopesCleanupTask::OPERATION_NOT_SET);
+ auto* const range = cleanup_task_buffer_.mutable_delete_range();
+ range->set_begin(std::move(begin));
+ range->set_end(std::move(end));
+ AddBufferedCleanupTask();
+}
+
+void LevelDBScope::AddCleanupDeleteAndCompactRangeTask(std::string begin,
+ std::string end) {
+ DCHECK(cleanup_task_buffer_.operation_case() ==
+ LevelDBScopesCleanupTask::OPERATION_NOT_SET);
+ auto* const range = cleanup_task_buffer_.mutable_delete_range_and_compact();
+ range->set_begin(std::move(begin));
+ range->set_end(std::move(end));
+ AddBufferedCleanupTask();
+}
+
+void LevelDBScope::AddBufferedCleanupTask() {
+ cleanup_task_buffer_.SerializeToString(&value_buffer_);
+ buffer_batch_.Put(
+ key_encoder_.CleanupTaskKey(prefix_, scope_id_, cleanup_sequence_number_),
+ value_buffer_);
+ DCHECK_LT(cleanup_sequence_number_, std::numeric_limits<int64_t>::max());
+ ++cleanup_sequence_number_;
+ buffer_batch_empty_ = false;
+ cleanup_task_buffer_.Clear();
+}
+
+void LevelDBScope::SetModeToUndoLog() {
+ if (mode_ == Mode::kUndoLogOnDisk)
+ return;
+ mode_ = Mode::kUndoLogOnDisk;
+
+ LevelDBScopesScopeMetadata metadata;
+ for (ScopeLock& lock : locks_) {
+ auto* lock_proto = metadata.add_locks();
+ lock_proto->set_level(lock.level());
+ auto* range = lock_proto->mutable_range();
+ range->set_begin(lock.range().begin);
+ range->set_end(lock.range().end);
+ }
+ metadata.SerializeToString(&value_buffer_);
+ buffer_batch_.Put(key_encoder_.ScopeMetadataKey(prefix_, scope_id_),
+ value_buffer_);
+ buffer_batch_empty_ = false;
+}
+
+bool LevelDBScope::CanSkipWritingUndoEntry(const leveldb::Slice& key) {
+ const leveldb::Comparator* const comparator = level_db_->comparator();
+ if (key.starts_with(leveldb::Slice(
+ reinterpret_cast<const char*>(prefix_.data()), prefix_.size())))
+ return true;
+ const auto it = std::upper_bound(
+ empty_ranges_.begin(), empty_ranges_.end(), key,
+ [comparator](const leveldb::Slice& key,
+ const std::pair<EmptyRange, bool>& range) {
+ // Compare the key to the end of the range.
+ const EmptyRange& empty_range = range.first;
+ return comparator->Compare(key, empty_range.second) < 0;
+ });
+ // If the key wasn't found (iterator is at the end, or the key is before the
+ // beginning).
+ if (LIKELY(it == empty_ranges_.end() ||
+ comparator->Compare(key, it->first.first) < 0)) {
+ return false;
+ }
+
+ // The key is within an empty range.
+ if (!it->second) {
+ // Only add the delete range once.
+ AddUndoDeleteRangeTask(it->first.first, it->first.second);
+ it->second = true;
+ }
+ return true;
+}
+
+void LevelDBScope::AddCommitPoint() {
+ DCHECK(mode_ == Mode::kUndoLogOnDisk);
+ // Remove the lock ranges from the metadata, which is the 'commit point' and
+ // means that this scope is committed.
+ LevelDBScopesScopeMetadata metadata;
+ metadata.SerializeToString(&value_buffer_);
+ buffer_batch_.Put(key_encoder_.ScopeMetadataKey(prefix_, scope_id_),
+ value_buffer_);
+ buffer_batch_empty_ = false;
+}
+
+leveldb::Status LevelDBScope::WriteBufferBatch(bool sync) {
+ leveldb::WriteOptions write_options;
+ write_options.sync = sync;
+ approximate_bytes_written_ += buffer_batch_.ApproximateSize();
+ leveldb::Status s = level_db_->db()->Write(write_options, &buffer_batch_);
+ // We intentionally clear the write batch, even if the write fails, as this
+ // class is expected to be treated as invalid after a failure and shouldn't be
+ // used.
+ buffer_batch_.Clear();
+ has_written_to_disk_ = true;
+ buffer_batch_empty_ = true;
+ return s;
+}
+
+#if DCHECK_IS_ON()
+bool LevelDBScope::IsRangeEmpty(const EmptyRange& range) {
+ leveldb::ReadOptions read_options;
+ read_options.verify_checksums = true;
+ // This is a debug-only operation, so it shouldn't fill the cache.
+ read_options.fill_cache = false;
+ const std::unique_ptr<leveldb::Iterator> it =
+ base::WrapUnique(level_db_->db()->NewIterator(read_options));
+ leveldb::Status s;
+ const leveldb::Comparator* const comparator = level_db_->comparator();
+ for (it->Seek(range.first);
+ (s = it->status(), s.ok()) && it->Valid() &&
+ IsKeyBeforeEndOfRange(comparator, it->key(), range.second, true);
+ it->Next()) {
+ return false;
+ }
+ return true;
+}
+
+bool LevelDBScope::IsInDeferredDeletionRange(const leveldb::Slice& key) {
+ const leveldb::Comparator* comparator = level_db_->comparator();
+ for (const auto& range : deferred_delete_ranges_) {
+ int beginCompare = comparator->Compare(range.first, key);
+ if (beginCompare > 0)
+ continue;
+ if (beginCompare == 0)
+ return true;
+ int endCompare = comparator->Compare(range.second, key);
+ if (endCompare < 0)
+ continue;
+ return endCompare > 0;
+ }
+ return false;
+}
+
+void LevelDBScope::ValidateEmptyRanges() {
+ for (auto it = empty_ranges_.begin(); it != empty_ranges_.end(); ++it) {
+ auto range = it->first;
+ DCHECK(IsRangeEmpty(range))
+ << "Range [" << range.first << ", " << range.second
+ << ") was reported empty, but keys were found.";
+ auto next_it = it;
+ ++next_it;
+ if (next_it != empty_ranges_.end()) {
+ DCHECK(level_db_->comparator()->Compare(range.second,
+ next_it->first.first) <= 0)
+ << "The |empty_ranges| are not disjoint.";
+ }
+ auto last_it = it;
+ if (last_it != empty_ranges_.begin()) {
+ --last_it;
+ DCHECK(level_db_->comparator()->Compare(last_it->first.second,
+ range.first) <= 0)
+ << "The |empty_ranges| are not disjoint.";
+ }
+ }
+}
+#endif
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/scopes/leveldb_scope.h b/chromium/content/browser/indexed_db/scopes/leveldb_scope.h
new file mode 100644
index 00000000000..e4a00d3df40
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/leveldb_scope.h
@@ -0,0 +1,208 @@
+// 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_INDEXED_DB_SCOPES_LEVELDB_SCOPE_H_
+#define CONTENT_BROWSER_INDEXED_DB_SCOPES_LEVELDB_SCOPE_H_
+
+#include <stdint.h>
+#include <limits>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/containers/flat_map.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/numerics/checked_math.h"
+#include "base/sequence_checker.h"
+#include "content/browser/indexed_db/scopes/leveldb_scope_deletion_mode.h"
+#include "content/browser/indexed_db/scopes/leveldb_scopes_coding.h"
+#include "content/browser/indexed_db/scopes/leveldb_state.h"
+#include "content/browser/indexed_db/scopes/scope_lock.h"
+#include "content/browser/indexed_db/scopes/scopes_metadata.pb.h"
+#include "content/common/content_export.h"
+#include "third_party/leveldatabase/src/include/leveldb/slice.h"
+#include "third_party/leveldatabase/src/include/leveldb/status.h"
+#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
+
+namespace content {
+
+// LevelDBScope is a specialized type of transaction used only for writing data,
+// and is created using the |LevelDBScopes::CreateScope| method.
+// It has optimizations like:
+// * Supporting deferred deletion for ranges that will never be accessed again.
+// This guarantees the data will be deleted, but it will delete it on a
+// different thread sometime in the future.
+// * Storing changes in leveldb instead of in memory, so the user doesn't have
+// to worry about having a set of changes that gets too big.
+// * Not bothering looking up 'undo' optimizations for empty ranges.
+// To support this, the following invariants have to be followed:
+// * The locks the scope was created with should protect it from colliding with
+// modifications by other parties.
+// * The |empty_ranges| the scope was created with are truly empty.
+// * The |empty_ranges| are also disjoints - none of them intersect.
+// * All 'Get' operations in the range/s locked by this scope will first call
+// |WriteChangesAndUndoLog()| so all writes are submitted to LevelDB.
+// * Any ranges deleted with |kDeferred| or |kDeferredWithCompaction| could
+// continue to have the data for a while, so they should never be accessed
+// again.
+//
+// Error handling on |Put|, |Delete*|, and |WriteChangesAndUndoLog|:
+// * After a corruption error (Status::IsCorruption() returns true), all
+// operations on the scope must cease, commit cannot be called, and the whole
+// database state must be wiped.
+// * After an IO error (Status::IsIOError() returns true), all operations on the
+// scope must cease, commit cannot be called, but the scope can attempt to be
+// reverted. If the revert fails for any reason, this is treated as a
+// corruption. A better route is to immediately abort all usage of the leveldb
+// state and close the database. A fresh database open could resolve the IO
+// error.
+//
+// This class is not thread safe, and should be used on the same sequence as
+// |LevelDBScopes::CreateScope|.
+class CONTENT_EXPORT LevelDBScope {
+ public:
+ using RollbackCallback =
+ base::OnceCallback<void(int64_t scope_id, std::vector<ScopeLock> locks)>;
+ using CleanupCallback = base::OnceCallback<void(int64_t scope_id)>;
+
+ ~LevelDBScope();
+
+ int64_t scope_id() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return scope_id_;
+ }
+
+ leveldb::Status Put(const leveldb::Slice& key,
+ const leveldb::Slice& value) WARN_UNUSED_RESULT;
+ leveldb::Status Delete(const leveldb::Slice& key) WARN_UNUSED_RESULT;
+
+ // Deletes the range. |begin| is always inclusive. See
+ // |LevelDBScopeDeletionMode| for the different types of range deletion.
+ leveldb::Status DeleteRange(const leveldb::Slice& begin,
+ const leveldb::Slice& end,
+ LevelDBScopeDeletionMode mode) WARN_UNUSED_RESULT;
+ // Submits pending changes & the undo log to LevelDB. Required to be able to
+ // read any keys that have been submitted to |Put|, |Delete|, or
+ // |DeleteRange|.
+ leveldb::Status WriteChangesAndUndoLog() WARN_UNUSED_RESULT;
+
+ uint64_t GetMemoryUsage() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return buffer_batch_.ApproximateSize();
+ }
+
+ uint64_t GetTransactionSize() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return approximate_bytes_written_.ValueOrDie();
+ }
+
+ private:
+ using EmptyRange = std::pair<std::string, std::string>;
+ friend class LevelDBScopes;
+ class UndoLogWriter;
+
+ struct EmptyRangeLessThan {
+ // This constructor is needed to satisfy the constraints of having default
+ // construction of the |empty_ranges_| flat_map below.
+ EmptyRangeLessThan();
+ EmptyRangeLessThan(const leveldb::Comparator* comparator);
+ EmptyRangeLessThan& operator=(const EmptyRangeLessThan& other);
+
+ // The ranges are expected to be disjoint.
+ bool operator()(const EmptyRange& lhs, const EmptyRange& rhs) const;
+
+ const leveldb::Comparator* comparator_ = nullptr;
+ };
+
+ enum class Mode { kInMemory, kUndoLogOnDisk };
+
+ bool IsUndoLogMode() const { return mode_ == Mode::kUndoLogOnDisk; }
+
+ // In |empty_ranges|, |pair.first| is the inclusive range begin, and
+ // |pair.second| is the exclusive range end.
+ LevelDBScope(int64_t scope_id,
+ std::vector<uint8_t> prefix,
+ size_t write_batch_size,
+ scoped_refptr<LevelDBState> level_db,
+ std::vector<ScopeLock> locks,
+ std::vector<EmptyRange> empty_ranges,
+ RollbackCallback rollback_callback);
+
+ // Called by LevelDBScopes. Saves all data, release all locks, and returns the
+ // status & the mode of this scope. The caller (LevelDBScopes) is expected to
+ // queue up a cleanup task if the mode is kUndoLogOnDisk. This instance should
+ // not be used after this call.
+ std::pair<leveldb::Status, Mode> Commit() WARN_UNUSED_RESULT;
+
+ void AddUndoPutTask(std::string key, std::string value);
+ void AddUndoDeleteTask(std::string key);
+ void AddUndoDeleteRangeTask(std::string begin, std::string end);
+ // Writes the current |undo_task_buffer_| to the |write_batch_|, and
+ // decrements the |undo_sequence_number_|.
+ void AddBufferedUndoTask();
+
+ void AddCleanupDeleteRangeTask(std::string begin, std::string end);
+ void AddCleanupDeleteAndCompactRangeTask(std::string begin, std::string end);
+ // Writes the current |cleanup_task_buffer_| to the |write_batch_|, and
+ // decrements the |cleanup_sequence_number_|.
+ void AddBufferedCleanupTask();
+
+ void SetModeToUndoLog();
+
+ // Returns true if the the given key is either part of the scope metadata
+ // (starts with |prefix_|) or is in a known empty range. If true, then this
+ // key should NOT have an undo entry generated.
+ // On the first match of an empty range, the DELETE_RANGE undo log entry is
+ // written to the buffer_batch_. Since that range is known to be empty, all
+ // keys within it can be reversed by a delete range operation, and only one
+ // delete range per empty range is needed.
+ bool CanSkipWritingUndoEntry(const leveldb::Slice& key);
+
+ void AddCommitPoint();
+ leveldb::Status WriteBufferBatch(bool sync) WARN_UNUSED_RESULT;
+
+#if DCHECK_IS_ON()
+ std::vector<std::pair<std::string, std::string>> deferred_delete_ranges_;
+ bool IsRangeEmpty(const EmptyRange& range);
+ bool IsInDeferredDeletionRange(const leveldb::Slice& key);
+ void ValidateEmptyRanges();
+#endif
+
+ SEQUENCE_CHECKER(sequence_checker_);
+ const int64_t scope_id_;
+ // The undo tasks are written in reverse, as they are executed in ascending
+ // order (and they need to be executed in reverse).
+ int64_t undo_sequence_number_ = leveldb_scopes::kFirstSequenceNumberToWrite;
+ // The cleanup tasks are written in order, and will be executed in the same
+ // order.
+ int64_t cleanup_sequence_number_ = 0ll;
+ Mode mode_ = Mode::kInMemory;
+ const std::vector<uint8_t> prefix_;
+ const size_t write_batch_size_;
+ const scoped_refptr<LevelDBState> level_db_;
+ std::vector<ScopeLock> locks_;
+ base::flat_map<EmptyRange, bool, EmptyRangeLessThan> empty_ranges_;
+ RollbackCallback rollback_callback_;
+
+ leveldb::WriteBatch buffer_batch_;
+ bool buffer_batch_empty_ = true;
+ base::CheckedNumeric<uint64_t> approximate_bytes_written_ = 0;
+ bool has_written_to_disk_ = false;
+ bool committed_ = false;
+
+ LevelDBScopesUndoTask undo_task_buffer_;
+ LevelDBScopesCleanupTask cleanup_task_buffer_;
+ ScopesEncoder key_encoder_;
+ std::string value_buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(LevelDBScope);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_SCOPES_LEVELDB_SCOPE_H_
diff --git a/chromium/content/browser/indexed_db/scopes/leveldb_scope_deletion_mode.h b/chromium/content/browser/indexed_db/scopes/leveldb_scope_deletion_mode.h
new file mode 100644
index 00000000000..d3a3dfefe9e
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/leveldb_scope_deletion_mode.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_INDEXED_DB_SCOPES_LEVELDB_SCOPE_DELETION_MODE_H_
+#define CONTENT_BROWSER_INDEXED_DB_SCOPES_LEVELDB_SCOPE_DELETION_MODE_H_
+
+enum class LevelDBScopeDeletionMode {
+ // The range is deleted immediately.
+ // This mode treats the 'end' of the range as exclusive.
+ kImmediateWithRangeEndExclusive,
+ // The range is deleted immediately, where it will be iterated and deleted.
+ // This mode treats the 'end' of the range as inclusive.
+ kImmediateWithRangeEndInclusive,
+ // The range will be deleted eventually. All future access to this range is
+ // undefined - the data may or may not still exist, even after Chrome
+ // restarts. So only do this for ranges that are known to never be used again.
+ // This mode treats the 'end' of the range as exclusive.
+ kDeferred,
+ // Same as |kDeferred|, except the range will also be compacted afterwards
+ // to further ensure the data is deleted.
+ // This mode treats the 'end' of the range as exclusive.
+ kDeferredWithCompaction
+};
+
+#endif // CONTENT_BROWSER_INDEXED_DB_SCOPES_LEVELDB_SCOPE_DELETION_MODE_H_
diff --git a/chromium/content/browser/indexed_db/scopes/leveldb_scope_unittest.cc b/chromium/content/browser/indexed_db/scopes/leveldb_scope_unittest.cc
new file mode 100644
index 00000000000..b6712331226
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/leveldb_scope_unittest.cc
@@ -0,0 +1,665 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/indexed_db/scopes/leveldb_scopes.h"
+
+#include <limits>
+#include <utility>
+
+#include "base/containers/flat_set.h"
+#include "base/run_loop.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/bind_test_util.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "content/browser/indexed_db/scopes/disjoint_range_lock_manager.h"
+#include "content/browser/indexed_db/scopes/leveldb_scope.h"
+#include "content/browser/indexed_db/scopes/leveldb_scopes.h"
+#include "content/browser/indexed_db/scopes/leveldb_scopes_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/leveldatabase/src/include/leveldb/slice.h"
+
+namespace content {
+namespace {
+
+class LevelDBScopeTest : public LevelDBScopesTestBase {
+ public:
+ LevelDBScopeTest() = default;
+ ~LevelDBScopeTest() override = default;
+
+ std::vector<ScopeLock> AcquireLocksSync(
+ ScopesLockManager* lock_manager,
+ base::flat_set<ScopesLockManager::ScopeLockRequest> lock_requests) {
+ base::RunLoop loop;
+ ScopesLocksHolder locks_receiver;
+ bool success = lock_manager->AcquireLocks(
+ lock_requests, locks_receiver.AsWeakPtr(),
+ base::BindLambdaForTesting([&loop]() { loop.Quit(); }));
+ EXPECT_TRUE(success);
+ if (success)
+ loop.Run();
+ return std::move(locks_receiver.locks);
+ }
+
+ std::string CreateKey(int key_num) {
+ return base::StrCat({base::NumberToString(db_prefix_[0]),
+ base::StringPrintf("%010d", key_num), "key"});
+ }
+
+ std::string CreateLargeValue(int num) {
+ return base::StrCat(
+ {base::StringPrintf("%05d", num), "value", large_string_});
+ }
+};
+
+TEST_F(LevelDBScopeTest, BasicUsage) {
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+
+ leveldb::Status failure_status = leveldb::Status::OK();
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+
+ std::string value = "12345";
+ std::string key = CreateKey(0);
+ s = scope->Put(key, value);
+ EXPECT_TRUE(s.ok());
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+ EXPECT_TRUE(failure_status.ok());
+
+ leveldb::ReadOptions options;
+ options.verify_checksums = true;
+ std::string out;
+ leveldb_->db()->Get(options, CreateKey(0), &out);
+ EXPECT_EQ(out, value);
+}
+
+TEST_F(LevelDBScopeTest, InMemoryAbort) {
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+
+ leveldb::Status failure_status = leveldb::Status::OK();
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+
+ // This change is smaller than 1024 bytes so it should be in-memory.
+ std::string value = "12345";
+ std::string key = CreateKey(0);
+ s = scope->Put(key, value);
+ EXPECT_TRUE(s.ok());
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+
+ // Write over the value and abort.
+ scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+ value = "55555";
+ s = scope->Put(key, value);
+ scope.reset();
+ EXPECT_TRUE(s.ok());
+
+ // Acquire the locks, which should mean that the revert is done.
+ auto locks = AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()});
+ leveldb::ReadOptions options;
+ options.verify_checksums = true;
+ s = leveldb_->db()->Get(options, key, &value);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ("12345", value);
+ EXPECT_TRUE(failure_status.ok());
+}
+
+TEST_F(LevelDBScopeTest, AbortWithRevertTask) {
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+
+ leveldb::Status failure_status = leveldb::Status::OK();
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+
+ std::string value = "12345";
+ leveldb::WriteOptions woptions;
+ s = leveldb_->db()->Put(woptions, CreateKey(0), leveldb::Slice(value));
+
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+
+ // This makes sure the scope goes to disk and writes an undo-log. This forces
+ // it to revert the changes.
+ value = CreateLargeValue(1);
+ for (int i = 0; i < 10; ++i) {
+ std::string key = CreateKey(0);
+ s = scope->Put(key, value);
+ EXPECT_TRUE(s.ok());
+ }
+ scope.reset();
+
+ // Acquire the locks, which should mean that the revert is done.
+ auto locks = AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()});
+ leveldb::ReadOptions options;
+ options.verify_checksums = true;
+ std::string key = CreateKey(0);
+ s = leveldb_->db()->Get(options, key, &value);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ("12345", value);
+ EXPECT_TRUE(failure_status.ok());
+}
+
+TEST_F(LevelDBScopeTest, ManyScopes) {
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+ leveldb::Status failure_status;
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+
+ std::string value;
+ for (int i = 0; i < 20; ++i) {
+ std::string key = CreateKey(i);
+ value = CreateLargeValue(i);
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateExclusiveLock(i)}), {});
+ s = scope->Put(key, value);
+ EXPECT_TRUE(s.ok());
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+ }
+
+ // Wait until cleanup task runs.
+ base::RunLoop loop;
+ scopes.CleanupRunnerForTesting()->PostTask(FROM_HERE, loop.QuitClosure());
+ loop.Run();
+
+ ScopesEncoder encoder;
+ for (int i = 0; i < 20; ++i) {
+ EXPECT_TRUE(
+ IsPrefixedRangeEmptyInDB(encoder.TasksKeyPrefix(metadata_prefix_, i)));
+ }
+ EXPECT_TRUE(
+ IsPrefixedRangeEmptyInDB(encoder.ScopeMetadataPrefix(metadata_prefix_)));
+
+ EXPECT_TRUE(failure_status.ok());
+}
+
+TEST_F(LevelDBScopeTest, DeleteRangeExclusive) {
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+ leveldb::Status failure_status;
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+
+ // Create values for keys 0-20, inclusive.
+ std::string value;
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+ for (int i = 0; i < 21; ++i) {
+ std::string key = CreateKey(i);
+ value = i % 2 == 0 ? CreateLargeValue(i) : "smallvalue";
+ s = scope->Put(key, value);
+ EXPECT_TRUE(s.ok());
+ }
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+
+ // Do a exclusive range delete, so we should not delete 20.
+ scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+ s = scope->DeleteRange(
+ CreateKey(0), CreateKey(20),
+ LevelDBScopeDeletionMode::kImmediateWithRangeEndExclusive);
+ EXPECT_TRUE(s.ok());
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+
+ // Check that keys 0-20 (exclusive) are gone, but 20 still exists.
+ auto locks = AcquireLocksSync(&lock_manager, {CreateSimpleSharedLock()});
+ leveldb::ReadOptions options;
+ options.verify_checksums = true;
+ for (int i = 0; i < 20; ++i) {
+ std::string key = CreateKey(i);
+ s = leveldb_->db()->Get(options, key, &value);
+ EXPECT_TRUE(s.IsNotFound()) << i;
+ }
+ {
+ std::string key = CreateKey(20);
+ s = leveldb_->db()->Get(options, key, &value);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(value, CreateLargeValue(20));
+ }
+ locks.clear();
+}
+
+TEST_F(LevelDBScopeTest, DeleteRangeInclusive) {
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+ leveldb::Status failure_status;
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+
+ // Create values for keys 0-20, inclusive.
+ std::string value;
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+ for (int i = 0; i < 21; ++i) {
+ std::string key = CreateKey(i);
+ value = i % 2 == 0 ? CreateLargeValue(i) : "smallvalue";
+ s = scope->Put(key, value);
+ EXPECT_TRUE(s.ok());
+ }
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+
+ // Do an inclusive delete range, so key 20 should be deleted.
+ scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+ s = scope->DeleteRange(
+ CreateKey(0), CreateKey(20),
+ LevelDBScopeDeletionMode::kImmediateWithRangeEndInclusive);
+ EXPECT_TRUE(s.ok());
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+
+ // Check that keys 0-20 (inclusive) are gone, including 20.
+ auto locks = AcquireLocksSync(&lock_manager, {CreateSimpleSharedLock()});
+ leveldb::ReadOptions options;
+ options.verify_checksums = true;
+ for (int i = 0; i < 21; ++i) {
+ std::string key = CreateKey(i);
+ s = leveldb_->db()->Get(options, key, &value);
+ EXPECT_TRUE(s.IsNotFound()) << i;
+ }
+ locks.clear();
+}
+
+TEST_F(LevelDBScopeTest, DeleteRangeDeferred) {
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+ leveldb::Status failure_status;
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+
+ std::string value;
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+ for (int i = 0; i < 20; ++i) {
+ std::string key = CreateKey(i);
+ value = i % 2 == 0 ? CreateLargeValue(i) : "smallvalue";
+ s = scope->Put(key, value);
+ EXPECT_TRUE(s.ok());
+ }
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+
+ scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+ s = scope->DeleteRange(CreateKey(0), CreateKey(20),
+ LevelDBScopeDeletionMode::kDeferred);
+ EXPECT_TRUE(s.ok());
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+
+ // Wait until cleanup task runs.
+ base::RunLoop loop;
+ scopes.CleanupRunnerForTesting()->PostTask(FROM_HERE, loop.QuitClosure());
+ loop.Run();
+
+ // Be a good citizen and acquire read locks.
+ auto locks = AcquireLocksSync(&lock_manager, {CreateSimpleSharedLock()});
+ leveldb::ReadOptions options;
+ options.verify_checksums = true;
+ for (int i = 0; i < 20; ++i) {
+ std::string key = CreateKey(i);
+ s = leveldb_->db()->Get(options, key, &value);
+ EXPECT_TRUE(s.IsNotFound()) << i;
+ }
+ EXPECT_TRUE(failure_status.ok());
+}
+
+TEST_F(LevelDBScopeTest, DeleteRangeCompact) {
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+ leveldb::Status failure_status;
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+
+ std::string value;
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+ for (int i = 0; i < 20; ++i) {
+ std::string key = CreateKey(i);
+ value = i % 2 == 0 ? CreateLargeValue(i) : "smallvalue";
+ s = scope->Put(key, value);
+ EXPECT_TRUE(s.ok());
+ }
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+
+ scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+ s = scope->DeleteRange(CreateKey(0), CreateKey(20),
+ LevelDBScopeDeletionMode::kDeferredWithCompaction);
+ EXPECT_TRUE(s.ok());
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+
+ // Wait until cleanup task runs.
+ base::RunLoop loop;
+ scopes.CleanupRunnerForTesting()->PostTask(FROM_HERE, loop.QuitClosure());
+ loop.Run();
+
+ // Be a good citizen and acquire read locks.
+ auto locks = AcquireLocksSync(&lock_manager, {CreateSimpleSharedLock()});
+ leveldb::ReadOptions options;
+ options.verify_checksums = true;
+ for (int i = 0; i < 20; ++i) {
+ std::string key = CreateKey(i);
+ s = leveldb_->db()->Get(options, key, &value);
+ EXPECT_TRUE(s.IsNotFound()) << i;
+ }
+ EXPECT_TRUE(failure_status.ok());
+}
+
+TEST_F(LevelDBScopeTest, RevertWithDeferredDelete) {
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+ leveldb::Status failure_status;
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+
+ // This test makes sure that the cleanup scheduled after the revert doesn't
+ // execute it's cleanup tasks.
+
+ // Populate the database.
+ std::string value;
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+ for (int i = 0; i < 20; ++i) {
+ std::string key = CreateKey(i);
+ value = i % 2 == 0 ? CreateLargeValue(i) : "smallvalue";
+ s = scope->Put(key, value);
+ EXPECT_TRUE(s.ok());
+ }
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+
+ // Do a deferred delete & a write large enough to make this a log-based scope,
+ // and then revert it.
+ scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+ value = CreateLargeValue(20);
+ s = scope->Put(CreateKey(20), value);
+ s = scope->DeleteRange(CreateKey(0), CreateKey(20),
+ LevelDBScopeDeletionMode::kDeferred);
+ EXPECT_TRUE(s.ok());
+ scope.reset();
+
+ // Wait until revert runner runs.
+ {
+ base::RunLoop loop;
+ scopes.RevertRunnerForTesting()->PostTask(FROM_HERE, loop.QuitClosure());
+ loop.Run();
+ }
+
+ // Wait until cleanup runner runs.
+ {
+ base::RunLoop loop;
+ scopes.CleanupRunnerForTesting()->PostTask(FROM_HERE, loop.QuitClosure());
+ loop.Run();
+ }
+
+ // If the cleanup correctly ignored the tasks, then the values should still
+ // exist.
+
+ auto locks = AcquireLocksSync(&lock_manager, {CreateSimpleSharedLock()});
+ leveldb::ReadOptions options;
+ options.verify_checksums = true;
+ for (int i = 0; i < 20; ++i) {
+ std::string key = CreateKey(i);
+ s = leveldb_->db()->Get(options, key, &value);
+ EXPECT_TRUE(s.ok()) << i;
+ }
+ s = leveldb_->db()->Get(options, CreateKey(20), &value);
+ EXPECT_TRUE(s.IsNotFound());
+ EXPECT_TRUE(failure_status.ok());
+}
+
+TEST_F(LevelDBScopeTest, EmptyRangeRevert) {
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+ leveldb::Status failure_status = leveldb::Status::OK();
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ std::vector<std::pair<std::string, std::string>> empty_ranges = {
+ std::make_pair(CreateKey(0), CreateKey(10)),
+ std::make_pair(CreateKey(30), CreateKey(50))};
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}),
+ std::move(empty_ranges));
+
+ // Use a large value to ensure we are in a undo log state.
+ std::string value = CreateLargeValue(0);
+ s = scope->Put(CreateKey(0), value);
+ EXPECT_TRUE(s.ok());
+ s = scope->Put(CreateKey(1), value);
+ EXPECT_TRUE(s.ok());
+ s = scope->Put(CreateKey(11), value);
+ EXPECT_TRUE(s.ok());
+ scope.reset();
+ EXPECT_TRUE(s.ok());
+ EXPECT_TRUE(failure_status.ok());
+
+ auto locks = AcquireLocksSync(&lock_manager, {CreateSimpleSharedLock()});
+ leveldb::ReadOptions options;
+ options.verify_checksums = true;
+ std::string out;
+ s = leveldb_->db()->Get(options, CreateKey(0), &out);
+ EXPECT_TRUE(s.IsNotFound());
+}
+
+TEST_F(LevelDBScopeTest, BrokenDBForInitialize) {
+ leveldb::Status error = leveldb::Status::IOError("test");
+ leveldb_ =
+ indexed_db::FakeLevelDBFactory::GetBrokenLevelDB(error, base::FilePath());
+ DisjointRangeLockManager lock_manager(3);
+
+ leveldb::Status failure_status = leveldb::Status::OK();
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_FALSE(s.ok());
+ EXPECT_EQ(s.ToString(), error.ToString());
+}
+
+TEST_F(LevelDBScopeTest, BrokenDBForCommit) {
+ base::OnceCallback<void(leveldb::Status)> break_db;
+ SetUpBreakableDB(&break_db);
+ DisjointRangeLockManager lock_manager(3);
+
+ leveldb::Status failure_status = leveldb::Status::OK();
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+
+ leveldb::Status error = leveldb::Status::IOError("test");
+ std::move(break_db).Run(error);
+ std::string value = "12345";
+ std::string key = CreateKey(0);
+ s = scope->Put(key, value);
+ EXPECT_TRUE(s.ok());
+ s = scopes.Commit(std::move(scope));
+ EXPECT_EQ(s.ToString(), error.ToString());
+ EXPECT_TRUE(failure_status.ok());
+}
+
+TEST_F(LevelDBScopeTest, BrokenDBForCleanup) {
+ base::OnceCallback<void(leveldb::Status)> break_db;
+ SetUpBreakableDB(&break_db);
+ DisjointRangeLockManager lock_manager(3);
+
+ leveldb::Status failure_status = leveldb::Status::OK();
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+
+ leveldb::Status error = leveldb::Status::IOError("test");
+ std::string value = CreateLargeValue(0);
+ std::string key = CreateKey(0);
+ s = scope->Put(key, value);
+ EXPECT_TRUE(s.ok());
+ s = scopes.Commit(std::move(scope));
+ // Break the database, which should hopefully effect the cleanup task.
+ std::move(break_db).Run(error);
+ EXPECT_TRUE(s.ok());
+
+ // Wait until cleanup task runs.
+ base::RunLoop loop;
+ scopes.CleanupRunnerForTesting()->PostTask(FROM_HERE, loop.QuitClosure());
+ loop.Run();
+
+ EXPECT_FALSE(failure_status.ok());
+ EXPECT_EQ(failure_status.ToString(), error.ToString());
+}
+
+TEST_F(LevelDBScopeTest, BrokenDBForRevert) {
+ base::OnceCallback<void(leveldb::Status)> break_db;
+ SetUpBreakableDB(&break_db);
+ DisjointRangeLockManager lock_manager(3);
+
+ leveldb::Status failure_status = leveldb::Status::OK();
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+
+ leveldb::Status error = leveldb::Status::IOError("test");
+ std::string value = CreateLargeValue(0);
+ std::string key = CreateKey(0);
+ s = scope->Put(key, value);
+ EXPECT_TRUE(s.ok());
+ std::move(break_db).Run(error);
+ scope.reset();
+
+ // Wait until revert task runs.
+ base::RunLoop loop;
+ scopes.RevertRunnerForTesting()->PostTask(FROM_HERE, loop.QuitClosure());
+ loop.Run();
+
+ EXPECT_FALSE(failure_status.ok());
+ EXPECT_EQ(failure_status.ToString(), error.ToString());
+}
+
+TEST_F(LevelDBScopeTest, DeleteNonExistentRangeDoesNotWrite) {
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+
+ leveldb::Status failure_status = leveldb::Status::OK();
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_status](leveldb::Status s) { failure_status = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+
+ auto scope = scopes.CreateScope(
+ AcquireLocksSync(&lock_manager, {CreateSimpleExclusiveLock()}), {});
+
+ s = scope->DeleteRange(
+ "b1", "b2", LevelDBScopeDeletionMode::kImmediateWithRangeEndInclusive);
+ EXPECT_TRUE(s.ok());
+ s = scopes.Commit(std::move(scope));
+ EXPECT_TRUE(s.ok());
+ EXPECT_TRUE(failure_status.ok());
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/scopes/leveldb_scopes.cc b/chromium/content/browser/indexed_db/scopes/leveldb_scopes.cc
new file mode 100644
index 00000000000..bd5ea14e7d5
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/leveldb_scopes.cc
@@ -0,0 +1,290 @@
+// 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/indexed_db/scopes/leveldb_scopes.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/barrier_closure.h"
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ptr_util.h"
+#include "base/optional.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/task_runner_util.h"
+#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
+#include "content/browser/indexed_db/scopes/leveldb_scope.h"
+#include "content/browser/indexed_db/scopes/leveldb_scopes_coding.h"
+#include "content/browser/indexed_db/scopes/leveldb_scopes_tasks.h"
+#include "content/browser/indexed_db/scopes/scopes_lock_manager.h"
+#include "content/browser/indexed_db/scopes/scopes_metadata.pb.h"
+
+namespace content {
+
+LevelDBScopes::LevelDBScopes(std::vector<uint8_t> metadata_key_prefix,
+ size_t max_write_batch_size,
+ scoped_refptr<LevelDBState> level_db,
+ ScopesLockManager* lock_manager,
+ FailureCallback failure_callback)
+ : metadata_key_prefix_(std::move(metadata_key_prefix)),
+ max_write_batch_size_bytes_(max_write_batch_size),
+ level_db_(std::move(level_db)),
+ lock_manager_(lock_manager),
+ failure_callback_(std::move(failure_callback)),
+ weak_factory_(this) {}
+
+LevelDBScopes::~LevelDBScopes() = default;
+
+leveldb::Status LevelDBScopes::Initialize() {
+#if DCHECK_IS_ON()
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!initialize_called_) << "Initialize() already called";
+ initialize_called_ = true;
+#endif // DCHECK_IS_ON()
+
+ leveldb::ReadOptions read_options;
+ read_options.fill_cache = true;
+ read_options.verify_checksums = true;
+ leveldb::WriteOptions write_options;
+ write_options.sync = false;
+ ScopesEncoder key_encoder;
+ leveldb::Status s;
+
+ // This method loads the global metadata, reads in all of the scopes still on
+ // disk, and stores their information for later cleanup or reverting. For all
+ // reverting scopes, the appropriate locks are acquired now.
+
+ // Step 1 - Load & initialize global metadata.
+ std::string metadata_value;
+ leveldb::Slice metadata_key =
+ key_encoder.GlobalMetadataKey(metadata_key_prefix_);
+ s = level_db_->db()->Get(read_options, metadata_key, &metadata_value);
+ if (UNLIKELY(!s.ok() && !s.IsNotFound()))
+ return s;
+
+ LevelDBScopesMetadata metadata;
+ if (s.IsNotFound()) {
+ metadata.set_version(leveldb_scopes::kCurrentVersion);
+ // This is the only 'write' operation that is done in this method, so a
+ // leveldb::WriteBatch isn't necessary.
+ s = level_db_->db()->Put(write_options, metadata_key,
+ metadata.SerializeAsString());
+ if (UNLIKELY(!s.ok()))
+ return s;
+ } else {
+ if (!metadata.ParseFromString(metadata_value)) {
+ return leveldb::Status::Corruption(
+ "Could not parse LevelDBScopes Metadata.");
+ }
+ if (metadata.version() < leveldb_scopes::kMinSupportedVersion ||
+ metadata.version() > leveldb_scopes::kCurrentVersion) {
+ return leveldb::Status::Corruption(
+ base::StrCat({"Unsupported scopes metadata version ",
+ base::NumberToString(metadata.version())}));
+ }
+ }
+
+ // Step 2 - Load scopes metadata & queue up revert or cleanup tasks, to be run
+ // when StartRecoveryAndCleanupTasks() is called. All locks for the revert
+ // tasks are acquired now.
+
+ DCHECK(startup_scopes_to_clean_.empty());
+ DCHECK(startup_scopes_to_revert_.empty());
+ const std::unique_ptr<leveldb::Iterator> iterator =
+ base::WrapUnique(level_db_->db()->NewIterator(read_options));
+ leveldb::Slice prefix_key =
+ key_encoder.ScopeMetadataPrefix(metadata_key_prefix_);
+ iterator->Seek(prefix_key);
+ LevelDBScopesScopeMetadata scope_metadata;
+ for (; iterator->Valid() && iterator->key().starts_with(prefix_key);
+ iterator->Next()) {
+ // Parse the key & value.
+ int64_t scope_id;
+ bool success;
+ std::tie(success, scope_id) = leveldb_scopes::ParseScopeMetadataId(
+ iterator->key(), metadata_key_prefix_);
+ if (UNLIKELY(!success)) {
+ return leveldb::Status::Corruption(base::StrCat(
+ {"Could not read scope metadata key: ", iterator->key().ToString()}));
+ }
+ if (UNLIKELY(!scope_metadata.ParseFromArray(iterator->value().data(),
+ iterator->value().size()))) {
+ return leveldb::Status::Corruption(base::StrCat(
+ {"Could not parse scope value key: ", iterator->value().ToString()}));
+ }
+
+ // The 'commit point' is not having any lock ranges in scope_metadata. If
+ // lock ranges aren't present then it was committed, and the scope only
+ // needs to be cleaned up.
+ if (LIKELY(scope_metadata.locks_size() == 0)) {
+ startup_scopes_to_clean_.emplace_back(
+ scope_id, scope_metadata.ignore_cleanup_tasks()
+ ? StartupCleanupType::kIgnoreCleanupTasks
+ : StartupCleanupType::kExecuteCleanupTasks);
+ continue;
+ }
+
+ // The commit point isn't there, so that scope needs to be reverted.
+ // Acquire all locks necessary to undo the scope to prevent user-created
+ // scopes for reading or writing changes that will be undone.
+ ScopeLockRange range;
+ base::flat_set<ScopesLockManager::ScopeLockRequest> lock_requests;
+ lock_requests.reserve(scope_metadata.locks().size());
+ for (const auto& lock : scope_metadata.locks()) {
+ range.begin = lock.range().begin();
+ range.end = lock.range().end();
+ lock_requests.emplace(lock.level(), range,
+ ScopesLockManager::LockType::kExclusive);
+ }
+ ScopesLocksHolder receiver;
+ bool locks_acquired = lock_manager_->AcquireLocks(
+ std::move(lock_requests), receiver.weak_factory.GetWeakPtr(),
+ base::DoNothing());
+ if (UNLIKELY(!locks_acquired))
+ return leveldb::Status::Corruption("Invalid locks on disk.");
+
+ // AcquireLocks should grant the locks synchronously because
+ // 1. There should be no locks acquired before calling this method, and
+ // 2. All locks that were are being loaded from disk were previously 'held'
+ // by this system. If they conflict, this is an invalid state on disk.
+ if (UNLIKELY(receiver.locks.empty()))
+ return leveldb::Status::Corruption("Invalid lock ranges on disk.");
+
+ startup_scopes_to_revert_.emplace_back(scope_id, std::move(receiver.locks));
+ }
+ if (LIKELY(iterator->status().ok()))
+ recovery_finished_ = true;
+ return s;
+}
+
+void LevelDBScopes::StartRecoveryAndCleanupTasks() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!revert_runner_) << "StartRecoveryAndCleanupTasks() already called.";
+ DCHECK(!cleanup_runner_);
+
+ // There are many choices for how to run these tasks. They technically could
+ // be done on a threadpool, where each task is in its own thread. Because both
+ // of these task types are triggered by the code on a webpage, it is dangerous
+ // to let them completely fill up a threadpool.
+ // The cleanup tasks are imporatant to run because they will result in disk
+ // space shrinkage, especially when they have compaction tasks. This effects
+ // the webpage quota.
+ // The revert tasks are very important because they still hold a lock to that
+ // object store or database. This can completely block website database
+ // operations from happening.
+ // The compromise here is:
+ // It is OK to mark these priorities as somewhat high(blocking and visible)
+ // as long as each task type only uses one sequence. This makes sure that the
+ // tasks cannot monopolize the entire thread pool, and that they will be run
+ // reasonably soon.
+
+ // Create the revert runner first, and schedule all pending revert tasks ASAP.
+ revert_runner_ = base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::WithBaseSyncPrimitives(),
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+ base::TaskPriority::USER_BLOCKING});
+ for (StartupScopeToRevert& revert_scope_data : startup_scopes_to_revert_) {
+ Rollback(revert_scope_data.first, std::move(revert_scope_data.second));
+ }
+ startup_scopes_to_revert_.clear();
+
+ // Create the cleanup runner and schedule all committed scopes to be cleaned
+ // up.
+ cleanup_runner_ = base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::WithBaseSyncPrimitives(),
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+ base::TaskPriority::USER_VISIBLE});
+ for (auto& cleanup_scope_data : startup_scopes_to_clean_) {
+ auto cleanup_task = std::make_unique<CleanupScopeTask>(
+ level_db_, metadata_key_prefix_, cleanup_scope_data.first,
+ cleanup_scope_data.second == StartupCleanupType::kExecuteCleanupTasks
+ ? CleanupScopeTask::CleanupMode::kExecuteCleanupTasks
+ : CleanupScopeTask::CleanupMode::kIgnoreCleanupTasks,
+ max_write_batch_size_bytes_);
+ base::PostTaskAndReplyWithResult(
+ cleanup_runner_.get(), FROM_HERE,
+ base::BindOnce(&CleanupScopeTask::Run, std::move(cleanup_task)),
+ base::BindOnce(&LevelDBScopes::OnCleanupTaskResult,
+ weak_factory_.GetWeakPtr()));
+ }
+ startup_scopes_to_clean_.clear();
+}
+
+std::unique_ptr<LevelDBScope> LevelDBScopes::CreateScope(
+ std::vector<ScopeLock> locks,
+ std::vector<std::pair<std::string, std::string>> empty_ranges) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(recovery_finished_);
+ int scope_id = next_scope_id_;
+ ++next_scope_id_;
+ return base::WrapUnique(new LevelDBScope(
+ scope_id, metadata_key_prefix_, max_write_batch_size_bytes_, level_db_,
+ std::move(locks), std::move(empty_ranges),
+ base::BindOnce(&LevelDBScopes::Rollback, weak_factory_.GetWeakPtr())));
+}
+
+leveldb::Status LevelDBScopes::Commit(std::unique_ptr<LevelDBScope> scope) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(recovery_finished_);
+ DCHECK(cleanup_runner_);
+ LevelDBScope::Mode scopes_mode;
+ leveldb::Status s;
+ std::tie(s, scopes_mode) = scope->Commit();
+ if (scopes_mode == LevelDBScope::Mode::kUndoLogOnDisk) {
+ auto task = std::make_unique<CleanupScopeTask>(
+ level_db_, metadata_key_prefix_, scope->scope_id(),
+ CleanupScopeTask::CleanupMode::kExecuteCleanupTasks,
+ max_write_batch_size_bytes_);
+ base::PostTaskAndReplyWithResult(
+ cleanup_runner_.get(), FROM_HERE,
+ base::BindOnce(&CleanupScopeTask::Run, std::move(task)),
+ base::BindOnce(&LevelDBScopes::OnCleanupTaskResult,
+ weak_factory_.GetWeakPtr()));
+ }
+ return s;
+}
+
+void LevelDBScopes::Rollback(int64_t scope_id, std::vector<ScopeLock> locks) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(revert_runner_);
+ auto task = std::make_unique<RevertScopeTask>(
+ level_db_, metadata_key_prefix_, scope_id, max_write_batch_size_bytes_);
+ base::PostTaskAndReplyWithResult(
+ revert_runner_.get(), FROM_HERE,
+ base::BindOnce(&RevertScopeTask::Run, std::move(task)),
+ base::BindOnce(&LevelDBScopes::OnRevertTaskResult,
+ weak_factory_.GetWeakPtr(), scope_id, std::move(locks)));
+}
+
+void LevelDBScopes::OnCleanupTaskResult(leveldb::Status result) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (UNLIKELY(!result.ok()))
+ failure_callback_.Run(result);
+}
+
+void LevelDBScopes::OnRevertTaskResult(int64_t scope_id,
+ std::vector<ScopeLock> locks,
+ leveldb::Status result) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (UNLIKELY(!result.ok())) {
+ failure_callback_.Run(result);
+ return;
+ }
+ auto task = std::make_unique<CleanupScopeTask>(
+ level_db_, metadata_key_prefix_, scope_id,
+ CleanupScopeTask::CleanupMode::kIgnoreCleanupTasks,
+ max_write_batch_size_bytes_);
+ base::PostTaskAndReplyWithResult(
+ cleanup_runner_.get(), FROM_HERE,
+ base::BindOnce(&CleanupScopeTask::Run, std::move(task)),
+ base::BindOnce(&LevelDBScopes::OnCleanupTaskResult,
+ weak_factory_.GetWeakPtr()));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/scopes/leveldb_scopes.h b/chromium/content/browser/indexed_db/scopes/leveldb_scopes.h
new file mode 100644
index 00000000000..433ba638485
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/leveldb_scopes.h
@@ -0,0 +1,133 @@
+// 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_INDEXED_DB_SCOPES_LEVELDB_SCOPES_H_
+#define CONTENT_BROWSER_INDEXED_DB_SCOPES_LEVELDB_SCOPES_H_
+
+#include <stdint.h>
+#include <limits>
+#include <list>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/numerics/checked_math.h"
+#include "base/sequence_checker.h"
+#include "base/sequenced_task_runner.h"
+#include "content/browser/indexed_db/scopes/leveldb_scopes_coding.h"
+#include "content/browser/indexed_db/scopes/leveldb_state.h"
+#include "content/browser/indexed_db/scopes/scope_lock.h"
+#include "content/browser/indexed_db/scopes/scope_lock_range.h"
+#include "content/common/content_export.h"
+#include "third_party/leveldatabase/src/include/leveldb/comparator.h"
+#include "third_party/leveldatabase/src/include/leveldb/db.h"
+#include "third_party/leveldatabase/src/include/leveldb/iterator.h"
+#include "third_party/leveldatabase/src/include/leveldb/slice.h"
+#include "third_party/leveldatabase/src/include/leveldb/status.h"
+#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
+
+namespace content {
+class LevelDBScope;
+class ScopesLockManager;
+
+class CONTENT_EXPORT LevelDBScopes {
+ public:
+ using FailureCallback = base::RepeatingCallback<void(leveldb::Status)>;
+ static constexpr const size_t kDefaultMaxWriteBatchSizeBytes = 1024 * 1024;
+
+ // |lock_manager| is expected to be alive during the lifetime of this class.
+ // |failure_callback| will not be called after the destruction of this class.
+ LevelDBScopes(std::vector<uint8_t> metadata_key_prefix,
+ size_t max_write_batch_size_bytes_bytes,
+ scoped_refptr<LevelDBState> level_db,
+ ScopesLockManager* lock_manager,
+ FailureCallback failure_callback);
+ ~LevelDBScopes();
+
+ // This method needs to be called before any other method on this class. If
+ // unsuccessful, the class cannot be used. Note, this will acquire locks for
+ // the revert tasks if necessary.
+ leveldb::Status Initialize();
+
+ // This starts the task runners associated with aborting and cleaning up
+ // previous logs, and runs any pending cleanup or revert tasks.
+ void StartRecoveryAndCleanupTasks();
+
+ // In |empty_ranges|, |pair.first| is the inclusive range begin, and
+ // |pair.end| is the exclusive range end. The ranges must be disjoint (they
+ // cannot overlap).
+ std::unique_ptr<LevelDBScope> CreateScope(
+ std::vector<ScopeLock> locks,
+ std::vector<std::pair<std::string, std::string>> empty_ranges);
+
+ leveldb::Status Commit(std::unique_ptr<LevelDBScope> scope);
+
+ base::SequencedTaskRunner* RevertRunnerForTesting() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return revert_runner_.get();
+ }
+
+ base::SequencedTaskRunner* CleanupRunnerForTesting() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return cleanup_runner_.get();
+ }
+
+ private:
+ enum class StartupCleanupType { kExecuteCleanupTasks, kIgnoreCleanupTasks };
+ using StartupScopeToRevert = std::pair<int64_t, std::vector<ScopeLock>>;
+ using StartupScopeToCleanup = std::pair<int64_t, StartupCleanupType>;
+ using RecoveryLocksList = std::list<std::vector<ScopeLock>>;
+
+ leveldb::Status InitializeGlobalMetadata(
+ const leveldb::ReadOptions& read_options,
+ const leveldb::WriteOptions& write_options);
+ leveldb::Status InitializeScopesAndTasks(
+ const leveldb::ReadOptions& read_options,
+ const leveldb::WriteOptions& write_options);
+
+ void Rollback(int64_t scope_id, std::vector<ScopeLock> locks);
+
+ void OnCleanupTaskResult(leveldb::Status result);
+
+ void StartRevertTask(int64_t scope_id, std::vector<ScopeLock> locks);
+
+ void OnRevertTaskResult(int64_t scope_id,
+ std::vector<ScopeLock> locks,
+ leveldb::Status result);
+
+ SEQUENCE_CHECKER(sequence_checker_);
+ const std::vector<uint8_t> metadata_key_prefix_;
+ const size_t max_write_batch_size_bytes_;
+ std::vector<StartupScopeToCleanup> startup_scopes_to_clean_;
+ std::vector<StartupScopeToRevert> startup_scopes_to_revert_;
+ scoped_refptr<base::SequencedTaskRunner> revert_runner_;
+ scoped_refptr<base::SequencedTaskRunner> cleanup_runner_;
+
+ // This gets set to |true| when |Initialize()| succeeds.
+ bool recovery_finished_ = false;
+ int next_scope_id_ = 0;
+ scoped_refptr<LevelDBState> level_db_;
+ // The |lock_manager_| is expected to outlive this class.
+ ScopesLockManager* lock_manager_;
+ FailureCallback failure_callback_;
+
+#if DCHECK_IS_ON()
+ bool initialize_called_ = false;
+#endif
+
+ base::WeakPtrFactory<LevelDBScopes> weak_factory_;
+ DISALLOW_COPY_AND_ASSIGN(LevelDBScopes);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_SCOPES_LEVELDB_SCOPES_H_
diff --git a/chromium/content/browser/indexed_db/scopes/leveldb_scopes_factory.cc b/chromium/content/browser/indexed_db/scopes/leveldb_scopes_factory.cc
new file mode 100644
index 00000000000..aac8b0a5030
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/leveldb_scopes_factory.cc
@@ -0,0 +1,32 @@
+// 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/indexed_db/scopes/leveldb_scopes_factory.h"
+
+#include <utility>
+
+#include "content/browser/indexed_db/scopes/leveldb_scopes.h"
+
+namespace content {
+
+LevelDBScopesOptions::LevelDBScopesOptions() = default;
+LevelDBScopesOptions::~LevelDBScopesOptions() = default;
+LevelDBScopesOptions::LevelDBScopesOptions(LevelDBScopesOptions&&) noexcept =
+ default;
+LevelDBScopesOptions& LevelDBScopesOptions::operator=(
+ LevelDBScopesOptions&&) noexcept = default;
+
+std::tuple<std::unique_ptr<LevelDBScopes>, leveldb::Status>
+DefaultLevelDBScopesFactory::CreateAndInitializeLevelDBScopes(
+ LevelDBScopesOptions options,
+ scoped_refptr<LevelDBState> level_db) {
+ std::unique_ptr<LevelDBScopes> scopes = std::make_unique<LevelDBScopes>(
+ std::move(options.metadata_key_prefix), options.max_write_batch_size,
+ std::move(level_db), options.lock_manager,
+ std::move(options.failure_callback));
+ leveldb::Status s = scopes->Initialize();
+ return {s.ok() ? std::move(scopes) : nullptr, s};
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/scopes/leveldb_scopes_factory.h b/chromium/content/browser/indexed_db/scopes/leveldb_scopes_factory.h
new file mode 100644
index 00000000000..c12ceceea2b
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/leveldb_scopes_factory.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_INDEXED_DB_SCOPES_LEVELDB_SCOPES_FACTORY_H_
+#define CONTENT_BROWSER_INDEXED_DB_SCOPES_LEVELDB_SCOPES_FACTORY_H_
+
+#include <stdint.h>
+#include <memory>
+#include <tuple>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "third_party/leveldatabase/src/include/leveldb/status.h"
+
+namespace content {
+
+class LevelDBScopes;
+class LevelDBState;
+class ScopesLockManager;
+
+struct LevelDBScopesOptions {
+ LevelDBScopesOptions();
+ ~LevelDBScopesOptions();
+ LevelDBScopesOptions(LevelDBScopesOptions&&) noexcept;
+ LevelDBScopesOptions& operator=(LevelDBScopesOptions&&) noexcept;
+
+ std::vector<uint8_t> metadata_key_prefix;
+ size_t max_write_batch_size = 1 * 1024 * 1024;
+ ScopesLockManager* lock_manager;
+ base::RepeatingCallback<void(leveldb::Status)> failure_callback;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LevelDBScopesOptions);
+};
+
+// The user must still call |StartTaskRunners| on the LevelDBScopes object after
+// calling |OpenLevelDBScopes|.
+class LevelDBScopesFactory {
+ public:
+ virtual ~LevelDBScopesFactory() = default;
+ virtual std::tuple<std::unique_ptr<LevelDBScopes>, leveldb::Status>
+ CreateAndInitializeLevelDBScopes(LevelDBScopesOptions options,
+ scoped_refptr<LevelDBState> level_db) = 0;
+};
+
+class DefaultLevelDBScopesFactory : public LevelDBScopesFactory {
+ public:
+ ~DefaultLevelDBScopesFactory() override = default;
+ std::tuple<std::unique_ptr<LevelDBScopes>, leveldb::Status>
+ CreateAndInitializeLevelDBScopes(
+ LevelDBScopesOptions options,
+ scoped_refptr<LevelDBState> level_db) override;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_SCOPES_LEVELDB_SCOPES_FACTORY_H_
diff --git a/chromium/content/browser/indexed_db/scopes/leveldb_scopes_unittest.cc b/chromium/content/browser/indexed_db/scopes/leveldb_scopes_unittest.cc
new file mode 100644
index 00000000000..3e8b573dba7
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/leveldb_scopes_unittest.cc
@@ -0,0 +1,154 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/indexed_db/scopes/leveldb_scopes.h"
+
+#include <limits>
+#include <utility>
+
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "content/browser/indexed_db/scopes/disjoint_range_lock_manager.h"
+#include "content/browser/indexed_db/scopes/leveldb_scopes.h"
+#include "content/browser/indexed_db/scopes/leveldb_scopes_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/leveldatabase/src/include/leveldb/slice.h"
+
+namespace content {
+namespace {
+
+class LevelDBScopesStartupTest : public LevelDBScopesTestBase {
+ public:
+ LevelDBScopesStartupTest() = default;
+ ~LevelDBScopesStartupTest() override = default;
+};
+
+TEST_F(LevelDBScopesStartupTest, CleanupOnRecovery) {
+ const int64_t kScopeToCleanUp = 19;
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+ WriteScopesMetadata(kScopeToCleanUp, true);
+
+ leveldb::Status failure_callback = leveldb::Status::OK();
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_callback](leveldb::Status s) { failure_callback = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+ scopes.StartRecoveryAndCleanupTasks();
+
+ // Wait until cleanup task runs.
+ base::RunLoop loop;
+ scopes.CleanupRunnerForTesting()->PostTask(FROM_HERE, loop.QuitClosure());
+ loop.Run();
+
+ EXPECT_TRUE(IsScopeCleanedUp(kScopeToCleanUp));
+ EXPECT_FALSE(ScopeDataExistsOnDisk());
+
+ EXPECT_TRUE(failure_callback.ok());
+}
+
+TEST_F(LevelDBScopesStartupTest, RevertWithLocksOnRecoveryWithNoCleanup) {
+ const int64_t kScopeToResumeRevert = 19;
+ const std::string kUndoPutKey = "b10";
+ const std::string kUndoPutValue = "abc";
+ const std::string kCleanupDeleteRangeBegin = "b1";
+ const std::string kKeyWithinCleanupDeleteRange = "b2";
+ const std::string kCleanupDeleteRangeEnd = "b3";
+ SetUpRealDatabase();
+ DisjointRangeLockManager lock_manager(3);
+
+ // Tests that the revert execution on startup is performed correctly. This
+ // includes:
+ // * The revert task is executed & a value is written to disk,
+ // * The cleanup task is executed & deletes the scope metadata, but does not
+ // execute the cleanup tasks.
+
+ metadata_buffer_.mutable_locks()->Add();
+ metadata_buffer_.mutable_locks()->Mutable(0)->set_level(0);
+ metadata_buffer_.mutable_locks()->Mutable(0)->mutable_range()->set_begin(
+ simple_lock_begin_);
+ metadata_buffer_.mutable_locks()->Mutable(0)->mutable_range()->set_end(
+ simple_lock_end_);
+ WriteScopesMetadata(kScopeToResumeRevert, false);
+
+ // Cleanup task that will be ignored.
+ cleanup_task_buffer_.mutable_delete_range()->set_begin(
+ kCleanupDeleteRangeBegin);
+ cleanup_task_buffer_.mutable_delete_range()->set_end(kCleanupDeleteRangeEnd);
+ WriteCleanupTask(kScopeToResumeRevert, /*sequence_number=*/0);
+
+ // Undo task that will be executed.
+ int64_t undo_sequence_number = std::numeric_limits<int64_t>::max();
+ undo_task_buffer_.mutable_put()->set_key(kUndoPutKey);
+ undo_task_buffer_.mutable_put()->set_value(kUndoPutValue);
+ WriteUndoTask(kScopeToResumeRevert, undo_sequence_number);
+
+ // Entry which would be deleted by the cleanup task if it were run.
+ WriteLargeValue(kKeyWithinCleanupDeleteRange);
+
+ leveldb::Status failure_callback = leveldb::Status::OK();
+ LevelDBScopes scopes(
+ metadata_prefix_, kWriteBatchSizeForTesting, leveldb_, &lock_manager,
+ base::BindLambdaForTesting(
+ [&failure_callback](leveldb::Status s) { failure_callback = s; }));
+
+ leveldb::Status s = scopes.Initialize();
+ EXPECT_TRUE(s.ok());
+
+ // Verify that the lock was grabbed.
+ bool lock_grabbed = false;
+ ScopesLocksHolder locks_receiver;
+ lock_manager.AcquireLocks(
+ {CreateSimpleExclusiveLock()}, locks_receiver.AsWeakPtr(),
+ base::BindLambdaForTesting([&]() { lock_grabbed = true; }));
+
+ scopes.StartRecoveryAndCleanupTasks();
+
+ EXPECT_FALSE(lock_grabbed);
+
+ // Wait until revert runs.
+ {
+ base::RunLoop loop;
+ scopes.RevertRunnerForTesting()->PostTask(FROM_HERE, loop.QuitClosure());
+ loop.Run();
+ }
+ value_buffer_.clear();
+ EXPECT_TRUE(leveldb_->db()
+ ->Get(leveldb::ReadOptions(), kUndoPutKey, &value_buffer_)
+ .ok());
+ EXPECT_EQ(kUndoPutValue, value_buffer_);
+
+ // Ensure the cleanup task was posted & locks were released.
+ {
+ base::RunLoop loop;
+ base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ loop.QuitClosure());
+ loop.Run();
+ }
+ EXPECT_TRUE(lock_grabbed);
+
+ // Wait until cleanup runs.
+ {
+ base::RunLoop loop;
+ scopes.CleanupRunnerForTesting()->PostTask(FROM_HERE, loop.QuitClosure());
+ loop.Run();
+ }
+ EXPECT_TRUE(IsScopeCleanedUp(kScopeToResumeRevert));
+ EXPECT_FALSE(ScopeDataExistsOnDisk());
+
+ value_buffer_.clear();
+ EXPECT_TRUE(leveldb_->db()
+ ->Get(leveldb::ReadOptions(), kKeyWithinCleanupDeleteRange,
+ &value_buffer_)
+ .ok());
+
+ EXPECT_TRUE(failure_callback.ok());
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.cc b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.cc
index 5d0da32c4ca..709f579869c 100644
--- a/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.cc
+++ b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.cc
@@ -12,6 +12,9 @@
namespace content {
+ScopesLocksHolder::ScopesLocksHolder() = default;
+ScopesLocksHolder::~ScopesLocksHolder() = default;
+
ScopesLockManager::ScopesLockManager() : weak_factory_(this) {}
ScopesLockManager::~ScopesLockManager() = default;
diff --git a/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h
index 6b336b954e7..eaa4aceeac5 100644
--- a/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h
+++ b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h
@@ -19,11 +19,33 @@
namespace content {
+// Used to receive and hold locks from a ScopesLockManager. This struct enables
+// the ScopeLock objects to always live in the destination of the caller's
+// choosing (as opposed to having the locks be an argument in the callback,
+// where they could be owned by the task scheduler).
+// This class must be used and destructed on the same sequence as the
+// ScopesLockManager.
+struct CONTENT_EXPORT ScopesLocksHolder {
+ public:
+ ScopesLocksHolder();
+ ~ScopesLocksHolder();
+
+ base::WeakPtr<ScopesLocksHolder> AsWeakPtr() {
+ return weak_factory.GetWeakPtr();
+ }
+
+ std::vector<ScopeLock> locks;
+ base::WeakPtrFactory<ScopesLocksHolder> weak_factory{this};
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopesLocksHolder);
+};
+
// Generic two-level lock management system based on ranges. Granted locks are
// represented by the |ScopeLock| class.
class CONTENT_EXPORT ScopesLockManager {
public:
- using LocksAquiredCallback = base::OnceCallback<void(std::vector<ScopeLock>)>;
+ using LocksAquiredCallback = base::OnceClosure;
// Shared locks can share access to a lock range, while exclusive locks
// require that they are the only lock for their range.
@@ -46,6 +68,7 @@ class CONTENT_EXPORT ScopesLockManager {
LockType type;
};
virtual bool AcquireLocks(base::flat_set<ScopeLockRequest> lock_requests,
+ base::WeakPtr<ScopesLocksHolder> locks_receiever,
LocksAquiredCallback callback) = 0;
private:
diff --git a/chromium/content/browser/indexed_db/transaction_impl.cc b/chromium/content/browser/indexed_db/transaction_impl.cc
index 8ba3fc3fb5b..88a295c8689 100644
--- a/chromium/content/browser/indexed_db/transaction_impl.cc
+++ b/chromium/content/browser/indexed_db/transaction_impl.cc
@@ -99,6 +99,7 @@ void TransactionImpl::CreateObjectStore(int64_t object_store_id,
if (transaction_->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
mojo::ReportBadMessage(
"CreateObjectStore must be called from a version change transaction.");
+ return;
}
IndexedDBConnection* connection = transaction_->connection();
@@ -119,6 +120,7 @@ void TransactionImpl::DeleteObjectStore(int64_t object_store_id) {
if (transaction_->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
mojo::ReportBadMessage(
"DeleteObjectStore must be called from a version change transaction.");
+ return;
}
IndexedDBConnection* connection = transaction_->connection();
diff --git a/chromium/content/browser/isolated_origin_browsertest.cc b/chromium/content/browser/isolated_origin_browsertest.cc
index 32b5d5e9fb9..7d1d7c934f5 100644
--- a/chromium/content/browser/isolated_origin_browsertest.cc
+++ b/chromium/content/browser/isolated_origin_browsertest.cc
@@ -63,6 +63,10 @@ class IsolatedOriginTestBase : public ContentBrowserTest {
return IsIsolatedOrigin(url::Origin::Create(url));
}
+ WebContentsImpl* web_contents() const {
+ return static_cast<WebContentsImpl*>(shell()->web_contents());
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(IsolatedOriginTestBase);
};
@@ -86,10 +90,6 @@ class IsolatedOriginTest : public IsolatedOriginTestBase {
embedded_test_server()->StartAcceptingConnections();
}
- WebContentsImpl* web_contents() const {
- return static_cast<WebContentsImpl*>(shell()->web_contents());
- }
-
void InjectAndClickLinkTo(GURL url) {
EXPECT_TRUE(ExecuteScript(web_contents(),
"var link = document.createElement('a');"
@@ -102,6 +102,126 @@ class IsolatedOriginTest : public IsolatedOriginTestBase {
DISALLOW_COPY_AND_ASSIGN(IsolatedOriginTest);
};
+class StrictOriginIsolationTest : public IsolatedOriginTestBase {
+ public:
+ StrictOriginIsolationTest() {}
+ ~StrictOriginIsolationTest() override {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ IsolatedOriginTestBase::SetUpCommandLine(command_line);
+ ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+
+ // This is needed for this test to run properly on platforms where
+ // --site-per-process isn't the default, such as Android.
+ IsolateAllSitesForTesting(command_line);
+ feature_list_.InitAndEnableFeature(features::kStrictOriginIsolation);
+ }
+
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ embedded_test_server()->StartAcceptingConnections();
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(StrictOriginIsolationTest);
+};
+
+IN_PROC_BROWSER_TEST_F(StrictOriginIsolationTest, SubframesAreIsolated) {
+ GURL test_url(embedded_test_server()->GetURL(
+ "foo.com",
+ "/cross_site_iframe_factory.html?"
+ "foo.com(mail.foo.com,bar.foo.com(foo.com),foo.com)"));
+ EXPECT_TRUE(NavigateToURL(shell(), test_url));
+ EXPECT_EQ(5u, shell()->web_contents()->GetAllFrames().size());
+
+ // Make sure we have three separate processes.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ RenderFrameHost* main_frame = root->current_frame_host();
+ int main_frame_id = main_frame->GetProcess()->GetID();
+ RenderFrameHost* child_frame0 = root->child_at(0)->current_frame_host();
+ int child_frame0_id = child_frame0->GetProcess()->GetID();
+ RenderFrameHost* child_frame1 = root->child_at(1)->current_frame_host();
+ int child_frame1_id = child_frame1->GetProcess()->GetID();
+ RenderFrameHost* child_frame2 = root->child_at(2)->current_frame_host();
+ int child_frame2_id = child_frame2->GetProcess()->GetID();
+ RenderFrameHost* grandchild_frame0 =
+ root->child_at(1)->child_at(0)->current_frame_host();
+ int grandchild_frame0_id = grandchild_frame0->GetProcess()->GetID();
+ EXPECT_NE(main_frame_id, child_frame0_id);
+ EXPECT_NE(main_frame_id, child_frame1_id);
+ EXPECT_EQ(main_frame_id, child_frame2_id);
+ EXPECT_EQ(main_frame_id, grandchild_frame0_id);
+
+ std::string port_string =
+ base::StringPrintf(":%u", embedded_test_server()->port());
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ EXPECT_EQ(GURL("http://foo.com" + port_string),
+ policy->GetOriginLock(main_frame_id));
+ EXPECT_EQ(GURL("http://mail.foo.com" + port_string),
+ policy->GetOriginLock(child_frame0_id));
+ EXPECT_EQ(GURL("http://bar.foo.com" + port_string),
+ policy->GetOriginLock(child_frame1_id));
+ EXPECT_EQ(GURL("http://foo.com" + port_string),
+ policy->GetOriginLock(child_frame2_id));
+ EXPECT_EQ(GURL("http://foo.com" + port_string),
+ policy->GetOriginLock(grandchild_frame0_id));
+
+ // Navigate child_frame1 to a new origin ... it should get its own process.
+ FrameTreeNode* child_frame2_node = root->child_at(2);
+ GURL foo_url(embedded_test_server()->GetURL("www.foo.com", "/title1.html"));
+ NavigateFrameToURL(child_frame2_node, foo_url);
+ EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+ child_frame2_node->current_frame_host()->GetSiteInstance());
+ // The old RenderFrameHost for subframe3 will no longer be valid, so get the
+ // new one.
+ child_frame2 = root->child_at(2)->current_frame_host();
+ EXPECT_NE(main_frame->GetProcess()->GetID(),
+ child_frame2->GetProcess()->GetID());
+ EXPECT_EQ(GURL("http://www.foo.com" + port_string),
+ policy->GetOriginLock(child_frame2->GetProcess()->GetID()));
+}
+
+IN_PROC_BROWSER_TEST_F(StrictOriginIsolationTest, MainframesAreIsolated) {
+ GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), foo_url));
+ EXPECT_EQ(1u, web_contents()->GetAllFrames().size());
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+
+ auto foo_process_id = web_contents()->GetMainFrame()->GetProcess()->GetID();
+ SiteInstance* foo_site_instance = shell()->web_contents()->GetSiteInstance();
+ EXPECT_EQ(foo_site_instance->GetSiteURL(),
+ policy->GetOriginLock(foo_process_id));
+
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("sub.foo.com", "/title1.html")));
+ auto sub_foo_process_id =
+ shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
+ SiteInstance* sub_foo_site_instance =
+ shell()->web_contents()->GetSiteInstance();
+ EXPECT_EQ(sub_foo_site_instance->GetSiteURL(),
+ policy->GetOriginLock(sub_foo_process_id));
+
+ EXPECT_NE(foo_process_id, sub_foo_process_id);
+ EXPECT_NE(foo_site_instance->GetSiteURL(),
+ sub_foo_site_instance->GetSiteURL());
+
+ // Now verify with a renderer-initiated navigation.
+ GURL another_foo_url(
+ embedded_test_server()->GetURL("another.foo.com", "/title2.html"));
+ EXPECT_TRUE(NavigateToURLFromRenderer(shell(), another_foo_url));
+ auto another_foo_process_id =
+ shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
+ SiteInstance* another_foo_site_instance =
+ shell()->web_contents()->GetSiteInstance();
+ EXPECT_NE(another_foo_process_id, sub_foo_process_id);
+ EXPECT_NE(another_foo_process_id, foo_process_id);
+ EXPECT_EQ(another_foo_site_instance->GetSiteURL(),
+ policy->GetOriginLock(another_foo_process_id));
+ EXPECT_NE(another_foo_site_instance, foo_site_instance);
+}
+
// Check that navigating a main frame from an non-isolated origin to an
// isolated origin and vice versa swaps processes and uses a new SiteInstance,
// both for renderer-initiated and browser-initiated navigations.
@@ -979,11 +1099,9 @@ IN_PROC_BROWSER_TEST_F(
// A SiteInstance created for an isolated origin ServiceWorker should
// not reuse the unsuitable first process.
scoped_refptr<SiteInstanceImpl> sw_site_instance =
- SiteInstanceImpl::CreateForURL(web_contents()->GetBrowserContext(),
- hung_isolated_url);
- sw_site_instance->set_is_for_service_worker();
- sw_site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateForServiceWorker(
+ web_contents()->GetBrowserContext(), hung_isolated_url,
+ /* can_reuse_process */ true);
RenderProcessHost* sw_host = sw_site_instance->GetProcess();
EXPECT_NE(new_shell->web_contents()->GetMainFrame()->GetProcess(), sw_host);
@@ -1395,7 +1513,7 @@ IN_PROC_BROWSER_TEST_F(IsolatedOriginTrialOverrideTest, Test) {
}
// Ensure that --disable-site-isolation-trials and/or
-// --disable-site-isolation-for-enterprise-policy do not override the flag.
+// --disable-site-isolation-for-policy do not override the flag.
class IsolatedOriginPolicyOverrideTest : public IsolatedOriginFieldTrialTest {
public:
IsolatedOriginPolicyOverrideTest() {}
@@ -1404,7 +1522,9 @@ class IsolatedOriginPolicyOverrideTest : public IsolatedOriginFieldTrialTest {
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kDisableSiteIsolation);
+#if defined(OS_ANDROID)
command_line->AppendSwitch(switches::kDisableSiteIsolationForPolicy);
+#endif
}
private:
@@ -1419,7 +1539,7 @@ IN_PROC_BROWSER_TEST_F(IsolatedOriginPolicyOverrideTest, Test) {
}
// Ensure that --disable-site-isolation-trials and/or
-// DisableSiteIsolationForPolicy do not override the flag.
+// --disable-site-isolation-for-policy do not override the flag.
class IsolatedOriginNoFlagOverrideTest : public IsolatedOriginTest {
public:
IsolatedOriginNoFlagOverrideTest() {}
@@ -1429,7 +1549,9 @@ class IsolatedOriginNoFlagOverrideTest : public IsolatedOriginTest {
void SetUpCommandLine(base::CommandLine* command_line) override {
IsolatedOriginTest::SetUpCommandLine(command_line);
command_line->AppendSwitch(switches::kDisableSiteIsolation);
+#if defined(OS_ANDROID)
command_line->AppendSwitch(switches::kDisableSiteIsolationForPolicy);
+#endif
}
private:
diff --git a/chromium/content/browser/isolation_context.h b/chromium/content/browser/isolation_context.h
index e91a20b5fd5..a607fdb89bf 100644
--- a/chromium/content/browser/isolation_context.h
+++ b/chromium/content/browser/isolation_context.h
@@ -6,14 +6,14 @@
#define CONTENT_BROWSER_ISOLATION_CONTEXT_H_
#include "base/optional.h"
+#include "base/util/type_safety/id_type.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_or_resource_context.h"
-#include "gpu/command_buffer/common/id_type.h"
namespace content {
class BrowsingInstance;
-using BrowsingInstanceId = gpu::IdType32<BrowsingInstance>;
+using BrowsingInstanceId = util::IdType32<BrowsingInstance>;
// This class is used to specify the context in which process model decisions
// need to be made. For example, dynamically added isolated origins only take
diff --git a/chromium/content/browser/keyboard_lock_browsertest.cc b/chromium/content/browser/keyboard_lock_browsertest.cc
index a219cefad0a..e7545cc79d2 100644
--- a/chromium/content/browser/keyboard_lock_browsertest.cc
+++ b/chromium/content/browser/keyboard_lock_browsertest.cc
@@ -127,9 +127,7 @@ bool g_window_has_focus = false;
class TestRenderWidgetHostView : public RenderWidgetHostViewAura {
public:
TestRenderWidgetHostView(RenderWidgetHost* host, bool is_guest_view_hack)
- : RenderWidgetHostViewAura(host,
- is_guest_view_hack,
- false /* is_mus_browser_plugin_guest */) {}
+ : RenderWidgetHostViewAura(host, is_guest_view_hack) {}
~TestRenderWidgetHostView() override {}
bool HasFocus() override { return g_window_has_focus; }
diff --git a/chromium/content/browser/loader/cross_origin_read_blocking_checker.cc b/chromium/content/browser/loader/cross_origin_read_blocking_checker.cc
new file mode 100644
index 00000000000..3aee65b718f
--- /dev/null
+++ b/chromium/content/browser/loader/cross_origin_read_blocking_checker.cc
@@ -0,0 +1,122 @@
+// Copyright 2019 The Chromium Authors. All rights 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/cross_origin_read_blocking_checker.h"
+
+#include "base/callback.h"
+#include "net/base/io_buffer.h"
+#include "net/base/mime_sniffer.h"
+#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_reader.h"
+#include "url/origin.h"
+
+namespace content {
+
+CrossOriginReadBlockingChecker::CrossOriginReadBlockingChecker(
+ const network::ResourceRequest& request,
+ const network::ResourceResponseHead& response,
+ const url::Origin& request_initiator_site_lock,
+ const storage::BlobDataHandle& blob_data_handle,
+ base::OnceCallback<void(Result)> callback)
+ : callback_(std::move(callback)) {
+ DCHECK(!callback_.is_null());
+ network::CrossOriginReadBlocking::LogAction(
+ network::CrossOriginReadBlocking::Action::kResponseStarted);
+ corb_analyzer_ =
+ std::make_unique<network::CrossOriginReadBlocking::ResponseAnalyzer>(
+ request.url, request.request_initiator, response,
+ request_initiator_site_lock, request.fetch_request_mode);
+ if (corb_analyzer_->ShouldBlock()) {
+ OnBlocked();
+ return;
+ }
+ if (corb_analyzer_->needs_sniffing()) {
+ StartSniffing(blob_data_handle);
+ return;
+ }
+ DCHECK(corb_analyzer_->ShouldAllow());
+ OnAllowed();
+}
+
+CrossOriginReadBlockingChecker::~CrossOriginReadBlockingChecker() = default;
+
+int CrossOriginReadBlockingChecker::GetNetError() {
+ DCHECK(blob_reader_);
+ return blob_reader_->net_error();
+}
+
+void CrossOriginReadBlockingChecker::OnAllowed() {
+ corb_analyzer_->LogAllowedResponse();
+ std::move(callback_).Run(Result::kAllowed);
+}
+
+void CrossOriginReadBlockingChecker::OnBlocked() {
+ corb_analyzer_->LogBlockedResponse();
+ std::move(callback_).Run(corb_analyzer_->ShouldReportBlockedResponse()
+ ? Result::kBlocked_ShouldReport
+ : Result::kBlocked_ShouldNotReport);
+}
+
+void CrossOriginReadBlockingChecker::OnNetError() {
+ std::move(callback_).Run(Result::kNetError);
+}
+
+void CrossOriginReadBlockingChecker::StartSniffing(
+ const storage::BlobDataHandle& blob_data_handle) {
+ blob_reader_ = blob_data_handle.CreateReader();
+ const storage::BlobReader::Status size_status = blob_reader_->CalculateSize(
+ base::BindOnce(&CrossOriginReadBlockingChecker::DidCalculateSize,
+ base::Unretained(this)));
+ switch (size_status) {
+ case storage::BlobReader::Status::NET_ERROR:
+ OnNetError();
+ return;
+ case storage::BlobReader::Status::IO_PENDING:
+ return;
+ case storage::BlobReader::Status::DONE:
+ DidCalculateSize(net::OK);
+ return;
+ }
+}
+
+void CrossOriginReadBlockingChecker::DidCalculateSize(int result) {
+ size_t buf_size = net::kMaxBytesToSniff;
+ if (buf_size > blob_reader_->total_size())
+ buf_size = blob_reader_->total_size();
+ buffer_ = base::MakeRefCounted<net::IOBufferWithSize>(buf_size);
+ int bytes_read;
+ const storage::BlobReader::Status status = blob_reader_->Read(
+ buffer_.get(), buf_size, &bytes_read,
+ base::BindOnce(&CrossOriginReadBlockingChecker::OnReadComplete,
+ base::Unretained(this)));
+ switch (status) {
+ case storage::BlobReader::Status::NET_ERROR:
+ OnNetError();
+ return;
+ case storage::BlobReader::Status::IO_PENDING:
+ return;
+ case storage::BlobReader::Status::DONE:
+ OnReadComplete(bytes_read);
+ return;
+ }
+}
+
+void CrossOriginReadBlockingChecker::OnReadComplete(int bytes_read) {
+ if (bytes_read != buffer_->size()) {
+ OnNetError();
+ return;
+ }
+ base::StringPiece data(buffer_->data(), bytes_read);
+ corb_analyzer_->SniffResponseBody(data, 0);
+ if (corb_analyzer_->ShouldBlock()) {
+ OnBlocked();
+ return;
+ }
+ OnAllowed();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/cross_origin_read_blocking_checker.h b/chromium/content/browser/loader/cross_origin_read_blocking_checker.h
new file mode 100644
index 00000000000..f72a8cb4d38
--- /dev/null
+++ b/chromium/content/browser/loader/cross_origin_read_blocking_checker.h
@@ -0,0 +1,74 @@
+// Copyright 2019 The Chromium Authors. All rights 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_CROSS_ORIGIN_READ_BLOCKING_CHECKER_H_
+#define CONTENT_BROWSER_LOADER_CROSS_ORIGIN_READ_BLOCKING_CHECKER_H_
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "services/network/cross_origin_read_blocking.h"
+
+namespace net {
+class IOBufferWithSize;
+} // namespace net
+
+namespace network {
+struct ResourceRequest;
+struct ResourceResponseHead;
+} // namespace network
+
+namespace storage {
+class BlobDataHandle;
+class BlobReader;
+} // namespace storage
+
+namespace url {
+class Origin;
+} // namespace url
+
+namespace content {
+
+// This class checks whether we should block the response or not using
+// CrossOriginReadBlocking::ResponseAnalyzer.
+class CrossOriginReadBlockingChecker {
+ public:
+ enum class Result {
+ kAllowed,
+ kBlocked_ShouldReport,
+ kBlocked_ShouldNotReport,
+ kNetError
+ };
+ CrossOriginReadBlockingChecker(
+ const network::ResourceRequest& request,
+ const network::ResourceResponseHead& response,
+ const url::Origin& request_initiator_site_lock,
+ const storage::BlobDataHandle& blob_data_handle,
+ base::OnceCallback<void(Result)> callback);
+ ~CrossOriginReadBlockingChecker();
+
+ int GetNetError();
+
+ private:
+ void OnAllowed();
+ void OnBlocked();
+ void OnNetError();
+
+ void StartSniffing(const storage::BlobDataHandle& blob_data_handle);
+
+ void DidCalculateSize(int result);
+
+ void OnReadComplete(int bytes_read);
+
+ base::OnceCallback<void(Result)> callback_;
+ std::unique_ptr<network::CrossOriginReadBlocking::ResponseAnalyzer>
+ corb_analyzer_;
+ std::unique_ptr<storage::BlobReader> blob_reader_;
+ scoped_refptr<net::IOBufferWithSize> buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(CrossOriginReadBlockingChecker);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_CROSS_ORIGIN_READ_BLOCKING_CHECKER_H_
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 6bab20d86be..8f3984e1ce0 100644
--- a/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
+++ b/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -54,10 +54,9 @@ namespace content {
using testing::Not;
using testing::HasSubstr;
using Action = network::CrossOriginReadBlocking::Action;
+using CorbMimeType = network::CrossOriginReadBlocking::MimeType;
using RequestInitiatorOriginLockCompatibility =
network::InitiatorLockCompatibility;
-using CorbVsInitiatorLock =
- network::CrossOriginReadBlocking::CorbResultVsInitiatorLockCompatibility;
namespace {
@@ -116,50 +115,33 @@ void InspectHistograms(
histograms.ExpectUniqueSample(
"NetworkService.URLLoader.RequestInitiatorOriginLockCompatibility",
expected_lock_compatibility, 1);
-
- if (0 != (expectations & kShouldBeBlocked)) {
- auto benign_blocking = base::Bucket(
- static_cast<int>(CorbVsInitiatorLock::kBenignBlocking), 1);
- auto compatible_blocking = base::Bucket(
- static_cast<int>(CorbVsInitiatorLock::kBlockingWhenCompatibleLock),
- 1);
- auto other_blocking = base::Bucket(
- static_cast<int>(CorbVsInitiatorLock::kBlockingWhenOtherLock), 1);
-
- ::testing::Matcher<std::vector<base::Bucket>> expected_buckets;
- if (special_request_initiator_origin_lock_check_for_appcache) {
- expected_buckets = ::testing::ElementsAre(other_blocking);
- } else {
- // Important part of the verification is that we never expect to
- // encounted kBlockingWhenIncorrectLock (outside of HTML Import
- // scenarios covered by separate, explicit tests below).
- expected_buckets =
- ::testing::AnyOf(::testing::ElementsAre(benign_blocking),
- ::testing::ElementsAre(compatible_blocking));
- }
-
- EXPECT_THAT(
- histograms.GetAllSamples(
- "SiteIsolation.XSD.NetworkService.InitiatorLockCompatibility"),
- expected_buckets);
- } else { // ~kAllowed
- histograms.ExpectUniqueSample(
- "SiteIsolation.XSD.NetworkService.InitiatorLockCompatibility",
- CorbVsInitiatorLock::kNoBlocking, 1);
- }
}
std::string bucket;
+ CorbMimeType expected_mime_type = CorbMimeType::kInvalidMimeType;
if (base::MatchPattern(resource_name, "*.html")) {
bucket = "HTML";
+ expected_mime_type = CorbMimeType::kHtml;
} else if (base::MatchPattern(resource_name, "*.xml")) {
bucket = "XML";
+ expected_mime_type = CorbMimeType::kXml;
} else if (base::MatchPattern(resource_name, "*.json")) {
bucket = "JSON";
+ expected_mime_type = CorbMimeType::kJson;
} else if (base::MatchPattern(resource_name, "*.txt")) {
bucket = "Plain";
+ expected_mime_type = CorbMimeType::kPlain;
+ } else if (base::MatchPattern(resource_name, "*.zip") ||
+ base::MatchPattern(resource_name, "*.pdf")) {
+ // SiteIsolation.XSD.Browser.Blocked* histograms are only logged from the
+ // pre-kNetworkService code. Because of this we did not add
+ // SiteIsolation.XSD.Browser.Blocked.NonSniffed histogram. An empty
+ // |bucket| value indicates that the test should not expect a histogram.
+ bucket = "";
+ expected_mime_type = CorbMimeType::kNeverSniffed;
} else {
bucket = "Others";
+ expected_mime_type = CorbMimeType::kOthers;
}
// Determine the appropriate histograms, including a start and end action
@@ -176,9 +158,11 @@ void InspectHistograms(
expected_counts[base + ".BytesReadForSniffing"] = 1;
if (0 != (expectations & kShouldBeBlocked && !is_restricted_uma_expected)) {
expected_counts[base + ".Blocked"] = 1;
- expected_counts[base + ".Blocked." + bucket] = 1;
+ if (!bucket.empty())
+ expected_counts[base + ".Blocked." + bucket] = 1;
}
if (0 != (expectations & kShouldBeBlocked)) {
+ expected_counts[base + ".Blocked.CanonicalMimeType"] = 1;
expected_counts[base + ".Blocked.ContentLength.WasAvailable"] = 1;
bool should_have_content_length =
0 != (expectations & kShouldLogContentLengthUma);
@@ -197,15 +181,23 @@ void InspectHistograms(
<< ", expectations=" << expectations;
// Determine if the bucket for the resource type (XHR) was incremented.
- if (0 != (expectations & kShouldBeBlocked) && !is_restricted_uma_expected) {
- EXPECT_THAT(
- histograms.GetAllSamples(base + ".Blocked"),
- testing::ElementsAre(base::Bucket(static_cast<int>(resource_type), 1)))
- << "The wrong Blocked bucket was incremented.";
- EXPECT_THAT(
- histograms.GetAllSamples(base + ".Blocked." + bucket),
- testing::ElementsAre(base::Bucket(static_cast<int>(resource_type), 1)))
- << "The wrong Blocked bucket was incremented.";
+ if (0 != (expectations & kShouldBeBlocked)) {
+ EXPECT_THAT(histograms.GetAllSamples(base + ".Blocked.CanonicalMimeType"),
+ testing::ElementsAre(
+ base::Bucket(static_cast<int>(expected_mime_type), 1)))
+ << "The wrong CorbMimeType bucket was incremented.";
+ if (!is_restricted_uma_expected) {
+ EXPECT_THAT(histograms.GetAllSamples(base + ".Blocked"),
+ testing::ElementsAre(
+ base::Bucket(static_cast<int>(resource_type), 1)))
+ << "The wrong Blocked bucket was incremented.";
+ if (!bucket.empty()) {
+ EXPECT_THAT(histograms.GetAllSamples(base + ".Blocked." + bucket),
+ testing::ElementsAre(
+ base::Bucket(static_cast<int>(resource_type), 1)))
+ << "The wrong Blocked bucket was incremented.";
+ }
+ }
}
// SiteIsolation.XSD.Browser.Action should always include kResponseStarted.
@@ -319,6 +311,10 @@ class RequestInterceptor {
request_initiator_to_inject_ = request_initiator;
}
+ void InjectFetchMode(network::mojom::FetchRequestMode fetch_mode) {
+ fetch_mode_to_inject_ = fetch_mode;
+ }
+
private:
void ReadBody(base::OnceClosure completion_callback) {
char buffer[128];
@@ -375,6 +371,8 @@ class RequestInterceptor {
// Modify |params| if requested.
if (request_initiator_to_inject_.has_value())
params->url_request.request_initiator = request_initiator_to_inject_;
+ if (fetch_mode_to_inject_.has_value())
+ params->url_request.fetch_request_mode = fetch_mode_to_inject_.value();
// Inject |test_client_| into the request.
DCHECK(!original_client_);
@@ -441,6 +439,7 @@ class RequestInterceptor {
URLLoaderInterceptor interceptor_;
base::Optional<url::Origin> request_initiator_to_inject_;
+ base::Optional<network::mojom::FetchRequestMode> fetch_mode_to_inject_;
// |test_client_ptr_info_| below is used to transition results of
// |test_client_.CreateInterfacePtr()| into IO thread.
@@ -592,8 +591,14 @@ IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BlockImages) {
// These files should be disallowed without sniffing.
// nosniff.* - Won't sniff correctly, but blocked because of nosniff.
- const char* nosniff_blocked_resources[] = {"nosniff.html", "nosniff.xml",
- "nosniff.json", "nosniff.txt"};
+ //
+ // TODO(lukasza): https://crbug.com/944162: Once
+ // kMimeHandlerViewInCrossProcessFrame feature ships cover "fake.pdf" below
+ // (this can't be tested in content_browsertests, because covering of
+ // application/pdf is handled by //chrome-layer
+ // ChromeContentBrowserClient::OnNetworkServiceCreated.
+ const char* nosniff_blocked_resources[] = {
+ "nosniff.html", "nosniff.xml", "nosniff.json", "nosniff.txt", "fake.zip"};
for (const char* resource : nosniff_blocked_resources) {
SCOPED_TRACE(base::StringPrintf("... while testing page: %s", resource));
VerifyImgRequest(resource, kShouldBeBlockedWithoutSniffing);
@@ -657,7 +662,7 @@ IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest,
EXPECT_EQ("", interceptor.response_body());
}
-IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BlockFetches) {
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, AllowCorsFetches) {
embedded_test_server()->StartAcceptingConnections();
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -686,10 +691,57 @@ IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BlockFetches) {
}
}
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest,
+ AllowSameOriginFetchFromLoadDataWithBaseUrl) {
+ embedded_test_server()->StartAcceptingConnections();
+
+ // LoadDataWithBaseURL is never subject to --site-per-process policy today
+ // (this API is only used by Android WebView [where OOPIFs have not shipped
+ // yet] and GuestView cases [which always hosts guests inside a renderer
+ // without an origin lock]). Therefore, skip the test in --site-per-process
+ // mode to avoid renderer kills which won't happen in practice as described
+ // above.
+ //
+ // TODO(https://crbug.com/962643): Consider enabling this test once Android
+ // Webview or WebView guests support OOPIFs and/or origin locks.
+ if (AreAllSitesIsolatedForTesting())
+ return;
+
+ // Navigate via LoadDataWithBaseURL.
+ const GURL base_url("http://foo.com");
+ const std::string data = "<html><body>foo</body></html>";
+ const GURL data_url = GURL("data:text/html;charset=utf-8," + data);
+ TestNavigationObserver nav_observer(shell()->web_contents(), 1);
+ shell()->LoadDataWithBaseURL(base_url /* history_url */, data, base_url);
+ nav_observer.Wait();
+
+ // Fetch a same-origin resource.
+ GURL resource_url("http://foo.com/site_isolation/nosniff.html");
+ EXPECT_EQ(url::Origin::Create(resource_url),
+ shell()->web_contents()->GetMainFrame()->GetLastCommittedOrigin());
+ FetchHistogramsFromChildProcesses();
+ base::HistogramTester histograms;
+ std::string fetch_result =
+ EvalJs(shell(), JsReplace("fetch($1).then(response => response.text())",
+ resource_url))
+ .ExtractString();
+ fetch_result = TrimWhitespaceASCII(fetch_result, base::TRIM_ALL).as_string();
+
+ // Verify that the response was not blocked.
+ EXPECT_EQ("runMe({ \"name\" : \"chromium\" });", fetch_result);
+ InspectHistograms(histograms, kShouldBeAllowedWithoutSniffing, "nosniff.html",
+ ResourceType::kXhr);
+}
+
// Regression test for https://crbug.com/958421.
IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BackToAboutBlank) {
embedded_test_server()->StartAcceptingConnections();
+ // TODO(lukasza, nasko): https://crbug.com/888079: Re-enable the test once
+ // initiator origin is stored and reused for history navigations.
+ if (!AreAllSitesIsolatedForTesting())
+ return;
+
// Prepare to verify results of a fetch.
GURL resource_url("http://foo.com/title2.html");
const char* resource = "title2.html";
@@ -1056,10 +1108,9 @@ IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest,
if (!AreAllSitesIsolatedForTesting())
return;
- // Prepare to intercept the network request at the IPC layer.
- // in a way, that injects |spoofed_initiator| (simulating a compromised
- // renderer that pretends to be making the request on behalf of another
- // origin).
+ // Prepare to intercept the network request at the IPC layer in a way, that
+ // injects |spoofed_initiator| (simulating a compromised renderer that
+ // pretends to be making the request on behalf of another origin).
//
// Note that RequestInterceptor has to be constructed before the
// RenderFrameHostImpl is created.
@@ -1100,6 +1151,64 @@ IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest,
bad_message_observer.WaitForBadMessage());
}
+// Tests that renderer will be terminated if it asks AppCache to initiate a
+// cross-origin request with network::mojom::FetchRequestMode::kNavigate.
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest,
+ AppCache_NoNavigationsEnforcement) {
+ embedded_test_server()->StartAcceptingConnections();
+
+ // Verification of |request_initiator| is only done in the NetworkService code
+ // path.
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
+ // No kills are expected unless the fetch requesting process is locked to a
+ // specific site URL. Therefore, the test should be skipped unless the full
+ // Site Isolation is enabled.
+ if (!AreAllSitesIsolatedForTesting())
+ return;
+
+ // Prepare to intercept the network request at the IPC layer in a way, that
+ // injects a spoofed fetch mode (simulating a compromised renderer that
+ // attempts to bypass CORB by using a fetch mode other than no-cors).
+ //
+ // Note that RequestInterceptor has to be constructed before the
+ // RenderFrameHostImpl is created.
+ GURL cross_site_url("http://cross-origin.com/site_isolation/nosniff.json");
+ RequestInterceptor interceptor(cross_site_url);
+ interceptor.InjectFetchMode(network::mojom::FetchRequestMode::kNavigate);
+
+ // Load the main page twice. The second navigation should have AppCache
+ // initialized for the page.
+ GURL main_url = embedded_test_server()->GetURL(
+ "/appcache/simple_page_with_manifest.html");
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ base::string16 expected_title = base::ASCIIToUTF16("AppCache updated");
+ content::TitleWatcher title_watcher(shell()->web_contents(), expected_title);
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Trigger an AppCache request with an incorrect |request_initiator| and
+ // verify that this will terminate the renderer process.
+ //
+ // Note that during the test, no renderer processes will be actually
+ // terminated, because the malicious/invalid message originates from within
+ // the test process (i.e. from URLLoaderInterceptor::Interceptor's
+ // CreateLoaderAndStart method which forwards the
+ // InjectFetchMode-modified request into
+ // AppCacheSubresourceURLFactory). This necessitates testing via
+ // mojo::test::BadMessageObserver rather than via RenderProcessHostWatcher or
+ // RenderProcessHostKillWaiter.
+ mojo::test::BadMessageObserver bad_message_observer;
+ const char kScriptTemplate[] = R"(
+ var img = document.createElement('img');
+ img.src = $1;
+ document.body.appendChild(img); )";
+ EXPECT_TRUE(ExecJs(shell(), JsReplace(kScriptTemplate, cross_site_url)));
+ EXPECT_EQ("APPCACHE_SUBRESOURCE_URL_FACTORY_NAVIGATE",
+ bad_message_observer.WaitForBadMessage());
+}
+
IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, PrefetchIsNotImpacted) {
// Prepare for intercepting the resource request for testing prefetching.
const char* kPrefetchResourcePath = "/prefetch-test";
@@ -1264,28 +1373,6 @@ IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest,
// which means that legitimate fetches from HTML Imported scripts may get
// incorrectly blocked.
interceptor.Verify(CorbExpectations::kShouldBeBlockedWithoutSniffing);
-
- // The main purpose of the test is not verifying the incorrect behavior
- // above, but making sure that the UMA that records the incorrect behavior
- // is logged. Hopefully the incorrect behavior will rarely occur in
- // practice.
- FetchHistogramsFromChildProcesses();
- auto incorrect_lock_blocking = base::Bucket(
- static_cast<int>(CorbVsInitiatorLock::kBlockingWhenIncorrectLock), 1);
-
- // ExecuteScriptAsync covers 2 fetches:
- // - Fetching cross_site_document_blocking/html_import.html
- // - Fetching site_isolation/nosniff.json (via <script src=...>
- // from html_import.html)
- // The second one is done with kIncorrectLock, but the assertion below
- // needs to also cover the first one:
- auto no_blocking =
- base::Bucket(static_cast<int>(CorbVsInitiatorLock::kNoBlocking), 1);
- EXPECT_THAT(
- histograms.GetAllSamples(
- "SiteIsolation.XSD.NetworkService.InitiatorLockCompatibility"),
- ::testing::UnorderedElementsAre(no_blocking,
- incorrect_lock_blocking));
} else {
// Without |request_initiator_site_lock| no CORB blocking is expected.
interceptor.Verify(CorbExpectations::kShouldBeAllowedWithoutSniffing);
@@ -1356,22 +1443,6 @@ IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest,
std::string fetch_result;
EXPECT_TRUE(msg_queue.WaitForMessage(&fetch_result));
EXPECT_THAT(fetch_result, ::testing::HasSubstr("BODY: runMe"));
-
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- FetchHistogramsFromChildProcesses();
-
- // ExecuteScriptAsync covers 3 fetches:
- // - Fetching cross_site_document_blocking/html_import.html
- // - Fetching cross_site_document_blocking/fetch_nosniff_json.js
- // - Fetching site_isolation/nosniff.json
- // All of them should result in no CORB blocking.
- auto no_blocking =
- base::Bucket(static_cast<int>(CorbVsInitiatorLock::kNoBlocking), 3);
- EXPECT_THAT(
- histograms.GetAllSamples(
- "SiteIsolation.XSD.NetworkService.InitiatorLockCompatibility"),
- ::testing::UnorderedElementsAre(no_blocking));
- }
}
}
@@ -1438,25 +1509,6 @@ IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest,
std::string fetch_result;
EXPECT_TRUE(msg_queue.WaitForMessage(&fetch_result));
EXPECT_THAT(fetch_result, ::testing::HasSubstr("BODY: runMe"));
-
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- // The main purpose of the test is not verifying the incorrect behavior
- // above, but making sure that the UMA that records the incorrect behavior
- // is logged. Hopefully the incorrect behavior will rarely occur in
- // practice.
- FetchHistogramsFromChildProcesses();
-
- // ExecuteScriptAsync covers 3 fetches:
- // - Fetching cross_site_document_blocking/html_import.html
- // - Fetching site_isolation/nosniff.json
- // All of them should result in no CORB blocking.
- auto no_blocking =
- base::Bucket(static_cast<int>(CorbVsInitiatorLock::kNoBlocking), 2);
- EXPECT_THAT(
- histograms.GetAllSamples(
- "SiteIsolation.XSD.NetworkService.InitiatorLockCompatibility"),
- ::testing::UnorderedElementsAre(no_blocking));
- }
}
}
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 9e65e50de1d..d514c10160d 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler.cc
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler.cc
@@ -125,8 +125,13 @@ void CrossSiteDocumentResourceHandler::LogBlockedResponse(
UMA_HISTOGRAM_ENUMERATION("SiteIsolation.XSD.Browser.Blocked.Others",
resource_type);
break;
- default:
+
+ case MimeType::kNeverSniffed:
+ break;
+
+ case MimeType::kInvalidMimeType:
NOTREACHED();
+ break;
}
if (analyzer_->found_parser_breaker()) {
UMA_HISTOGRAM_ENUMERATION(
@@ -231,8 +236,8 @@ void CrossSiteDocumentResourceHandler::OnRequestRedirected(
// Enforce the Cross-Origin-Resource-Policy (CORP) header.
if (network::CrossOriginResourcePolicy::kBlock ==
network::CrossOriginResourcePolicy::Verify(
- *request(), *response, fetch_request_mode_,
- kNonNetworkServiceInitiatorLock)) {
+ request()->url(), request()->initiator(), response->head,
+ fetch_request_mode_, kNonNetworkServiceInitiatorLock)) {
blocked_read_completed_ = true;
blocked_by_cross_origin_resource_policy_ = true;
controller->Cancel();
@@ -251,8 +256,8 @@ void CrossSiteDocumentResourceHandler::OnResponseStarted(
// Enforce the Cross-Origin-Resource-Policy (CORP) header.
if (network::CrossOriginResourcePolicy::kBlock ==
network::CrossOriginResourcePolicy::Verify(
- *request(), *response, fetch_request_mode_,
- kNonNetworkServiceInitiatorLock)) {
+ request()->url(), request()->initiator(), response->head,
+ fetch_request_mode_, kNonNetworkServiceInitiatorLock)) {
blocked_read_completed_ = true;
blocked_by_cross_origin_resource_policy_ = true;
controller->Cancel();
@@ -505,7 +510,7 @@ void CrossSiteDocumentResourceHandler::OnReadCompleted(
if (analyzer_->ShouldReportBlockedResponse())
info->set_should_report_corb_blocking(true);
network::CrossOriginReadBlocking::SanitizeBlockedResponse(
- pending_response_start_);
+ &pending_response_start_->head);
// Pass an empty/blocked body onto the next handler. size of the two
// buffers is the same (see OnWillRead). After the next statement,
@@ -632,8 +637,8 @@ bool CrossSiteDocumentResourceHandler::ShouldBlockBasedOnHeaders(
// Delegate most decisions to CrossOriginReadBlocking::ResponseAnalyzer.
analyzer_ =
std::make_unique<network::CrossOriginReadBlocking::ResponseAnalyzer>(
- *request(), response, kNonNetworkServiceInitiatorLock,
- fetch_request_mode_);
+ request()->url(), request()->initiator(), response.head,
+ kNonNetworkServiceInitiatorLock, fetch_request_mode_);
if (analyzer_->ShouldAllow())
return false;
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 6bc209f46d6..2a8a7ecccf8 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
@@ -1558,10 +1558,15 @@ TEST_P(CrossSiteDocumentResourceHandlerTest, ResponseBlocking) {
case MimeType::kOthers:
bucket = "Others";
break;
+ case MimeType::kNeverSniffed:
+ DCHECK_EQ(Verdict::kBlock, scenario.verdict);
+ DCHECK_EQ(-1, scenario.verdict_packet);
+ bucket = "Blocked without sniffing / no bucket";
+ break;
case MimeType::kInvalidMimeType:
DCHECK_EQ(Verdict::kAllow, scenario.verdict);
DCHECK_EQ(-1, scenario.verdict_packet);
- bucket = "No blocking = no bucket";
+ bucket = "Allowed without considering the MIME type / no bucket";
break;
}
int start_action = static_cast<int>(
@@ -1620,6 +1625,7 @@ TEST_P(CrossSiteDocumentResourceHandlerTest, ResponseBlocking) {
}
if (should_be_blocked) {
expected_counts[histogram_base + ".Blocked"] = 1;
+ expected_counts[histogram_base + ".Blocked.CanonicalMimeType"] = 1;
expected_counts[histogram_base + ".Blocked.ContentLength.WasAvailable"] = 1;
expected_counts[histogram_base + ".Blocked." + bucket] = 1;
EXPECT_THAT(histograms.GetAllSamples(histogram_base + ".Blocked"),
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.cc b/chromium/content/browser/loader/mojo_async_resource_handler.cc
index cedc99acc9a..37800b24f3f 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.cc
@@ -23,6 +23,7 @@
#include "net/base/mime_sniffer.h"
#include "net/base/net_errors.h"
#include "net/url_request/redirect_info.h"
+#include "services/network/public/cpp/constants.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/resource_scheduler.h"
@@ -30,7 +31,7 @@
namespace content {
namespace {
-int g_allocation_size = MojoAsyncResourceHandler::kDefaultAllocationSize;
+int g_allocation_size = network::kDataPipeDefaultAllocationSize;
// MimeTypeResourceHandler *implicitly* requires that the buffer size
// returned from OnWillRead should be larger than certain size.
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.h b/chromium/content/browser/loader/mojo_async_resource_handler.h
index c3dc4722736..d705c83a512 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.h
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.h
@@ -97,7 +97,6 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
std::unique_ptr<base::OneShotTimer> timer);
void OnWritableForTesting();
static void SetAllocationSizeForTesting(size_t size);
- static constexpr size_t kDefaultAllocationSize = 512 * 1024;
protected:
// These functions can be overriden only for tests.
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 c1e20b658c2..3df9e054852 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -55,6 +55,7 @@
#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/constants.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/mojom/url_loader.mojom.h"
@@ -344,7 +345,7 @@ class MojoAsyncResourceHandlerTestBase {
virtual ~MojoAsyncResourceHandlerTestBase() {
MojoAsyncResourceHandler::SetAllocationSizeForTesting(
- MojoAsyncResourceHandler::kDefaultAllocationSize);
+ network::kDataPipeDefaultAllocationSize);
base::RunLoop().RunUntilIdle();
}
@@ -1368,9 +1369,9 @@ TEST_F(MojoAsyncResourceHandlerDeferOnResponseStartedTest,
MockResourceLoader::Status result = mock_loader_->OnResponseStarted(
base::MakeRefCounted<network::ResourceResponse>());
EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING, result);
- std::unique_ptr<base::Value> request_state = request_->GetStateAsValue();
+ base::Value request_state = request_->GetStateAsValue();
base::Value* delegate_blocked_by =
- request_state->FindKey("delegate_blocked_by");
+ request_state.FindKey("delegate_blocked_by");
EXPECT_TRUE(delegate_blocked_by);
EXPECT_EQ("MojoAsyncResourceHandler", delegate_blocked_by->GetString());
}
@@ -1381,9 +1382,9 @@ TEST_F(MojoAsyncResourceHandlerDeferOnResponseStartedTest,
handler_->ProceedWithResponse();
mock_loader_->WaitUntilIdleOrCanceled();
EXPECT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
- std::unique_ptr<base::Value> request_state = request_->GetStateAsValue();
+ base::Value request_state = request_->GetStateAsValue();
base::Value* delegate_blocked_by =
- request_state->FindKey("delegate_blocked_by");
+ request_state.FindKey("delegate_blocked_by");
EXPECT_FALSE(delegate_blocked_by);
}
}
diff --git a/chromium/content/browser/loader/navigation_loader_interceptor.cc b/chromium/content/browser/loader/navigation_loader_interceptor.cc
index 2b02b49d6c8..421aefd1441 100644
--- a/chromium/content/browser/loader/navigation_loader_interceptor.cc
+++ b/chromium/content/browser/loader/navigation_loader_interceptor.cc
@@ -4,7 +4,7 @@
#include "content/browser/loader/navigation_loader_interceptor.h"
-#include "content/common/navigation_subresource_loader_params.h"
+#include "content/browser/navigation_subresource_loader_params.h"
namespace content {
diff --git a/chromium/content/browser/loader/navigation_url_loader.cc b/chromium/content/browser/loader/navigation_url_loader.cc
index f6c965e4a0c..04d7ffb0891 100644
--- a/chromium/content/browser/loader/navigation_url_loader.cc
+++ b/chromium/content/browser/loader/navigation_url_loader.cc
@@ -11,6 +11,7 @@
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/loader/navigation_url_loader_factory.h"
#include "content/browser/loader/navigation_url_loader_impl.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
#include "content/public/browser/navigation_ui_data.h"
#include "services/network/public/cpp/features.h"
@@ -25,6 +26,8 @@ std::unique_ptr<NavigationURLLoader> NavigationURLLoader::Create(
std::unique_ptr<NavigationUIData> navigation_ui_data,
ServiceWorkerNavigationHandle* service_worker_handle,
AppCacheNavigationHandle* appcache_handle,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
NavigationURLLoaderDelegate* delegate) {
if (g_loader_factory) {
return g_loader_factory->CreateLoader(
@@ -34,7 +37,8 @@ std::unique_ptr<NavigationURLLoader> NavigationURLLoader::Create(
return std::make_unique<NavigationURLLoaderImpl>(
resource_context, storage_partition, std::move(request_info),
std::move(navigation_ui_data), service_worker_handle, appcache_handle,
- delegate, std::vector<std::unique_ptr<NavigationLoaderInterceptor>>());
+ std::move(prefetched_signed_exchange_cache), delegate,
+ std::vector<std::unique_ptr<NavigationLoaderInterceptor>>());
}
void NavigationURLLoader::SetFactoryForTesting(
diff --git a/chromium/content/browser/loader/navigation_url_loader.h b/chromium/content/browser/loader/navigation_url_loader.h
index f1a36f64b74..2cc2e00da9a 100644
--- a/chromium/content/browser/loader/navigation_url_loader.h
+++ b/chromium/content/browser/loader/navigation_url_loader.h
@@ -24,6 +24,7 @@ class AppCacheNavigationHandle;
class NavigationUIData;
class NavigationURLLoaderDelegate;
class NavigationURLLoaderFactory;
+class PrefetchedSignedExchangeCache;
class ResourceContext;
class ServiceWorkerNavigationHandle;
class StoragePartition;
@@ -50,6 +51,8 @@ class CONTENT_EXPORT NavigationURLLoader {
std::unique_ptr<NavigationUIData> navigation_ui_data,
ServiceWorkerNavigationHandle* service_worker_handle,
AppCacheNavigationHandle* appcache_handle,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
NavigationURLLoaderDelegate* delegate);
// For testing purposes; sets the factory for use in testing.
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.cc b/chromium/content/browser/loader/navigation_url_loader_impl.cc
index 0010982ecf2..052c6604499 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.cc
@@ -32,8 +32,10 @@
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
#include "content/browser/loader/prefetch_url_loader_service.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/browser/navigation_subresource_loader_params.h"
#include "content/browser/resource_context_impl.h"
#include "content/browser/service_worker/service_worker_navigation_handle.h"
#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
@@ -49,7 +51,6 @@
#include "content/browser/webui/url_data_manager_backend.h"
#include "content/browser/webui/web_ui_url_loader_factory_internal.h"
#include "content/common/mime_sniffing_throttle.h"
-#include "content/common/navigation_subresource_loader_params.h"
#include "content/common/net/record_load_histograms.h"
#include "content/common/throttling_url_loader.h"
#include "content/public/browser/browser_context.h"
@@ -88,7 +89,6 @@
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
@@ -138,16 +138,6 @@ size_t GetCertificateChainsSizeInKB(const net::SSLInfo& ssl_info) {
return (cert_pickle.size() + unverified_cert_pickle.size()) / 1000;
}
-WebContents* GetWebContentsFromFrameTreeNodeID(int frame_tree_node_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- FrameTreeNode* frame_tree_node =
- FrameTreeNode::GloballyFindByID(frame_tree_node_id);
- if (!frame_tree_node)
- return nullptr;
-
- return WebContentsImpl::FromFrameTreeNode(frame_tree_node);
-}
-
const net::NetworkTrafficAnnotationTag kNavigationUrlLoaderTrafficAnnotation =
net::DefineNetworkTrafficAnnotation("navigation_url_loader", R"(
semantics {
@@ -469,6 +459,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
storage::FileSystemContext* upload_file_system_context,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
scoped_refptr<SignedExchangePrefetchMetricRecorder>
signed_exchange_prefetch_metric_recorder,
std::unique_ptr<NavigationRequestInfo> request_info,
@@ -481,7 +473,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
request_info_ = std::move(request_info);
frame_tree_node_id_ = request_info_->frame_tree_node_id;
web_contents_getter_ = base::BindRepeating(
- &GetWebContentsFromFrameTreeNodeID, frame_tree_node_id_);
+ &WebContents::FromFrameTreeNodeId, frame_tree_node_id_);
navigation_ui_data_ = std::move(navigation_ui_data);
// The ResourceDispatcherHostImpl can be null in unit tests.
ResourceDispatcherHostImpl* rph = ResourceDispatcherHostImpl::Get();
@@ -499,6 +491,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
StartInternal(request_info_.get(), service_worker_navigation_handle_core,
nullptr /* appcache_handle_core */,
+ std::move(prefetched_signed_exchange_cache),
std::move(signed_exchange_prefetch_metric_recorder),
{} /* factory_for_webui */, url_request_context_getter,
std::move(accept_langs));
@@ -509,6 +502,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
network_loader_factory_info,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
scoped_refptr<SignedExchangePrefetchMetricRecorder>
signed_exchange_prefetch_metric_recorder,
std::unique_ptr<NavigationRequestInfo> request_info,
@@ -525,8 +520,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
global_request_id_ = MakeGlobalRequestID();
frame_tree_node_id_ = frame_tree_node_id;
started_ = true;
- web_contents_getter_ =
- base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id);
+ web_contents_getter_ = base::BindRepeating(
+ &WebContents::FromFrameTreeNodeId, frame_tree_node_id);
navigation_ui_data_ = std::move(navigation_ui_data);
base::PostTaskWithTraits(
@@ -553,12 +548,12 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
resource_context_, &blob_handles_);
}
- StartInternal(request_info.get(), service_worker_navigation_handle_core,
- appcache_handle_core,
- std::move(signed_exchange_prefetch_metric_recorder),
- std::move(factory_for_webui),
- nullptr /* url_request_context_getter */,
- std::move(accept_langs));
+ StartInternal(
+ request_info.get(), service_worker_navigation_handle_core,
+ appcache_handle_core, std::move(prefetched_signed_exchange_cache),
+ std::move(signed_exchange_prefetch_metric_recorder),
+ std::move(factory_for_webui), nullptr /* url_request_context_getter */,
+ std::move(accept_langs));
}
// Common setup routines, called by both StartWithoutNetworkService() and
@@ -573,6 +568,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
NavigationRequestInfo* request_info,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
scoped_refptr<SignedExchangePrefetchMetricRecorder>
signed_exchange_prefetch_metric_recorder,
network::mojom::URLLoaderFactoryPtrInfo factory_for_webui,
@@ -614,13 +611,26 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
return;
}
+ if (prefetched_signed_exchange_cache) {
+ DCHECK(base::FeatureList::IsEnabled(
+ features::kSignedExchangeSubresourcePrefetch));
+ std::unique_ptr<NavigationLoaderInterceptor>
+ prefetched_signed_exchange_interceptor =
+ prefetched_signed_exchange_cache->MaybeCreateInterceptor(
+ request_info->common_params.url);
+ if (prefetched_signed_exchange_interceptor) {
+ interceptors_.push_back(
+ std::move(prefetched_signed_exchange_interceptor));
+ }
+ }
+
// Set-up an interceptor for service workers.
if (service_worker_navigation_handle_core) {
std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
ServiceWorkerRequestHandler::CreateForNavigation(
resource_request_->url, resource_context_,
service_worker_navigation_handle_core, *request_info,
- web_contents_getter_, &service_worker_provider_host_);
+ &service_worker_provider_host_);
// The interceptor for service worker may not be created for some reasons
// (e.g. the origin is not secure).
if (service_worker_interceptor)
@@ -893,8 +903,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
resource_request_->resource_type ==
static_cast<int>(ResourceType::kMainFrame),
static_cast<ui::PageTransition>(resource_request_->transition_type),
- resource_request_->has_user_gesture, resource_request_->method,
- resource_request_->headers, &proxied_factory_request_,
+ resource_request_->has_user_gesture, &proxied_factory_request_,
external_protocol_factory);
if (external_protocol_factory) {
@@ -1229,7 +1238,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override {}
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override {}
void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle) override {
@@ -1461,6 +1470,8 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
std::unique_ptr<NavigationUIData> navigation_ui_data,
ServiceWorkerNavigationHandle* service_worker_navigation_handle,
AppCacheNavigationHandle* appcache_handle,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
NavigationURLLoaderDelegate* delegate,
std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
initial_interceptors)
@@ -1516,6 +1527,7 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
base::Unretained(storage_partition->GetFileSystemContext()),
base::Unretained(service_worker_navigation_handle_core),
base::Unretained(appcache_handle_core),
+ std::move(prefetched_signed_exchange_cache),
base::RetainedRef(signed_exchange_prefetch_metric_recorder),
std::move(request_info), std::move(navigation_ui_data),
std::move(accept_langs)));
@@ -1641,6 +1653,7 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
std::move(network_factory_info),
service_worker_navigation_handle_core,
appcache_handle_core,
+ std::move(prefetched_signed_exchange_cache),
std::move(signed_exchange_prefetch_metric_recorder),
std::move(request_info), std::move(navigation_ui_data),
std::move(factory_for_webui), frame_tree_node_id,
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.h b/chromium/content/browser/loader/navigation_url_loader_impl.h
index d9431f01e0b..5bbcb18dcf7 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.h
@@ -25,6 +25,7 @@ namespace content {
class NavigationData;
class NavigationLoaderInterceptor;
+class PrefetchedSignedExchangeCache;
class ResourceContext;
class StoragePartition;
class StoragePartitionImpl;
@@ -41,6 +42,8 @@ class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
std::unique_ptr<NavigationUIData> navigation_ui_data,
ServiceWorkerNavigationHandle* service_worker_handle,
AppCacheNavigationHandle* appcache_handle,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
NavigationURLLoaderDelegate* delegate,
std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
initial_interceptors);
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 edf1552bb02..3f6e602e79b 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -17,6 +17,7 @@
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/loader/navigation_url_loader.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
#include "content/common/navigation_params.h"
#include "content/common/navigation_params.mojom.h"
#include "content/common/service_manager/service_manager_connection_impl.h"
@@ -170,7 +171,9 @@ class NavigationURLLoaderImplTest : public testing::Test {
headers, net::LOAD_NORMAL, false /* skip_service_worker */,
blink::mojom::RequestContextType::LOCATION,
blink::WebMixedContentContextType::kBlockable,
- false /* is_form_submission */, GURL() /* searchable_form_url */,
+ false /* is_form_submission */,
+ false /* was_initiated_by_link_click */,
+ GURL() /* searchable_form_url */,
std::string() /* searchable_form_encoding */,
GURL() /* client_side_redirect_url */,
base::nullopt /* devtools_initiator_info */);
@@ -202,7 +205,8 @@ class NavigationURLLoaderImplTest : public testing::Test {
BrowserContext::GetDefaultStoragePartition(browser_context_.get()),
std::move(request_info), nullptr /* navigation_ui_data */,
nullptr /* service_worker_handle */, nullptr /* appcache_handle */,
- delegate, std::move(interceptors));
+ nullptr /* prefetched_signed_exchange_cache */, delegate,
+ std::move(interceptors));
}
// Requests |redirect_url|, which must return a HTTP 3xx redirect. It's also
diff --git a/chromium/content/browser/loader/navigation_url_loader_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
index 69ff37246d4..747f28c9d40 100644
--- a/chromium/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
@@ -13,6 +13,7 @@
#include "base/unguessable_token.h"
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_url_loader.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/test_resource_handler.h"
#include "content/browser/loader_delegate_impl.h"
@@ -21,6 +22,7 @@
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -37,6 +39,8 @@
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/network_context.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/origin.h"
@@ -85,7 +89,9 @@ class NavigationURLLoaderTest : public testing::Test {
false /* skip_service_worker */,
blink::mojom::RequestContextType::LOCATION,
blink::WebMixedContentContextType::kBlockable,
- false /* is_form_submission */, GURL() /* searchable_form_url */,
+ false /* is_form_submission */,
+ false /* was_initiated_by_link_click */,
+ GURL() /* searchable_form_url */,
std::string() /* searchable_form_encoding */,
GURL() /* client_side_redirect_url */,
base::nullopt /* devtools_initiator_info */);
@@ -102,7 +108,7 @@ class NavigationURLLoaderTest : public testing::Test {
return NavigationURLLoader::Create(
browser_context_->GetResourceContext(),
BrowserContext::GetDefaultStoragePartition(browser_context_.get()),
- std::move(request_info), nullptr, nullptr, nullptr, delegate);
+ std::move(request_info), nullptr, nullptr, nullptr, nullptr, delegate);
}
// Helper function for fetching the body of a URL to a string.
@@ -175,13 +181,22 @@ TEST_F(NavigationURLLoaderTest, RequestFailedCertErrorFatal) {
GURL url = https_server.GetURL("/");
// Set HSTS for the test domain in order to make SSL errors fatal.
- net::TransportSecurityState* transport_security_state =
- browser_context_->GetRequestContext()
- ->GetURLRequestContext()
- ->transport_security_state();
base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000);
bool include_subdomains = false;
- transport_security_state->AddHSTS(url.host(), expiry, include_subdomains);
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ auto* storage_partition =
+ BrowserContext::GetDefaultStoragePartition(browser_context_.get());
+ base::RunLoop run_loop;
+ storage_partition->GetNetworkContext()->AddHSTS(
+ url.host(), expiry, include_subdomains, run_loop.QuitClosure());
+ run_loop.Run();
+ } else {
+ net::TransportSecurityState* transport_security_state =
+ browser_context_->GetRequestContext()
+ ->GetURLRequestContext()
+ ->transport_security_state();
+ transport_security_state->AddHSTS(url.host(), expiry, include_subdomains);
+ }
TestNavigationURLLoaderDelegate delegate;
std::unique_ptr<NavigationURLLoader> loader = MakeTestLoader(url, &delegate);
@@ -201,6 +216,10 @@ TEST_F(NavigationURLLoaderTest, RequestFailedCertErrorFatal) {
// Tests that the destroying the loader cancels the request.
TEST_F(NavigationURLLoaderTest, CancelOnDestruct) {
+ // Specific to non-NetworkService path.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
// Fake a top-level request. Choose a URL which redirects so the request can
// be paused before the response comes in.
TestNavigationURLLoaderDelegate delegate;
@@ -220,6 +239,10 @@ TEST_F(NavigationURLLoaderTest, CancelOnDestruct) {
// Test that the delegate is not called if OnResponseStarted and destroying the
// loader race.
TEST_F(NavigationURLLoaderTest, CancelResponseRace) {
+ // Specific to non-NetworkService path.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
TestNavigationURLLoaderDelegate delegate;
std::unique_ptr<NavigationURLLoader> loader = MakeTestLoader(
net::URLRequestTestJob::test_url_redirect_to_url_2(), &delegate);
@@ -241,6 +264,10 @@ TEST_F(NavigationURLLoaderTest, CancelResponseRace) {
// Tests that the loader may be canceled by context.
TEST_F(NavigationURLLoaderTest, CancelByContext) {
+ // Specific to non-NetworkService path.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
TestNavigationURLLoaderDelegate delegate;
std::unique_ptr<NavigationURLLoader> loader = MakeTestLoader(
net::URLRequestTestJob::test_url_redirect_to_url_2(), &delegate);
@@ -260,6 +287,10 @@ TEST_F(NavigationURLLoaderTest, CancelByContext) {
// Tests that the request stays alive as long as the URLLoaderClient endpoints
// are not destructed.
TEST_F(NavigationURLLoaderTest, OwnedByHandle) {
+ // Specific to non-NetworkService path.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
// Fake a top-level request to a URL whose body does not load immediately.
TestNavigationURLLoaderDelegate delegate;
std::unique_ptr<NavigationURLLoader> loader =
diff --git a/chromium/content/browser/loader/prefetch_browsertest.cc b/chromium/content/browser/loader/prefetch_browsertest.cc
index a4a8dcabb29..8fa10d51ba8 100644
--- a/chromium/content/browser/loader/prefetch_browsertest.cc
+++ b/chromium/content/browser/loader/prefetch_browsertest.cc
@@ -2,22 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <map>
#include <string>
#include <vector>
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
-#include "content/browser/loader/prefetch_url_loader_service.h"
-#include "content/browser/storage_partition_impl.h"
+#include "content/browser/loader/prefetch_browsertest_base.h"
#include "content/browser/web_package/mock_signed_exchange_handler.h"
-#include "content/browser/web_package/signed_exchange_loader.h"
-#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
@@ -27,8 +18,6 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "net/base/features.h"
-#include "net/test/embedded_test_server/http_request.h"
-#include "net/test/embedded_test_server/http_response.h"
#include "services/network/public/cpp/features.h"
namespace content {
@@ -42,130 +31,6 @@ struct PrefetchBrowserTestParam {
const bool network_service_enabled;
};
-struct ScopedSignedExchangeHandlerFactory {
- explicit ScopedSignedExchangeHandlerFactory(
- SignedExchangeHandlerFactory* factory) {
- SignedExchangeLoader::SetSignedExchangeHandlerFactoryForTest(factory);
- }
- ~ScopedSignedExchangeHandlerFactory() {
- SignedExchangeLoader::SetSignedExchangeHandlerFactoryForTest(nullptr);
- }
-};
-
-class PrefetchBrowserTestBase : public ContentBrowserTest {
- public:
- struct ResponseEntry {
- ResponseEntry() = default;
- explicit ResponseEntry(
- const std::string& content,
- const std::string& content_type = "text/html",
- const std::vector<std::pair<std::string, std::string>>& headers = {})
- : content(content), content_type(content_type), headers(headers) {}
- ~ResponseEntry() = default;
- std::string content;
- std::string content_type;
- std::vector<std::pair<std::string, std::string>> headers;
- };
- PrefetchBrowserTestBase() = default;
- ~PrefetchBrowserTestBase() override = default;
-
- void SetUpOnMainThread() override {
- ContentBrowserTest::SetUpOnMainThread();
- StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
- BrowserContext::GetDefaultStoragePartition(
- shell()->web_contents()->GetBrowserContext()));
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- BindOnce(
- &PrefetchURLLoaderService::RegisterPrefetchLoaderCallbackForTest,
- base::RetainedRef(partition->GetPrefetchURLLoaderService()),
- base::BindRepeating(
- &PrefetchBrowserTestBase::OnPrefetchURLLoaderCalled,
- base::Unretained(this))));
- }
-
- protected:
- void RegisterResponse(const std::string& url, const ResponseEntry& entry) {
- response_map_[url] = entry;
- }
-
- std::unique_ptr<net::test_server::HttpResponse> ServeResponses(
- const net::test_server::HttpRequest& request) {
- auto found = response_map_.find(request.relative_url);
- if (found != response_map_.end()) {
- auto response = std::make_unique<net::test_server::BasicHttpResponse>();
- response->set_code(net::HTTP_OK);
- response->set_content(found->second.content);
- response->set_content_type(found->second.content_type);
- for (const auto& header : found->second.headers) {
- response->AddCustomHeader(header.first, header.second);
- }
- return std::move(response);
- }
- return nullptr;
- }
-
- void WatchURLAndRunClosure(
- const std::string& relative_url,
- int* visit_count,
- base::OnceClosure closure,
- const net::test_server::HttpRequest& request) {
- if (request.relative_url == relative_url) {
- (*visit_count)++;
- if (closure)
- std::move(closure).Run();
- }
- }
-
- void OnPrefetchURLLoaderCalled() { prefetch_url_loader_called_++; }
-
- void RegisterRequestMonitor(net::EmbeddedTestServer* test_server,
- const std::string& path,
- int* count,
- base::RunLoop* waiter) {
- test_server->RegisterRequestMonitor(base::BindRepeating(
- &PrefetchBrowserTestBase::WatchURLAndRunClosure, base::Unretained(this),
- path, count,
- waiter ? waiter->QuitClosure() : base::RepeatingClosure()));
- }
-
- void RegisterRequestHandler(net::EmbeddedTestServer* test_server) {
- test_server->RegisterRequestHandler(base::BindRepeating(
- &PrefetchBrowserTestBase::ServeResponses, base::Unretained(this)));
- }
-
- void NavigateToURLAndWaitTitle(const GURL& url, const std::string& title) {
- base::string16 title16 = base::ASCIIToUTF16(title);
- TitleWatcher title_watcher(shell()->web_contents(), title16);
- // Execute the JavaScript code to triger the followup navigation from the
- // current page.
- EXPECT_TRUE(ExecuteScript(
- shell()->web_contents(),
- base::StringPrintf("location.href = '%s';", url.spec().c_str())));
- EXPECT_EQ(title16, title_watcher.WaitAndGetTitle());
- }
-
- void WaitUntilLoaded(const GURL& url) {
- int entry_count = 0;
- while (entry_count == 0) {
- const bool result = ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- base::StringPrintf("window.domAutomationController.send("
- "performance.getEntriesByName('%s').length);",
- url.spec().c_str()),
- &entry_count);
- ASSERT_TRUE(result);
- }
- }
-
- int prefetch_url_loader_called_ = 0;
-
- private:
- std::map<std::string, ResponseEntry> response_map_;
-
- DISALLOW_COPY_AND_ASSIGN(PrefetchBrowserTestBase);
-};
-
class PrefetchBrowserTest
: public PrefetchBrowserTestBase,
public testing::WithParamInterface<PrefetchBrowserTestParam> {
@@ -514,7 +379,8 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) {
target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
GURL(embedded_test_server()->GetURL(target_path)), "text/html",
{base::StringPrintf("Link: <%s>;rel=\"preload\";as=\"script\"",
- preload_url_in_sxg.spec().c_str())})});
+ preload_url_in_sxg.spec().c_str())},
+ net::SHA256HashValue({{0x00}}))});
ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
// Loading a page that prefetches the target URL would increment both
@@ -586,7 +452,8 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, CrossOriginWebPackageWithPreload) {
target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
GURL(cross_origin_server_->GetURL(target_path)), "text/html",
{base::StringPrintf("Link: <%s>;rel=\"preload\";as=\"script\"",
- preload_url_in_sxg.spec().c_str())})});
+ preload_url_in_sxg.spec().c_str())},
+ net::SHA256HashValue({{0x00}}))});
ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
// Loading a page that prefetches the target URL would increment both
@@ -623,107 +490,4 @@ INSTANTIATE_TEST_SUITE_P(PrefetchBrowserTest,
PrefetchBrowserTestParam(true, false),
PrefetchBrowserTestParam(true, true)));
-class SignedExchangeSubresourcePrefetchBrowserTest
- : public PrefetchBrowserTestBase,
- public testing::WithParamInterface<PrefetchBrowserTestParam> {
- public:
- SignedExchangeSubresourcePrefetchBrowserTest() = default;
- ~SignedExchangeSubresourcePrefetchBrowserTest() = default;
-
- void SetUp() override {
- std::vector<base::Feature> enable_features;
- std::vector<base::Feature> disabled_features;
- enable_features.push_back(features::kSignedHTTPExchange);
- enable_features.push_back(features::kSignedExchangeSubresourcePrefetch);
- if (GetParam().network_service_enabled) {
- enable_features.push_back(network::features::kNetworkService);
- } else {
- disabled_features.push_back(network::features::kNetworkService);
- }
- feature_list_.InitWithFeatures(enable_features, disabled_features);
- PrefetchBrowserTestBase::SetUp();
- }
-
- private:
- base::test::ScopedFeatureList feature_list_;
-
- DISALLOW_COPY_AND_ASSIGN(SignedExchangeSubresourcePrefetchBrowserTest);
-};
-
-IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
- PrefetchAlternativeSubresourceSXG) {
- int script_sxg_fetch_count = 0;
- const char* prefetch_path = "/prefetch.html";
- const char* target_sxg_path = "/target.sxg";
- const char* target_path = "/target.html";
- const char* script_path_in_sxg = "/script.js";
- const char* script_sxg_path = "/script_js.sxg";
-
- base::RunLoop script_sxg_prefetch_waiter;
- RegisterRequestMonitor(embedded_test_server(), script_sxg_path,
- &script_sxg_fetch_count, &script_sxg_prefetch_waiter);
- RegisterRequestHandler(embedded_test_server());
- ASSERT_TRUE(embedded_test_server()->Start());
- EXPECT_EQ(0, prefetch_url_loader_called_);
-
- const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
- const GURL target_url = embedded_test_server()->GetURL(target_path);
- const GURL script_sxg_url = embedded_test_server()->GetURL(script_sxg_path);
- const GURL script_url = embedded_test_server()->GetURL(script_path_in_sxg);
-
- const std::string outer_link_header = base::StringPrintf(
- "<%s>;"
- "rel=\"alternate\";"
- "type=\"application/signed-exchange;v=b3\";"
- "anchor=\"%s\"",
- script_sxg_url.spec().c_str(), script_url.spec().c_str());
- const std::string inner_link_headers = base::StringPrintf(
- "Link: <%s>;"
- "rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
- "<%s>;rel=\"preload\";as=\"script\"",
- script_url.spec().c_str(),
- // This is just a dummy data as of now.
- // TODO(crbug.com/935267): When we will implement the header integrity
- // checking logic, add tests for it.
- "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- script_url.spec().c_str());
-
- RegisterResponse(
- prefetch_path,
- ResponseEntry(base::StringPrintf(
- "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
- RegisterResponse(
- target_sxg_path,
- // We mock the SignedExchangeHandler, so just return a HTML content
- // as "application/signed-exchange;v=b3".
- ResponseEntry("<head><title>Prefetch Target (SXG)</title><script "
- "src=\"./preload.js\"></script></head>",
- "application/signed-exchange;v=b3",
- {{"x-content-type-options", "nosniff"},
- {"link", outer_link_header}}));
- RegisterResponse(script_sxg_path,
- // We mock the SignedExchangeHandler, so just return a JS
- // content as "application/signed-exchange;v=b3".
- ResponseEntry("document.title=\"done\";",
- "application/signed-exchange;v=b3",
- {{"x-content-type-options", "nosniff"}}));
-
- MockSignedExchangeHandlerFactory factory(
- {MockSignedExchangeHandlerParams(
- target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
- target_url, "text/html", {inner_link_headers}),
- MockSignedExchangeHandlerParams(
- script_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
- script_url, "text/javascript", {})});
- ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
-
- NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
- script_sxg_prefetch_waiter.Run();
- EXPECT_EQ(1, script_sxg_fetch_count);
-}
-
-INSTANTIATE_TEST_SUITE_P(SignedExchangeSubresourcePrefetchBrowserTest,
- SignedExchangeSubresourcePrefetchBrowserTest,
- testing::Values(PrefetchBrowserTestParam(true, false),
- PrefetchBrowserTestParam(true, true)));
} // namespace content
diff --git a/chromium/content/browser/loader/prefetch_browsertest_base.cc b/chromium/content/browser/loader/prefetch_browsertest_base.cc
new file mode 100644
index 00000000000..e39eafd18d9
--- /dev/null
+++ b/chromium/content/browser/loader/prefetch_browsertest_base.cc
@@ -0,0 +1,154 @@
+// Copyright 2019 The Chromium Authors. All rights 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/prefetch_browsertest_base.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "content/browser/loader/prefetch_url_loader_service.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/browser/web_package/signed_exchange_handler.h"
+#include "content/browser/web_package/signed_exchange_loader.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/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"
+
+namespace content {
+
+PrefetchBrowserTestBase::ResponseEntry::ResponseEntry() = default;
+
+PrefetchBrowserTestBase::ResponseEntry::ResponseEntry(
+ const std::string& content,
+ const std::string& content_type,
+ const std::vector<std::pair<std::string, std::string>>& headers)
+ : content(content), content_type(content_type), headers(headers) {}
+
+PrefetchBrowserTestBase::ResponseEntry::~ResponseEntry() = default;
+
+PrefetchBrowserTestBase::ScopedSignedExchangeHandlerFactory::
+ ScopedSignedExchangeHandlerFactory(SignedExchangeHandlerFactory* factory) {
+ SignedExchangeLoader::SetSignedExchangeHandlerFactoryForTest(factory);
+}
+
+PrefetchBrowserTestBase::ScopedSignedExchangeHandlerFactory::
+ ~ScopedSignedExchangeHandlerFactory() {
+ SignedExchangeLoader::SetSignedExchangeHandlerFactoryForTest(nullptr);
+}
+
+PrefetchBrowserTestBase::PrefetchBrowserTestBase() = default;
+PrefetchBrowserTestBase::~PrefetchBrowserTestBase() = default;
+
+void PrefetchBrowserTestBase::SetUpOnMainThread() {
+ ContentBrowserTest::SetUpOnMainThread();
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(
+ shell()->web_contents()->GetBrowserContext()));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(
+ &PrefetchURLLoaderService::RegisterPrefetchLoaderCallbackForTest,
+ base::RetainedRef(partition->GetPrefetchURLLoaderService()),
+ base::BindRepeating(
+ &PrefetchBrowserTestBase::OnPrefetchURLLoaderCalled,
+ base::Unretained(this))));
+}
+
+void PrefetchBrowserTestBase::RegisterResponse(const std::string& url,
+ const ResponseEntry& entry) {
+ response_map_[url] = entry;
+}
+
+std::unique_ptr<net::test_server::HttpResponse>
+PrefetchBrowserTestBase::ServeResponses(
+ const net::test_server::HttpRequest& request) {
+ auto found = response_map_.find(request.relative_url);
+ if (found != response_map_.end()) {
+ auto response = std::make_unique<net::test_server::BasicHttpResponse>();
+ response->set_code(net::HTTP_OK);
+ response->set_content(found->second.content);
+ response->set_content_type(found->second.content_type);
+ for (const auto& header : found->second.headers) {
+ response->AddCustomHeader(header.first, header.second);
+ }
+ return std::move(response);
+ }
+ return nullptr;
+}
+
+void PrefetchBrowserTestBase::WatchURLAndRunClosure(
+ const std::string& relative_url,
+ int* visit_count,
+ base::OnceClosure closure,
+ const net::test_server::HttpRequest& request) {
+ if (request.relative_url == relative_url) {
+ (*visit_count)++;
+ if (closure)
+ std::move(closure).Run();
+ }
+}
+
+void PrefetchBrowserTestBase::OnPrefetchURLLoaderCalled() {
+ prefetch_url_loader_called_++;
+}
+
+void PrefetchBrowserTestBase::RegisterRequestMonitor(
+ net::EmbeddedTestServer* test_server,
+ const std::string& path,
+ int* count,
+ base::RunLoop* waiter) {
+ test_server->RegisterRequestMonitor(base::BindRepeating(
+ &PrefetchBrowserTestBase::WatchURLAndRunClosure, base::Unretained(this),
+ path, count, waiter ? waiter->QuitClosure() : base::RepeatingClosure()));
+}
+
+void PrefetchBrowserTestBase::RegisterRequestHandler(
+ net::EmbeddedTestServer* test_server) {
+ test_server->RegisterRequestHandler(base::BindRepeating(
+ &PrefetchBrowserTestBase::ServeResponses, base::Unretained(this)));
+}
+
+void PrefetchBrowserTestBase::NavigateToURLAndWaitTitle(
+ const GURL& url,
+ const std::string& title) {
+ base::string16 title16 = base::ASCIIToUTF16(title);
+ TitleWatcher title_watcher(shell()->web_contents(), title16);
+ // Execute the JavaScript code to triger the followup navigation from the
+ // current page.
+ EXPECT_TRUE(ExecuteScript(
+ shell()->web_contents(),
+ base::StringPrintf("location.href = '%s';", url.spec().c_str())));
+ EXPECT_EQ(title16, title_watcher.WaitAndGetTitle());
+}
+
+void PrefetchBrowserTestBase::WaitUntilLoaded(const GURL& url) {
+ bool result = false;
+ ASSERT_TRUE(
+ ExecuteScriptAndExtractBool(shell()->web_contents(),
+ base::StringPrintf(R"(
+new Promise((resolve) => {
+ const url = '%s';
+ if (performance.getEntriesByName(url).length > 0) {
+ resolve();
+ return;
+ }
+ new PerformanceObserver((list) => {
+ if (list.getEntriesByName(url).length > 0) {
+ resolve();
+ }
+ }).observe({ entryTypes: ['resource'] });
+}).then(() => {
+ window.domAutomationController.send(true);
+}))",
+ url.spec().c_str()),
+ &result));
+ ASSERT_TRUE(result);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/prefetch_browsertest_base.h b/chromium/content/browser/loader/prefetch_browsertest_base.h
new file mode 100644
index 00000000000..0a755cd2dd0
--- /dev/null
+++ b/chromium/content/browser/loader/prefetch_browsertest_base.h
@@ -0,0 +1,84 @@
+// Copyright 2019 The Chromium Authors. All rights 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_PREFETCH_BROWSERTEST_BASE_H_
+#define CONTENT_BROWSER_LOADER_PREFETCH_BROWSERTEST_BASE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "content/public/test/content_browser_test.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
+
+namespace net {
+namespace test_server {
+class EmbeddedTestServer;
+struct HttpRequest;
+} // namespace test_server
+} // namespace net
+
+namespace content {
+
+class SignedExchangeHandlerFactory;
+
+class PrefetchBrowserTestBase : public ContentBrowserTest {
+ public:
+ struct ResponseEntry {
+ ResponseEntry();
+ explicit ResponseEntry(
+ const std::string& content,
+ const std::string& content_types = "text/html",
+ const std::vector<std::pair<std::string, std::string>>& headers = {});
+ ~ResponseEntry();
+
+ std::string content;
+ std::string content_type;
+ std::vector<std::pair<std::string, std::string>> headers;
+ };
+
+ struct ScopedSignedExchangeHandlerFactory {
+ explicit ScopedSignedExchangeHandlerFactory(
+ SignedExchangeHandlerFactory* factory);
+ ~ScopedSignedExchangeHandlerFactory();
+ };
+
+ PrefetchBrowserTestBase();
+ ~PrefetchBrowserTestBase() override;
+
+ void SetUpOnMainThread() override;
+
+ protected:
+ void RegisterResponse(const std::string& url, const ResponseEntry& entry);
+
+ std::unique_ptr<net::test_server::HttpResponse> ServeResponses(
+ const net::test_server::HttpRequest& request);
+ void WatchURLAndRunClosure(const std::string& relative_url,
+ int* visit_count,
+ base::OnceClosure closure,
+ const net::test_server::HttpRequest& request);
+ void OnPrefetchURLLoaderCalled();
+ void RegisterRequestMonitor(net::test_server::EmbeddedTestServer* test_server,
+ const std::string& path,
+ int* count,
+ base::RunLoop* waiter);
+
+ void RegisterRequestHandler(
+ net::test_server::EmbeddedTestServer* test_server);
+ void NavigateToURLAndWaitTitle(const GURL& url, const std::string& title);
+ void WaitUntilLoaded(const GURL& url);
+
+ int prefetch_url_loader_called_ = 0;
+
+ private:
+ std::map<std::string, ResponseEntry> response_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrefetchBrowserTestBase);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_PREFETCH_BROWSERTEST_BASE_H_
diff --git a/chromium/content/browser/loader/prefetch_url_loader.cc b/chromium/content/browser/loader/prefetch_url_loader.cc
index 26f4b94716d..9847bc6466f 100644
--- a/chromium/content/browser/loader/prefetch_url_loader.cc
+++ b/chromium/content/browser/loader/prefetch_url_loader.cc
@@ -6,6 +6,8 @@
#include "base/bind.h"
#include "base/feature_list.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache_adapter.h"
#include "content/browser/web_package/signed_exchange_prefetch_handler.h"
#include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h"
#include "content/browser/web_package/signed_exchange_utils.h"
@@ -38,6 +40,9 @@ PrefetchURLLoader::PrefetchURLLoader(
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<SignedExchangePrefetchMetricRecorder>
signed_exchange_prefetch_metric_recorder,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
const std::string& accept_langs)
: frame_tree_node_id_getter_(frame_tree_node_id_getter),
resource_request_(resource_request),
@@ -58,6 +63,15 @@ PrefetchURLLoader::PrefetchURLLoader(
// (https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#internet-media-type-applicationsigned-exchange).
resource_request_.headers.SetHeader(
network::kAcceptHeader, kSignedExchangeEnabledAcceptHeaderForPrefetch);
+
+ if (prefetched_signed_exchange_cache) {
+ DCHECK(base::FeatureList::IsEnabled(
+ features::kSignedExchangeSubresourcePrefetch));
+ prefetched_signed_exchange_cache_adapter_ =
+ std::make_unique<PrefetchedSignedExchangeCacheAdapter>(
+ std::move(prefetched_signed_exchange_cache),
+ std::move(blob_storage_context), resource_request.url, this);
+ }
}
network::mojom::URLLoaderClientPtr network_client;
@@ -125,7 +139,10 @@ void PrefetchURLLoader::OnReceiveResponse(
signed_exchange_utils::ShouldHandleAsSignedHTTPExchange(
resource_request_.url, response)) {
DCHECK(!signed_exchange_prefetch_handler_);
-
+ if (prefetched_signed_exchange_cache_adapter_) {
+ prefetched_signed_exchange_cache_adapter_->OnReceiveOuterResponse(
+ response);
+ }
// Note that after this point this doesn't directly get upcalls from the
// network. (Until |this| calls the handler's FollowRedirect.)
signed_exchange_prefetch_handler_ =
@@ -137,12 +154,24 @@ void PrefetchURLLoader::OnReceiveResponse(
signed_exchange_prefetch_metric_recorder_, accept_langs_);
return;
}
+ if (prefetched_signed_exchange_cache_adapter_ &&
+ signed_exchange_prefetch_handler_) {
+ prefetched_signed_exchange_cache_adapter_->OnReceiveInnerResponse(response);
+ }
+
forwarding_client_->OnReceiveResponse(response);
}
void PrefetchURLLoader::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) {
+ if (prefetched_signed_exchange_cache_adapter_ &&
+ signed_exchange_prefetch_handler_) {
+ prefetched_signed_exchange_cache_adapter_->OnReceiveRedirect(
+ redirect_info.new_url,
+ signed_exchange_prefetch_handler_->ComputeHeaderIntegrity());
+ }
+
resource_request_.url = redirect_info.new_url;
resource_request_.site_for_cookies = redirect_info.new_site_for_cookies;
resource_request_.top_frame_origin = redirect_info.new_top_frame_origin;
@@ -158,8 +187,7 @@ void PrefetchURLLoader::OnUploadProgress(int64_t current_position,
std::move(callback));
}
-void PrefetchURLLoader::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
+void PrefetchURLLoader::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
// Just drop this; we don't need to forward this to the renderer
// for prefetch.
}
@@ -170,30 +198,52 @@ void PrefetchURLLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
void PrefetchURLLoader::OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) {
+ if (prefetched_signed_exchange_cache_adapter_ &&
+ signed_exchange_prefetch_handler_) {
+ prefetched_signed_exchange_cache_adapter_->OnStartLoadingResponseBody(
+ std::move(body));
+ return;
+ }
+
// Just drain the original response's body here.
DCHECK(!pipe_drainer_);
pipe_drainer_ =
std::make_unique<mojo::DataPipeDrainer>(this, std::move(body));
- // Send an empty response's body instead.
- mojo::ScopedDataPipeProducerHandle producer;
- mojo::ScopedDataPipeConsumerHandle consumer;
- if (CreateDataPipe(nullptr, &producer, &consumer) == MOJO_RESULT_OK) {
- forwarding_client_->OnStartLoadingResponseBody(std::move(consumer));
+ SendEmptyBody();
+}
+
+void PrefetchURLLoader::OnComplete(
+ const network::URLLoaderCompletionStatus& status) {
+ if (prefetched_signed_exchange_cache_adapter_ &&
+ signed_exchange_prefetch_handler_) {
+ prefetched_signed_exchange_cache_adapter_->OnComplete(status);
return;
}
- // No more resources available for creating a data pipe. Close the connection,
- // which will in turn make this loader destroyed.
- forwarding_client_->OnComplete(
- network::URLLoaderCompletionStatus(net::ERR_INSUFFICIENT_RESOURCES));
- forwarding_client_.reset();
- client_binding_.Close();
+ SendOnComplete(status);
}
-void PrefetchURLLoader::OnComplete(
- const network::URLLoaderCompletionStatus& status) {
- forwarding_client_->OnComplete(status);
+bool PrefetchURLLoader::SendEmptyBody() {
+ // Send an empty response's body.
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ if (CreateDataPipe(nullptr, &producer, &consumer) != MOJO_RESULT_OK) {
+ // No more resources available for creating a data pipe. Close the
+ // connection, which will in turn make this loader destroyed.
+ forwarding_client_->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_INSUFFICIENT_RESOURCES));
+ forwarding_client_.reset();
+ client_binding_.Close();
+ return false;
+ }
+ forwarding_client_->OnStartLoadingResponseBody(std::move(consumer));
+ return true;
+}
+
+void PrefetchURLLoader::SendOnComplete(
+ const network::URLLoaderCompletionStatus& completion_status) {
+ forwarding_client_->OnComplete(completion_status);
}
void PrefetchURLLoader::OnNetworkConnectionError() {
diff --git a/chromium/content/browser/loader/prefetch_url_loader.h b/chromium/content/browser/loader/prefetch_url_loader.h
index 6397e3b94ac..7a57f64077f 100644
--- a/chromium/content/browser/loader/prefetch_url_loader.h
+++ b/chromium/content/browser/loader/prefetch_url_loader.h
@@ -10,8 +10,10 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/unguessable_token.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/data_pipe_drainer.h"
@@ -20,6 +22,10 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "url/gurl.h"
+namespace storage {
+class BlobStorageContext;
+} // namespace storage
+
namespace net {
class URLRequestContextGetter;
}
@@ -32,6 +38,7 @@ namespace content {
class ResourceContext;
class URLLoaderThrottle;
+class PrefetchedSignedExchangeCacheAdapter;
class SignedExchangePrefetchHandler;
class SignedExchangePrefetchMetricRecorder;
@@ -63,9 +70,20 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<SignedExchangePrefetchMetricRecorder>
signed_exchange_prefetch_metric_recorder,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
const std::string& accept_langs);
~PrefetchURLLoader() override;
+ // Sends an empty response's body to |forwarding_client_|. If failed to create
+ // a new data pipe, sends ERR_INSUFFICIENT_RESOURCES and closes the
+ // connection, and returns false. Otherwise returns true.
+ bool SendEmptyBody();
+
+ void SendOnComplete(
+ const network::URLLoaderCompletionStatus& completion_status);
+
private:
// network::mojom::URLLoader overrides:
void FollowRedirect(const std::vector<std::string>& removed_headers,
@@ -84,7 +102,7 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
void OnUploadProgress(int64_t current_position,
int64_t total_size,
base::OnceCallback<void()> callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
@@ -124,6 +142,12 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
scoped_refptr<SignedExchangePrefetchMetricRecorder>
signed_exchange_prefetch_metric_recorder_;
+
+ // Used when SignedExchangeSubresourcePrefetch is enabled to store the
+ // prefetched signed exchanges to a PrefetchedSignedExchangeCache.
+ std::unique_ptr<PrefetchedSignedExchangeCacheAdapter>
+ prefetched_signed_exchange_cache_adapter_;
+
const std::string accept_langs_;
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 e590369d5d1..927a7a0d37f 100644
--- a/chromium/content/browser/loader/prefetch_url_loader_service.cc
+++ b/chromium/content/browser/loader/prefetch_url_loader_service.cc
@@ -7,7 +7,9 @@
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/time/default_tick_clock.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/loader/prefetch_url_loader.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/web_contents.h"
@@ -19,23 +21,32 @@
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "storage/browser/blob/blob_storage_context.h"
#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
namespace content {
struct PrefetchURLLoaderService::BindContext {
BindContext(int frame_tree_node_id,
- scoped_refptr<network::SharedURLLoaderFactory> factory)
- : frame_tree_node_id(frame_tree_node_id), factory(factory) {}
+ scoped_refptr<network::SharedURLLoaderFactory> factory,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache)
+ : frame_tree_node_id(frame_tree_node_id),
+ factory(factory),
+ prefetched_signed_exchange_cache(
+ std::move(prefetched_signed_exchange_cache)) {}
explicit BindContext(const std::unique_ptr<BindContext>& other)
: frame_tree_node_id(other->frame_tree_node_id),
- factory(other->factory) {}
+ factory(other->factory),
+ prefetched_signed_exchange_cache(
+ other->prefetched_signed_exchange_cache) {}
~BindContext() = default;
const int frame_tree_node_id;
scoped_refptr<network::SharedURLLoaderFactory> factory;
+ scoped_refptr<PrefetchedSignedExchangeCache> prefetched_signed_exchange_cache;
};
PrefetchURLLoaderService::PrefetchURLLoaderService(
@@ -57,25 +68,31 @@ PrefetchURLLoaderService::PrefetchURLLoaderService(
void PrefetchURLLoaderService::InitializeResourceContext(
ResourceContext* resource_context,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ ChromeBlobStorageContext* blob_storage_context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!resource_context_);
DCHECK(!request_context_getter_);
resource_context_ = resource_context;
request_context_getter_ = request_context_getter;
+ blob_storage_context_ = blob_storage_context->context()->AsWeakPtr();
preference_watcher_binding_.Bind(std::move(preference_watcher_request_));
}
void PrefetchURLLoaderService::GetFactory(
network::mojom::URLLoaderFactoryRequest request,
int frame_tree_node_id,
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> factories) {
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> factories,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto factory_bundle =
network::SharedURLLoaderFactory::Create(std::move(factories));
loader_factory_bindings_.AddBinding(
this, std::move(request),
- std::make_unique<BindContext>(frame_tree_node_id, factory_bundle));
+ std::make_unique<BindContext>(
+ frame_tree_node_id, factory_bundle,
+ std::move(prefetched_signed_exchange_cache)));
}
void PrefetchURLLoaderService::CreateLoaderAndStart(
@@ -96,6 +113,13 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
if (prefetch_load_callback_for_testing_)
prefetch_load_callback_for_testing_.Run();
+ scoped_refptr<PrefetchedSignedExchangeCache> prefetched_signed_exchange_cache;
+ if (loader_factory_bindings_.dispatch_context()) {
+ prefetched_signed_exchange_cache =
+ loader_factory_bindings_.dispatch_context()
+ ->prefetched_signed_exchange_cache;
+ }
+
// For now we strongly bind the loader to the request, while we can
// also possibly make the new loader owned by the factory so that
// they can live longer than the client (i.e. run in detached mode).
@@ -109,7 +133,9 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
&PrefetchURLLoaderService::CreateURLLoaderThrottles, this,
resource_request, frame_tree_node_id_getter),
resource_context_, request_context_getter_,
- signed_exchange_prefetch_metric_recorder_, accept_langs_),
+ signed_exchange_prefetch_metric_recorder_,
+ std::move(prefetched_signed_exchange_cache), blob_storage_context_,
+ accept_langs_),
std::move(request));
}
diff --git a/chromium/content/browser/loader/prefetch_url_loader_service.h b/chromium/content/browser/loader/prefetch_url_loader_service.h
index 6352f159bdf..cd6a930c6fb 100644
--- a/chromium/content/browser/loader/prefetch_url_loader_service.h
+++ b/chromium/content/browser/loader/prefetch_url_loader_service.h
@@ -18,6 +18,10 @@
#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
#include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
+namespace storage {
+class BlobStorageContext;
+}
+
namespace net {
class URLRequestContextGetter;
}
@@ -29,6 +33,8 @@ class SharedURLLoaderFactory;
namespace content {
class BrowserContext;
+class ChromeBlobStorageContext;
+class PrefetchedSignedExchangeCache;
class ResourceContext;
class URLLoaderFactoryGetter;
class URLLoaderThrottle;
@@ -45,12 +51,15 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
// be valid as far as request_context_getter returns non-null context.
void InitializeResourceContext(
ResourceContext* resource_context,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter);
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ ChromeBlobStorageContext* blob_storage_context);
void GetFactory(
network::mojom::URLLoaderFactoryRequest request,
int frame_tree_node_id,
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> factory_info);
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> factory_info,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache);
// Used only when NetworkService is not enabled (or indirectly via the
// other CreateLoaderAndStart when NetworkService is enabled).
@@ -132,6 +141,11 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
std::string accept_langs_;
+ // Used to create a BlobDataHandle from a DataPipe of signed exchange's inner
+ // response body to store to |prefetched_signed_exchange_cache_| when
+ // SignedExchangeSubresourcePrefetch is enabled.
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
+
DISALLOW_COPY_AND_ASSIGN(PrefetchURLLoaderService);
};
diff --git a/chromium/content/browser/loader/prefetched_signed_exchange_cache.cc b/chromium/content/browser/loader/prefetched_signed_exchange_cache.cc
new file mode 100644
index 00000000000..d1056e3d3d6
--- /dev/null
+++ b/chromium/content/browser/loader/prefetched_signed_exchange_cache.cc
@@ -0,0 +1,571 @@
+// Copyright 2019 The Chromium Authors. All rights 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/prefetched_signed_exchange_cache.h"
+
+#include "base/feature_list.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/loader/cross_origin_read_blocking_checker.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
+#include "content/browser/navigation_subresource_loader_params.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_features.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "net/http/http_util.h"
+#include "net/url_request/redirect_util.h"
+#include "services/network/public/cpp/constants.h"
+#include "services/network/public/cpp/cors/cors.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_impl.h"
+#include "storage/browser/blob/mojo_blob_reader.h"
+
+namespace content {
+
+namespace {
+
+// The max number of cached entry per one frame. This limit is intended to
+// prevent OOM crash of the browser process.
+constexpr size_t kMaxEntrySize = 100u;
+
+void UpdateRequestResponseStartTime(
+ network::ResourceResponseHead* response_head) {
+ const base::TimeTicks now_ticks = base::TimeTicks::Now();
+ const base::Time now = base::Time::Now();
+ response_head->request_start = now_ticks;
+ response_head->response_start = now_ticks;
+ response_head->load_timing.request_start_time = now;
+ response_head->load_timing.request_start = now_ticks;
+}
+
+// A utility subclass of MojoBlobReader::Delegate that calls the passed callback
+// in OnComplete().
+class MojoBlobReaderDelegate : public storage::MojoBlobReader::Delegate {
+ public:
+ explicit MojoBlobReaderDelegate(base::OnceCallback<void(net::Error)> callback)
+ : callback_(std::move(callback)) {}
+
+ private:
+ // storage::MojoBlobReader::Delegate
+ RequestSideData DidCalculateSize(uint64_t total_size,
+ uint64_t content_size) override {
+ return DONT_REQUEST_SIDE_DATA;
+ }
+
+ void OnComplete(net::Error result, uint64_t total_written_bytes) override {
+ std::move(callback_).Run(result);
+ }
+
+ base::OnceCallback<void(net::Error)> callback_;
+};
+
+// A URLLoader which returns a synthesized redirect response for signed
+// exchange's outer URL request.
+class RedirectResponseURLLoader : public network::mojom::URLLoader {
+ public:
+ RedirectResponseURLLoader(const network::ResourceRequest& url_request,
+ const GURL& inner_url,
+ const network::ResourceResponseHead& outer_response,
+ network::mojom::URLLoaderClientPtr client)
+ : client_(std::move(client)) {
+ network::ResourceResponseHead response_head =
+ signed_exchange_utils::CreateRedirectResponseHead(
+ outer_response, false /* is_fallback_redirect */);
+ response_head.was_in_prefetch_cache = true;
+ UpdateRequestResponseStartTime(&response_head);
+ client_->OnReceiveRedirect(signed_exchange_utils::CreateRedirectInfo(
+ inner_url, url_request, outer_response,
+ false /* is_fallback_redirect */),
+ response_head);
+ }
+ ~RedirectResponseURLLoader() override {}
+
+ private:
+ // network::mojom::URLLoader overrides:
+ void FollowRedirect(const std::vector<std::string>& removed_headers,
+ const net::HttpRequestHeaders& modified_headers,
+ const base::Optional<GURL>& new_url) override {
+ NOTREACHED();
+ }
+ void ProceedWithResponse() override { NOTREACHED(); }
+ void SetPriority(net::RequestPriority priority,
+ int intra_priority_value) override {
+ // There is nothing to do, because this class just calls OnReceiveRedirect.
+ }
+ void PauseReadingBodyFromNet() override {
+ // There is nothing to do, because we don't fetch the resource from the
+ // network.
+ }
+ void ResumeReadingBodyFromNet() override {
+ // There is nothing to do, because we don't fetch the resource from the
+ // network.
+ }
+
+ network::mojom::URLLoaderClientPtr client_;
+
+ DISALLOW_COPY_AND_ASSIGN(RedirectResponseURLLoader);
+};
+
+// A URLLoader which returns the inner response of signed exchange.
+class InnerResponseURLLoader : public network::mojom::URLLoader {
+ public:
+ InnerResponseURLLoader(
+ const network::ResourceRequest& request,
+ const network::ResourceResponseHead& inner_response,
+ const url::Origin& request_initiator_site_lock,
+ std::unique_ptr<const storage::BlobDataHandle> blob_data_handle,
+ const network::URLLoaderCompletionStatus& completion_status,
+ network::mojom::URLLoaderClientPtr client,
+ bool is_navigation_request)
+ : response_(inner_response),
+ blob_data_handle_(std::move(blob_data_handle)),
+ completion_status_(completion_status),
+ client_(std::move(client)),
+ weak_factory_(this) {
+ DCHECK(response_.headers);
+ DCHECK(request.request_initiator);
+
+ UpdateRequestResponseStartTime(&response_);
+ response_.encoded_data_length = 0;
+ if (is_navigation_request) {
+ client_->OnReceiveResponse(response_);
+ // When Network Service is not enabled, we need to wait
+ // ProceedWithResponse for navigation request. See
+ // https://crbug.com/791049.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ SendResponseBody();
+ return;
+ }
+
+ if (network::cors::ShouldCheckCors(request.url, request.request_initiator,
+ request.fetch_request_mode)) {
+ const auto error_status = network::cors::CheckAccess(
+ request.url, response_.headers->response_code(),
+ GetHeaderString(
+ response_,
+ network::cors::header_names::kAccessControlAllowOrigin),
+ GetHeaderString(
+ response_,
+ network::cors::header_names::kAccessControlAllowCredentials),
+ request.fetch_credentials_mode, *request.request_initiator);
+ if (error_status) {
+ client_->OnComplete(network::URLLoaderCompletionStatus(*error_status));
+ return;
+ }
+ }
+
+ corb_checker_ = std::make_unique<CrossOriginReadBlockingChecker>(
+ request, response_, request_initiator_site_lock, *blob_data_handle_,
+ base::BindOnce(
+ &InnerResponseURLLoader::OnCrossOriginReadBlockingCheckComplete,
+ base::Unretained(this)));
+ }
+ ~InnerResponseURLLoader() override {}
+
+ private:
+ static base::Optional<std::string> GetHeaderString(
+ const network::ResourceResponseHead& response,
+ const std::string& header_name) {
+ DCHECK(response.headers);
+ std::string header_value;
+ if (!response.headers->GetNormalizedHeader(header_name, &header_value))
+ return base::nullopt;
+ return header_value;
+ }
+
+ void OnCrossOriginReadBlockingCheckComplete(
+ CrossOriginReadBlockingChecker::Result result) {
+ switch (result) {
+ case CrossOriginReadBlockingChecker::Result::kAllowed:
+ client_->OnReceiveResponse(response_);
+ SendResponseBody();
+ return;
+ case CrossOriginReadBlockingChecker::Result::kNetError:
+ client_->OnComplete(
+ network::URLLoaderCompletionStatus(corb_checker_->GetNetError()));
+ return;
+ case CrossOriginReadBlockingChecker::Result::kBlocked_ShouldReport:
+ break;
+ case CrossOriginReadBlockingChecker::Result::kBlocked_ShouldNotReport:
+ break;
+ }
+
+ // Send sanitized response.
+ network::CrossOriginReadBlocking::SanitizeBlockedResponse(&response_);
+ client_->OnReceiveResponse(response_);
+
+ // Send an empty response's body.
+ mojo::ScopedDataPipeProducerHandle pipe_producer_handle;
+ mojo::ScopedDataPipeConsumerHandle pipe_consumer_handle;
+ MojoResult rv = mojo::CreateDataPipe(nullptr, &pipe_producer_handle,
+ &pipe_consumer_handle);
+ if (rv != MOJO_RESULT_OK) {
+ client_->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_INSUFFICIENT_RESOURCES));
+ return;
+ }
+ client_->OnStartLoadingResponseBody(std::move(pipe_consumer_handle));
+
+ // Send a dummy OnComplete message.
+ network::URLLoaderCompletionStatus status =
+ network::URLLoaderCompletionStatus(net::OK);
+ status.should_report_corb_blocking =
+ result == CrossOriginReadBlockingChecker::Result::kBlocked_ShouldReport;
+ client_->OnComplete(status);
+ }
+
+ // network::mojom::URLLoader overrides:
+ void FollowRedirect(const std::vector<std::string>& removed_headers,
+ const net::HttpRequestHeaders& modified_headers,
+ const base::Optional<GURL>& new_url) override {
+ NOTREACHED();
+ }
+ void ProceedWithResponse() override {
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+ SendResponseBody();
+ }
+ void SetPriority(net::RequestPriority priority,
+ int intra_priority_value) override {
+ // There is nothing to do, because there is no prioritization mechanism for
+ // reading a blob.
+ }
+ void PauseReadingBodyFromNet() override {
+ // There is nothing to do, because we don't fetch the resource from the
+ // network.
+ }
+ void ResumeReadingBodyFromNet() override {
+ // There is nothing to do, because we don't fetch the resource from the
+ // network.
+ }
+
+ void SendResponseBody() {
+ mojo::ScopedDataPipeProducerHandle pipe_producer_handle;
+ mojo::ScopedDataPipeConsumerHandle pipe_consumer_handle;
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(MojoCreateDataPipeOptions);
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+ options.element_num_bytes = 1;
+ options.capacity_num_bytes = network::kDataPipeDefaultAllocationSize;
+ MojoResult rv = mojo::CreateDataPipe(&options, &pipe_producer_handle,
+ &pipe_consumer_handle);
+ if (rv != MOJO_RESULT_OK) {
+ client_->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_INSUFFICIENT_RESOURCES));
+ return;
+ }
+
+ storage::MojoBlobReader::Create(
+ blob_data_handle_.get(), net::HttpByteRange(),
+ std::make_unique<MojoBlobReaderDelegate>(
+ base::BindOnce(&InnerResponseURLLoader::BlobReaderComplete,
+ weak_factory_.GetWeakPtr())),
+ std::move(pipe_producer_handle));
+
+ client_->OnStartLoadingResponseBody(std::move(pipe_consumer_handle));
+ }
+
+ void BlobReaderComplete(net::Error result) {
+ network::URLLoaderCompletionStatus status;
+ if (result == net::OK) {
+ status = completion_status_;
+ status.exists_in_cache = true;
+ status.completion_time = base::TimeTicks::Now();
+ status.encoded_data_length = 0;
+ } else {
+ status = network::URLLoaderCompletionStatus(status);
+ }
+ client_->OnComplete(status);
+ }
+
+ network::ResourceResponseHead response_;
+ std::unique_ptr<const storage::BlobDataHandle> blob_data_handle_;
+ const network::URLLoaderCompletionStatus completion_status_;
+ network::mojom::URLLoaderClientPtr client_;
+ std::unique_ptr<CrossOriginReadBlockingChecker> corb_checker_;
+
+ base::WeakPtrFactory<InnerResponseURLLoader> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(InnerResponseURLLoader);
+};
+
+// A URLLoaderFactory which handles a signed exchange subresource request from
+// renderer process.
+class SubresourceSignedExchangeURLLoaderFactory
+ : public network::mojom::URLLoaderFactory {
+ public:
+ SubresourceSignedExchangeURLLoaderFactory(
+ network::mojom::URLLoaderFactoryRequest request,
+ std::unique_ptr<const PrefetchedSignedExchangeCache::Entry> entry,
+ const url::Origin& request_initiator_site_lock)
+ : entry_(std::move(entry)),
+ request_initiator_site_lock_(request_initiator_site_lock) {
+ bindings_.AddBinding(this, std::move(request));
+ bindings_.set_connection_error_handler(base::BindRepeating(
+ &SubresourceSignedExchangeURLLoaderFactory::OnConnectionError,
+ base::Unretained(this)));
+ }
+ ~SubresourceSignedExchangeURLLoaderFactory() override {}
+
+ // 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 {
+ DCHECK_EQ(request.url, entry_->inner_url());
+ mojo::MakeStrongBinding(
+ std::make_unique<InnerResponseURLLoader>(
+ request, *entry_->inner_response(), request_initiator_site_lock_,
+ std::make_unique<const storage::BlobDataHandle>(
+ *entry_->blob_data_handle()),
+ *entry_->completion_status(), std::move(client),
+ false /* is_navigation_request */),
+ std::move(loader));
+ }
+ void Clone(network::mojom::URLLoaderFactoryRequest request) override {
+ bindings_.AddBinding(this, std::move(request));
+ }
+
+ private:
+ void OnConnectionError() {
+ if (!bindings_.empty())
+ return;
+ delete this;
+ }
+
+ std::unique_ptr<const PrefetchedSignedExchangeCache::Entry> entry_;
+ const url::Origin request_initiator_site_lock_;
+ mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
+
+ DISALLOW_COPY_AND_ASSIGN(SubresourceSignedExchangeURLLoaderFactory);
+};
+
+// A NavigationLoaderInterceptor which handles a request which matches the
+// prefetched signed exchange that has been stored to a
+// PrefetchedSignedExchangeCache.
+class PrefetchedNavigationLoaderInterceptor
+ : public NavigationLoaderInterceptor {
+ public:
+ PrefetchedNavigationLoaderInterceptor(
+ std::unique_ptr<const PrefetchedSignedExchangeCache::Entry> exchange,
+ std::vector<PrefetchedSignedExchangeInfo> info_list)
+ : exchange_(std::move(exchange)),
+ info_list_(std::move(info_list)),
+ weak_factory_(this) {}
+
+ ~PrefetchedNavigationLoaderInterceptor() override {}
+
+ void MaybeCreateLoader(
+ const network::ResourceRequest& tentative_resource_request,
+ ResourceContext* resource_context,
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) override {
+ // Currently we just check the URL matching. But we should check the Vary
+ // header (eg: HttpVaryData::MatchesRequest()) and Cache-Control header.
+ // And also we shuold check the expires parameter of the signed exchange's
+ // signature. TODO(crbug.com/935267): Implement these checking logic.
+ if (state_ == State::kInitial &&
+ tentative_resource_request.url == exchange_->outer_url()) {
+ state_ = State::kOuterRequestRequested;
+ std::move(callback).Run(base::BindOnce(
+ &PrefetchedNavigationLoaderInterceptor::StartRedirectResponse,
+ weak_factory_.GetWeakPtr()));
+ return;
+ }
+ if (tentative_resource_request.url == exchange_->inner_url()) {
+ DCHECK_EQ(State::kOuterRequestRequested, state_);
+ state_ = State::kInnerResponseRequested;
+ std::move(callback).Run(base::BindOnce(
+ &PrefetchedNavigationLoaderInterceptor::StartInnerResponse,
+ weak_factory_.GetWeakPtr()));
+ return;
+ }
+ NOTREACHED();
+ }
+
+ base::Optional<SubresourceLoaderParams> MaybeCreateSubresourceLoaderParams()
+ override {
+ if (state_ != State::kInnerResponseRequested)
+ return base::nullopt;
+
+ SubresourceLoaderParams params;
+ params.prefetched_signed_exchanges = std::move(info_list_);
+ return base::make_optional(std::move(params));
+ }
+
+ private:
+ enum class State {
+ kInitial,
+ kOuterRequestRequested,
+ kInnerResponseRequested
+ };
+
+ void StartRedirectResponse(const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderRequest request,
+ network::mojom::URLLoaderClientPtr client) {
+ mojo::MakeStrongBinding(
+ std::make_unique<RedirectResponseURLLoader>(
+ resource_request, exchange_->inner_url(),
+ *exchange_->outer_response(), std::move(client)),
+ std::move(request));
+ }
+
+ void StartInnerResponse(const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderRequest request,
+ network::mojom::URLLoaderClientPtr client) {
+ mojo::MakeStrongBinding(
+ std::make_unique<InnerResponseURLLoader>(
+ resource_request, *exchange_->inner_response(),
+ url::Origin::Create(exchange_->inner_url()),
+ std::make_unique<const storage::BlobDataHandle>(
+ *exchange_->blob_data_handle()),
+ *exchange_->completion_status(), std::move(client),
+ true /* is_navigation_request */),
+ std::move(request));
+ }
+
+ State state_ = State::kInitial;
+ std::unique_ptr<const PrefetchedSignedExchangeCache::Entry> exchange_;
+ std::vector<PrefetchedSignedExchangeInfo> info_list_;
+
+ base::WeakPtrFactory<PrefetchedNavigationLoaderInterceptor> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrefetchedNavigationLoaderInterceptor);
+};
+
+} // namespace
+
+PrefetchedSignedExchangeCache::Entry::Entry() = default;
+PrefetchedSignedExchangeCache::Entry::~Entry() = default;
+
+void PrefetchedSignedExchangeCache::Entry::SetOuterUrl(const GURL& outer_url) {
+ outer_url_ = outer_url;
+}
+void PrefetchedSignedExchangeCache::Entry::SetOuterResponse(
+ std::unique_ptr<const network::ResourceResponseHead> outer_response) {
+ outer_response_ = std::move(outer_response);
+}
+void PrefetchedSignedExchangeCache::Entry::SetHeaderIntegrity(
+ std::unique_ptr<const net::SHA256HashValue> header_integrity) {
+ header_integrity_ = std::move(header_integrity);
+}
+void PrefetchedSignedExchangeCache::Entry::SetInnerUrl(const GURL& inner_url) {
+ inner_url_ = inner_url;
+}
+void PrefetchedSignedExchangeCache::Entry::SetInnerResponse(
+ std::unique_ptr<const network::ResourceResponseHead> inner_response) {
+ inner_response_ = std::move(inner_response);
+}
+void PrefetchedSignedExchangeCache::Entry::SetCompletionStatus(
+ std::unique_ptr<const network::URLLoaderCompletionStatus>
+ completion_status) {
+ completion_status_ = std::move(completion_status);
+}
+void PrefetchedSignedExchangeCache::Entry::SetBlobDataHandle(
+ std::unique_ptr<const storage::BlobDataHandle> blob_data_handle) {
+ blob_data_handle_ = std::move(blob_data_handle);
+}
+
+std::unique_ptr<const PrefetchedSignedExchangeCache::Entry>
+PrefetchedSignedExchangeCache::Entry::Clone() const {
+ DCHECK(outer_url().is_valid());
+ DCHECK(outer_response());
+ DCHECK(header_integrity());
+ DCHECK(inner_url().is_valid());
+ DCHECK(inner_response());
+ DCHECK(completion_status());
+ DCHECK(blob_data_handle());
+
+ std::unique_ptr<Entry> clone = std::make_unique<Entry>();
+ clone->SetOuterUrl(outer_url_);
+ clone->SetOuterResponse(
+ std::make_unique<const network::ResourceResponseHead>(*outer_response_));
+ clone->SetHeaderIntegrity(
+ std::make_unique<const net::SHA256HashValue>(*header_integrity_));
+ clone->SetInnerUrl(inner_url_);
+ clone->SetInnerResponse(
+ std::make_unique<const network::ResourceResponseHead>(*inner_response_));
+ clone->SetCompletionStatus(
+ std::make_unique<const network::URLLoaderCompletionStatus>(
+ *completion_status_));
+ clone->SetBlobDataHandle(
+ std::make_unique<const storage::BlobDataHandle>(*blob_data_handle_));
+ return clone;
+}
+
+PrefetchedSignedExchangeCache::PrefetchedSignedExchangeCache() {
+ DCHECK(base::FeatureList::IsEnabled(
+ features::kSignedExchangeSubresourcePrefetch));
+}
+
+PrefetchedSignedExchangeCache::~PrefetchedSignedExchangeCache() {}
+
+void PrefetchedSignedExchangeCache::Store(
+ std::unique_ptr<const Entry> cached_exchange) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (exchanges_.size() > kMaxEntrySize)
+ return;
+ DCHECK(cached_exchange->outer_url().is_valid());
+ DCHECK(cached_exchange->outer_response());
+ DCHECK(cached_exchange->header_integrity());
+ DCHECK(cached_exchange->inner_url().is_valid());
+ DCHECK(cached_exchange->inner_response());
+ DCHECK(cached_exchange->completion_status());
+ DCHECK(cached_exchange->blob_data_handle());
+ const GURL outer_url = cached_exchange->outer_url();
+ exchanges_[outer_url] = std::move(cached_exchange);
+}
+
+std::unique_ptr<NavigationLoaderInterceptor>
+PrefetchedSignedExchangeCache::MaybeCreateInterceptor(const GURL& outer_url) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const auto it = exchanges_.find(outer_url);
+ if (it == exchanges_.end())
+ return nullptr;
+ return std::make_unique<PrefetchedNavigationLoaderInterceptor>(
+ it->second->Clone(),
+ GetInfoListForNavigation(outer_url, it->second->inner_url()));
+}
+
+std::vector<PrefetchedSignedExchangeInfo>
+PrefetchedSignedExchangeCache::GetInfoListForNavigation(
+ const GURL& outer_url,
+ const GURL& inner_url) const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::vector<PrefetchedSignedExchangeInfo> info_list;
+ const url::Origin outer_url_origin = url::Origin::Create(outer_url);
+ const url::Origin inner_url_origin = url::Origin::Create(inner_url);
+
+ for (const auto& exchanges_it : exchanges_) {
+ const std::unique_ptr<const Entry>& exchange = exchanges_it.second;
+ if (!outer_url_origin.IsSameOriginWith(
+ url::Origin::Create(exchange->outer_url()))) {
+ // Restrict the main SXG and the subresources SXGs to be served from the
+ // same origin.
+ continue;
+ }
+ network::mojom::URLLoaderFactoryPtrInfo loader_factory_info;
+ new SubresourceSignedExchangeURLLoaderFactory(
+ mojo::MakeRequest(&loader_factory_info), exchange->Clone(),
+ inner_url_origin);
+ info_list.emplace_back(
+ exchange->outer_url(), *exchange->header_integrity(),
+ exchange->inner_url(), *exchange->inner_response(),
+ std::move(loader_factory_info).PassHandle().release());
+ }
+ return info_list;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/prefetched_signed_exchange_cache.h b/chromium/content/browser/loader/prefetched_signed_exchange_cache.h
new file mode 100644
index 00000000000..c6856dc8895
--- /dev/null
+++ b/chromium/content/browser/loader/prefetched_signed_exchange_cache.h
@@ -0,0 +1,123 @@
+// Copyright 2019 The Chromium Authors. All rights 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_PREFETCHED_SIGNED_EXCHANGE_CACHE_H_
+#define CONTENT_BROWSER_LOADER_PREFETCHED_SIGNED_EXCHANGE_CACHE_H_
+
+#include <map>
+
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "content/common/prefetched_signed_exchange_info.h"
+#include "net/base/hash_value.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "url/gurl.h"
+
+namespace net {
+struct SHA256HashValue;
+} // namespace net
+
+namespace network {
+struct ResourceResponseHead;
+struct URLLoaderCompletionStatus;
+} // namespace network
+
+namespace storage {
+class BlobDataHandle;
+} // namespace storage
+
+namespace content {
+
+class NavigationLoaderInterceptor;
+
+// PrefetchedSignedExchangeCache keeps prefetched and verified signed
+// exchanges.
+class CONTENT_EXPORT PrefetchedSignedExchangeCache
+ : public base::RefCountedThreadSafe<PrefetchedSignedExchangeCache> {
+ public:
+ class CONTENT_EXPORT Entry {
+ public:
+ Entry();
+ ~Entry();
+
+ const GURL& outer_url() const { return outer_url_; }
+ const std::unique_ptr<const network::ResourceResponseHead>& outer_response()
+ const {
+ return outer_response_;
+ }
+ const std::unique_ptr<const net::SHA256HashValue>& header_integrity()
+ const {
+ return header_integrity_;
+ }
+ const GURL& inner_url() const { return inner_url_; }
+ const std::unique_ptr<const network::ResourceResponseHead>& inner_response()
+ const {
+ return inner_response_;
+ }
+ const std::unique_ptr<const network::URLLoaderCompletionStatus>&
+ completion_status() const {
+ return completion_status_;
+ }
+ const std::unique_ptr<const storage::BlobDataHandle>& blob_data_handle()
+ const {
+ return blob_data_handle_;
+ }
+
+ void SetOuterUrl(const GURL& outer_url);
+ void SetOuterResponse(
+ std::unique_ptr<const network::ResourceResponseHead> outer_response);
+ void SetHeaderIntegrity(
+ std::unique_ptr<const net::SHA256HashValue> header_integrity);
+ void SetInnerUrl(const GURL& inner_url);
+ void SetInnerResponse(
+ std::unique_ptr<const network::ResourceResponseHead> inner_response);
+ void SetCompletionStatus(
+ std::unique_ptr<const network::URLLoaderCompletionStatus>
+ completion_status);
+ void SetBlobDataHandle(
+ std::unique_ptr<const storage::BlobDataHandle> blob_data_handle);
+
+ std::unique_ptr<const Entry> Clone() const;
+
+ private:
+ GURL outer_url_;
+ std::unique_ptr<const network::ResourceResponseHead> outer_response_;
+ std::unique_ptr<const net::SHA256HashValue> header_integrity_;
+ GURL inner_url_;
+ std::unique_ptr<const network::ResourceResponseHead> inner_response_;
+ std::unique_ptr<const network::URLLoaderCompletionStatus>
+ completion_status_;
+ std::unique_ptr<const storage::BlobDataHandle> blob_data_handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(Entry);
+ };
+
+ PrefetchedSignedExchangeCache();
+
+ void Store(std::unique_ptr<const Entry> cached_exchange);
+
+ std::unique_ptr<NavigationLoaderInterceptor> MaybeCreateInterceptor(
+ const GURL& outer_url);
+
+ private:
+ friend class base::RefCountedThreadSafe<PrefetchedSignedExchangeCache>;
+ friend class SignedExchangeSubresourcePrefetchBrowserTest;
+
+ using EntryMap = std::map<GURL /* outer_url */, std::unique_ptr<const Entry>>;
+
+ ~PrefetchedSignedExchangeCache();
+ std::vector<PrefetchedSignedExchangeInfo> GetInfoListForNavigation(
+ const GURL& outer_url,
+ const GURL& inner_url) const;
+
+ EntryMap exchanges_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrefetchedSignedExchangeCache);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_PREFETCHED_SIGNED_EXCHANGE_CACHE_H_
diff --git a/chromium/content/browser/loader/prefetched_signed_exchange_cache_adapter.cc b/chromium/content/browser/loader/prefetched_signed_exchange_cache_adapter.cc
new file mode 100644
index 00000000000..4bbfaa1ae76
--- /dev/null
+++ b/chromium/content/browser/loader/prefetched_signed_exchange_cache_adapter.cc
@@ -0,0 +1,116 @@
+// Copyright 2019 The Chromium Authors. All rights 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/prefetched_signed_exchange_cache_adapter.h"
+
+#include "content/browser/loader/prefetch_url_loader.h"
+#include "storage/browser/blob/blob_builder_from_stream.h"
+#include "storage/browser/blob/blob_data_handle.h"
+
+namespace content {
+
+PrefetchedSignedExchangeCacheAdapter::PrefetchedSignedExchangeCacheAdapter(
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ const GURL& request_url,
+ PrefetchURLLoader* prefetch_url_loader)
+ : prefetched_signed_exchange_cache_(
+ std::move(prefetched_signed_exchange_cache)),
+ blob_storage_context_(std::move(blob_storage_context)),
+ cached_exchange_(
+ std::make_unique<PrefetchedSignedExchangeCache::Entry>()),
+ prefetch_url_loader_(prefetch_url_loader) {
+ cached_exchange_->SetOuterUrl(request_url);
+}
+
+PrefetchedSignedExchangeCacheAdapter::~PrefetchedSignedExchangeCacheAdapter() {
+ if (blob_builder_from_stream_)
+ blob_builder_from_stream_->Abort();
+}
+
+void PrefetchedSignedExchangeCacheAdapter::OnReceiveOuterResponse(
+ const network::ResourceResponseHead& response) {
+ cached_exchange_->SetOuterResponse(
+ std::make_unique<network::ResourceResponseHead>(response));
+}
+
+void PrefetchedSignedExchangeCacheAdapter::OnReceiveRedirect(
+ const GURL& new_url,
+ const base::Optional<net::SHA256HashValue> header_integrity) {
+ DCHECK(header_integrity);
+ cached_exchange_->SetHeaderIntegrity(
+ std::make_unique<net::SHA256HashValue>(*header_integrity));
+ cached_exchange_->SetInnerUrl(new_url);
+}
+
+void PrefetchedSignedExchangeCacheAdapter::OnReceiveInnerResponse(
+ const network::ResourceResponseHead& response) {
+ std::unique_ptr<network::ResourceResponseHead> inner_response =
+ std::make_unique<network::ResourceResponseHead>(response);
+ inner_response->was_in_prefetch_cache = true;
+ cached_exchange_->SetInnerResponse(std::move(inner_response));
+}
+
+void PrefetchedSignedExchangeCacheAdapter::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) {
+ DCHECK(cached_exchange_->inner_response());
+ DCHECK(!cached_exchange_->completion_status());
+ DCHECK(blob_storage_context_);
+ uint64_t length_hint = 0;
+ if (cached_exchange_->inner_response()->content_length > 0) {
+ length_hint = cached_exchange_->inner_response()->content_length;
+ }
+ blob_builder_from_stream_ = std::make_unique<storage::BlobBuilderFromStream>(
+ blob_storage_context_, "" /* content_type */,
+ "" /* content_disposition */,
+ base::BindOnce(&PrefetchedSignedExchangeCacheAdapter::StreamingBlobDone,
+ base::Unretained(this)));
+ blob_builder_from_stream_->Start(length_hint, std::move(body),
+ nullptr /* progress_client */);
+}
+
+void PrefetchedSignedExchangeCacheAdapter::OnComplete(
+ const network::URLLoaderCompletionStatus& status) {
+ cached_exchange_->SetCompletionStatus(
+ std::make_unique<network::URLLoaderCompletionStatus>(status));
+ MaybeCallOnSignedExchangeStored();
+}
+
+void PrefetchedSignedExchangeCacheAdapter::StreamingBlobDone(
+ storage::BlobBuilderFromStream* builder,
+ std::unique_ptr<storage::BlobDataHandle> result) {
+ blob_builder_from_stream_.reset();
+ cached_exchange_->SetBlobDataHandle(std::move(result));
+ MaybeCallOnSignedExchangeStored();
+}
+
+void PrefetchedSignedExchangeCacheAdapter::MaybeCallOnSignedExchangeStored() {
+ if (!cached_exchange_->completion_status() || blob_builder_from_stream_) {
+ return;
+ }
+
+ const network::URLLoaderCompletionStatus completion_status =
+ *cached_exchange_->completion_status();
+
+ // When SignedExchangePrefetchHandler failed to load the response (eg: invalid
+ // signed exchange format), the inner response is not set. In that case, we
+ // don't send the body to avoid the DCHECK() failure in URLLoaderClientImpl::
+ // OnStartLoadingResponseBody().
+ const bool should_send_body = cached_exchange_->inner_response().get();
+
+ if (completion_status.error_code == net::OK &&
+ cached_exchange_->blob_data_handle() &&
+ cached_exchange_->blob_data_handle()->size()) {
+ prefetched_signed_exchange_cache_->Store(std::move(cached_exchange_));
+ }
+
+ if (should_send_body) {
+ if (!prefetch_url_loader_->SendEmptyBody())
+ return;
+ }
+ prefetch_url_loader_->SendOnComplete(completion_status);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/prefetched_signed_exchange_cache_adapter.h b/chromium/content/browser/loader/prefetched_signed_exchange_cache_adapter.h
new file mode 100644
index 00000000000..18619c497f0
--- /dev/null
+++ b/chromium/content/browser/loader/prefetched_signed_exchange_cache_adapter.h
@@ -0,0 +1,77 @@
+// Copyright 2019 The Chromium Authors. All rights 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_PREFETCHED_SIGNED_EXCHANGE_CACHE_ADAPTER_H_
+#define CONTENT_BROWSER_LOADER_PREFETCHED_SIGNED_EXCHANGE_CACHE_ADAPTER_H_
+
+#include "base/optional.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+
+class GURL;
+
+namespace net {
+struct SHA256HashValue;
+}
+
+namespace storage {
+class BlobBuilderFromStream;
+class BlobDataHandle;
+} // namespace storage
+
+namespace content {
+class PrefetchURLLoader;
+
+// This class is used by PrefetchURLLoader to store the prefetched and verified
+// signed exchanges to the PrefetchedSignedExchangeCache.
+class PrefetchedSignedExchangeCacheAdapter {
+ public:
+ PrefetchedSignedExchangeCacheAdapter(
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ const GURL& request_url,
+ PrefetchURLLoader* prefetch_url_loader);
+ ~PrefetchedSignedExchangeCacheAdapter();
+
+ void OnReceiveOuterResponse(const network::ResourceResponseHead& response);
+ void OnReceiveRedirect(
+ const GURL& new_url,
+ const base::Optional<net::SHA256HashValue> header_integrity);
+ void OnReceiveInnerResponse(const network::ResourceResponseHead& response);
+ void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle body);
+ void OnComplete(const network::URLLoaderCompletionStatus& status);
+
+ private:
+ void StreamingBlobDone(storage::BlobBuilderFromStream* builder,
+ std::unique_ptr<storage::BlobDataHandle> result);
+
+ void MaybeCallOnSignedExchangeStored();
+
+ // Holds the prefetched signed exchanges which will be used in the next
+ // navigation. This is shared with RenderFrameHostImpl that created this.
+ const scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache_;
+
+ // Used to create a BlobDataHandle from a DataPipe of signed exchange's inner
+ // response body to store to |prefetched_signed_exchange_cache_|.
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
+
+ // A temporary entry of PrefetchedSignedExchangeCache, which will be stored
+ // to |prefetched_signed_exchange_cache_|.
+ std::unique_ptr<PrefetchedSignedExchangeCache::Entry> cached_exchange_;
+
+ // Used to create a BlobDataHandle from a DataPipe of signed exchange's inner
+ // response body.
+ std::unique_ptr<storage::BlobBuilderFromStream> blob_builder_from_stream_;
+
+ // |prefetch_url_loader_| owns |this|.
+ PrefetchURLLoader* prefetch_url_loader_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrefetchedSignedExchangeCacheAdapter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_PREFETCHED_SIGNED_EXCHANGE_CACHE_ADAPTER_H_
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index 289e7d0e40d..934dee87c44 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -52,6 +52,7 @@
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/loader/resource_requester_info.h"
+#include "content/browser/loader/sec_fetch_site_resource_handler.h"
#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"
@@ -105,7 +106,6 @@
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/resource_request_body.h"
#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"
@@ -336,7 +336,7 @@ class ResourceDispatcherHostImpl::ScheduledResourceRequestAdapter final
void WillStartRequest(bool* defer) override {
request_->WillStartRequest(defer);
}
- const char* GetNameForLogging() const override { return "ResourceScheduler"; }
+ const char* GetNameForLogging() override { return "ResourceScheduler"; }
private:
std::unique_ptr<network::ResourceScheduler::ScheduledResourceRequest>
@@ -374,7 +374,6 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl(
kMaxOutstandingRequestsCostPerProcess),
delegate_(nullptr),
loader_delegate_(nullptr),
- allow_cross_origin_auth_prompt_(false),
create_download_handler_intercept_(download_handler_intercept),
main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
io_thread_task_runner_(io_thread_runner),
@@ -418,10 +417,6 @@ void ResourceDispatcherHostImpl::SetDelegate(
delegate_ = delegate;
}
-void ResourceDispatcherHostImpl::SetAllowCrossOriginAuthPrompt(bool value) {
- allow_cross_origin_auth_prompt_ = value;
-}
-
void ResourceDispatcherHostImpl::CancelRequestsForContext(
ResourceContext* context) {
DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
@@ -633,8 +628,7 @@ bool ResourceDispatcherHostImpl::HandleExternalProtocol(ResourceLoader* loader,
return GetContentClient()->browser()->HandleExternalProtocol(
url, info->GetWebContentsGetterForRequest(), info->GetChildID(),
info->GetNavigationUIData(), info->IsMainFrame(),
- info->GetPageTransition(), info->HasUserGesture(), url_request->method(),
- url_request->extra_request_headers(), nullptr, dummy);
+ info->GetPageTransition(), info->HasUserGesture(), nullptr, dummy);
}
void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) {
@@ -721,7 +715,6 @@ void ResourceDispatcherHostImpl::OnRequestResourceInternal(
network::mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK(requester_info->IsRenderer() ||
- requester_info->IsNavigationPreload() ||
requester_info->IsCertificateFetcherForSignedExchange());
BeginRequest(requester_info, request_id, request_data, is_sync_load,
routing_id, url_loader_options, std::move(mojo_request),
@@ -753,7 +746,6 @@ void ResourceDispatcherHostImpl::BeginRequest(
network::mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK(requester_info->IsRenderer() ||
- requester_info->IsNavigationPreload() ||
requester_info->IsCertificateFetcherForSignedExchange());
int child_id = requester_info->child_id();
@@ -883,7 +875,6 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
const net::NetworkTrafficAnnotationTag& traffic_annotation,
HeaderInterceptorResult interceptor_result) {
DCHECK(requester_info->IsRenderer() ||
- requester_info->IsNavigationPreload() ||
requester_info->IsCertificateFetcherForSignedExchange());
// The request is always for a subresource.
// The renderer process is killed in BeginRequest() when it happens with a
@@ -906,7 +897,6 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
}
int child_id = requester_info->child_id();
storage::BlobStorageContext* blob_context = nullptr;
- bool do_not_prompt_for_login = false;
bool report_raw_headers = false;
bool report_security_info = false;
int load_flags = request_data.load_flags;
@@ -929,15 +919,6 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
std::unique_ptr<net::URLRequest> new_request = request_context->CreateRequest(
request_data.url, request_data.priority, nullptr, traffic_annotation);
- // Log that this request is a service worker navigation preload request
- // here, since navigation preload machinery has no access to netlog.
- // TODO(falken): Figure out how network::mojom::URLLoaderClient can
- // access the request's netlog.
- if (requester_info->IsNavigationPreload()) {
- new_request->net_log().AddEvent(
- net::NetLogEventType::SERVICE_WORKER_NAVIGATION_PRELOAD_REQUEST);
- }
-
new_request->set_method(request_data.method);
new_request->set_site_for_cookies(request_data.site_for_cookies);
new_request->set_top_frame_origin(request_data.top_frame_origin);
@@ -982,8 +963,6 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
.get()));
}
- do_not_prompt_for_login = request_data.do_not_prompt_for_login;
-
// Raw headers are sensitive, as they include Cookie/Set-Cookie, so only
// allow requesting them if requester has ReadRawCookies permission.
ChildProcessSecurityPolicyImpl* policy =
@@ -993,13 +972,8 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
// values), so |report_security_info| is not subject to the extra security
// checks that are applied to |report_raw_headers|.
report_security_info = request_data.report_raw_headers;
- if (report_raw_headers && !policy->CanReadRawCookies(child_id) &&
- !requester_info->IsNavigationPreload()) {
- // For navigation preload, the child_id is -1 so CanReadRawCookies would
- // return false. But |report_raw_headers| of the navigation preload
- // request was copied from the original request, so this check has already
- // been carried out.
- // TODO: https://crbug.com/523063 can we call
+ if (report_raw_headers && !policy->CanReadRawCookies(child_id)) {
+ // TODO(https://crbug.com/523063): can we call
// bad_message::ReceivedBadMessage here?
VLOG(1) << "Denied unauthorized request for raw headers";
report_raw_headers = false;
@@ -1012,20 +986,6 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
report_raw_headers = false;
}
- if (DoNotPromptForLogin(static_cast<ResourceType>(request_data.resource_type),
- request_data.url, request_data.site_for_cookies)) {
- // Prevent third-party image content from prompting for login, as this
- // is often a scam to extract credentials for another domain from the
- // user. Only block image loads, as the attack applies largely to the
- // "src" property of the <img> tag. It is common for web properties to
- // allow untrusted values for <img src>; this is considered a fair thing
- // for an HTML sanitizer to do. Conversely, any HTML sanitizer that didn't
- // filter sources for <script>, <link>, <embed>, <object>, <iframe> tags
- // would be considered vulnerable in and of itself.
- do_not_prompt_for_login = true;
- load_flags |= net::LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
- }
-
// Sync loads should have maximum priority and should be the only
// requets that have the ignore limits flag set.
if (is_sync_load) {
@@ -1057,7 +1017,7 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
false, // is stream
ResourceInterceptPolicy::kAllowNone, request_data.has_user_gesture,
request_data.enable_load_timing, request_data.enable_upload_progress,
- do_not_prompt_for_login, request_data.keepalive,
+ request_data.do_not_prompt_for_login, request_data.keepalive,
Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
request_data.referrer_policy),
request_data.is_prerendering, resource_context, report_raw_headers,
@@ -1079,8 +1039,8 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
// Have the appcache associate its extra info with the request.
AppCacheInterceptor::SetExtraRequestInfo(
- new_request.get(), requester_info->appcache_service(), child_id,
- request_data.appcache_host_id,
+ new_request.get(), requester_info->appcache_service(),
+ request_data.appcache_host_id.value_or(base::UnguessableToken()),
static_cast<ResourceType>(request_data.resource_type),
request_data.should_reset_appcache);
@@ -1111,7 +1071,6 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client) {
DCHECK(requester_info->IsRenderer() ||
- requester_info->IsNavigationPreload() ||
requester_info->IsCertificateFetcherForSignedExchange());
// Construct the IPC resource handler.
std::unique_ptr<ResourceHandler> handler =
@@ -1201,6 +1160,8 @@ ResourceDispatcherHostImpl::AddStandardHandlers(
plugin_service = PluginService::GetInstance();
#endif
+ handler.reset(new SecFetchSiteResourceHandler(request, std::move(handler)));
+
if (!IsResourceTypeFrame(resource_type)) {
// Add a handler to block cross-site documents from the renderer process.
handler.reset(new CrossSiteDocumentResourceHandler(
@@ -1876,18 +1837,6 @@ void ResourceDispatcherHostImpl::CancelRequestFromRenderer(
loader->CancelRequest(true);
}
-bool ResourceDispatcherHostImpl::DoNotPromptForLogin(
- ResourceType resource_type,
- const GURL& url,
- const GURL& site_for_cookies) {
- if (resource_type == ResourceType::kImage &&
- HTTP_AUTH_RELATION_BLOCKED_CROSS ==
- HttpAuthRelationTypeOf(url, site_for_cookies)) {
- return true;
- }
- return false;
-}
-
void ResourceDispatcherHostImpl::StartLoading(
ResourceRequestInfoImpl* info,
std::unique_ptr<ResourceLoader> loader) {
@@ -2085,35 +2034,6 @@ void ResourceDispatcherHostImpl::ProcessBlockedRequestsForRoute(
}
}
-ResourceDispatcherHostImpl::HttpAuthRelationType
-ResourceDispatcherHostImpl::HttpAuthRelationTypeOf(
- const GURL& request_url,
- const GURL& first_party) {
- if (!first_party.is_valid())
- return HTTP_AUTH_RELATION_TOP;
-
- if (net::registry_controlled_domains::SameDomainOrHost(
- first_party, request_url,
- net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
- // If the first party is secure but the subresource is not, this is
- // mixed-content. Do not allow the image.
- if (!allow_cross_origin_auth_prompt() && IsOriginSecure(first_party) &&
- !IsOriginSecure(request_url)) {
- return HTTP_AUTH_RELATION_BLOCKED_CROSS;
- }
- return HTTP_AUTH_RELATION_SAME_DOMAIN;
- }
-
- if (allow_cross_origin_auth_prompt())
- return HTTP_AUTH_RELATION_ALLOWED_CROSS;
-
- return HTTP_AUTH_RELATION_BLOCKED_CROSS;
-}
-
-bool ResourceDispatcherHostImpl::allow_cross_origin_auth_prompt() {
- return allow_cross_origin_auth_prompt_;
-}
-
ResourceLoader* ResourceDispatcherHostImpl::GetLoader(
const GlobalRequestID& id) const {
DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index 68ac30b509a..fe0937ef2b3 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -105,7 +105,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// ResourceDispatcherHost implementation:
void SetDelegate(ResourceDispatcherHostDelegate* delegate) override;
- void SetAllowCrossOriginAuthPrompt(bool value) override;
void RegisterInterceptor(const std::string& http_header,
const std::string& starts_with,
const InterceptorCallback& interceptor) override;
@@ -175,10 +174,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
void CancelBlockedRequestsForRoute(
const GlobalFrameRoutingId& global_routing_id);
- // Indicates whether third-party sub-content can pop-up HTTP basic auth
- // dialog boxes.
- bool allow_cross_origin_auth_prompt();
-
ResourceDispatcherHostDelegate* delegate() {
return delegate_;
}
@@ -608,18 +603,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
bool download,
ResourceContext* context);
- // Relationship of resource being authenticated with the top level page.
- enum HttpAuthRelationType {
- HTTP_AUTH_RELATION_TOP, // Top-level page itself
- HTTP_AUTH_RELATION_SAME_DOMAIN, // Sub-content from same domain
- HTTP_AUTH_RELATION_BLOCKED_CROSS, // Blocked Sub-content from cross domain
- HTTP_AUTH_RELATION_ALLOWED_CROSS, // Allowed Sub-content per command line
- HTTP_AUTH_RELATION_LAST
- };
-
- HttpAuthRelationType HttpAuthRelationTypeOf(const GURL& request_url,
- const GURL& first_party);
-
ResourceLoader* GetLoader(const GlobalRequestID& id) const;
ResourceLoader* GetLoader(int child_id, int request_id) const;
@@ -723,8 +706,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
LoaderDelegate* loader_delegate_;
- bool allow_cross_origin_auth_prompt_;
-
std::unique_ptr<network::ResourceScheduler> scheduler_;
// Used to invoke an interceptor for the HTTP header.
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index db25e249f98..1ad8c6f4902 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -30,6 +30,7 @@
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/detachable_resource_handler.h"
#include "content/browser/loader/navigation_url_loader.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_message_filter.h"
@@ -108,7 +109,7 @@ static network::ResourceRequest CreateResourceRequest(const char* method,
request.load_flags = 0;
request.plugin_child_id = -1;
request.resource_type = static_cast<int>(type);
- request.appcache_host_id = blink::mojom::kAppCacheNoHostId;
+ request.appcache_host_id = base::nullopt;
request.should_reset_appcache = false;
request.render_frame_id = 0;
request.is_main_frame = true;
@@ -128,7 +129,6 @@ class TestFilterSpecifyingChild : public ResourceMessageFilter {
nullptr,
nullptr,
nullptr,
- nullptr,
base::Bind(&TestFilterSpecifyingChild::GetContexts,
base::Unretained(this)),
base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})),
@@ -528,9 +528,7 @@ class GenericResourceThrottle : public ResourceThrottle {
}
}
- const char* GetNameForLogging() const override {
- return "GenericResourceThrottle";
- }
+ const char* GetNameForLogging() override { return "GenericResourceThrottle"; }
void AssertAndResume() {
ASSERT_TRUE(this == active_throttle_);
@@ -830,7 +828,9 @@ class ResourceDispatcherHostTest : public testing::TestWithParam<TestMode> {
false /* skip_service_worker */,
blink::mojom::RequestContextType::LOCATION,
blink::WebMixedContentContextType::kBlockable,
- false /* is_form_submission */, GURL() /* searchable_form_url */,
+ false /* is_form_submission */,
+ false /* was_initiated_by_link_click */,
+ GURL() /* searchable_form_url */,
std::string() /* searchable_form_encoding */,
GURL() /* client_side_redirect_url */,
base::nullopt /* devtools_initiator_info */);
@@ -848,7 +848,8 @@ class ResourceDispatcherHostTest : public testing::TestWithParam<TestMode> {
NavigationURLLoader::Create(
browser_context_->GetResourceContext(),
BrowserContext::GetDefaultStoragePartition(browser_context_.get()),
- std::move(request_info), nullptr, nullptr, nullptr, &delegate);
+ std::move(request_info), nullptr, nullptr, nullptr, nullptr,
+ &delegate);
// The navigation should fail with the expected error code.
delegate.WaitForRequestFailed();
@@ -2123,6 +2124,12 @@ TEST_P(ResourceDispatcherHostTest, MimeSniffEmpty) {
// Tests for crbug.com/31266 (Non-2xx + application/octet-stream).
TEST_P(ResourceDispatcherHostTest, ForbiddenDownload) {
+ // This is a regression test for code in ResourceDispatcherHost, but it's
+ // written in a way that uses code from network service if that feature is
+ // enabled. This will fail because not everything is setup.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
std::string raw_headers("HTTP/1.1 403 Forbidden\n"
"Content-disposition: attachment; filename=blah\n"
"Content-type: application/octet-stream\n\n");
@@ -2183,8 +2190,6 @@ class ExternalProtocolBrowserClient : public TestContentBrowserClient {
bool is_main_frame,
ui::PageTransition page_transition,
bool has_user_gesture,
- const std::string& method,
- const net::HttpRequestHeaders& headers,
network::mojom::URLLoaderFactoryRequest* factory_request,
network::mojom::URLLoaderFactory*& out_factory) override {
return false;
diff --git a/chromium/content/browser/loader/resource_loader.cc b/chromium/content/browser/loader/resource_loader.cc
index 1f070739398..6bd5b8dc334 100644
--- a/chromium/content/browser/loader/resource_loader.cc
+++ b/chromium/content/browser/loader/resource_loader.cc
@@ -90,6 +90,9 @@ void PopulateResourceResponse(
response->head.network_accessed = response_info.network_accessed;
response->head.async_revalidation_requested =
response_info.async_revalidation_requested;
+ response->head.was_in_prefetch_cache =
+ !(request->load_flags() & net::LOAD_PREFETCH) &&
+ response_info.unused_since_prefetch;
if (info->ShouldReportRawHeaders()) {
response->head.raw_request_response_info =
network::BuildRawRequestResponseInfo(*request, raw_request_headers,
@@ -135,6 +138,7 @@ void PopulateResourceResponse(
DCHECK_EQ(request->ssl_info().peer_signature_algorithm, 0);
DCHECK_EQ(request->ssl_info().connection_status, 0);
}
+ response->head.auth_challenge_info = request->auth_challenge_info();
}
} // namespace
@@ -442,13 +446,15 @@ void ResourceLoader::OnCertificateRequested(
}
void ResourceLoader::OnSSLCertificateError(net::URLRequest* request,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal) {
ResourceRequestInfoImpl* info = GetRequestInfo();
SSLManager::OnSSLCertificateError(
- weak_ptr_factory_.GetWeakPtr(), info->GetResourceType(), request_->url(),
- info->GetWebContentsGetterForRequest(), ssl_info, fatal);
+ weak_ptr_factory_.GetWeakPtr(),
+ info->GetResourceType() == ResourceType::kMainFrame, request_->url(),
+ info->GetWebContentsGetterForRequest(), net_error, ssl_info, fatal);
}
void ResourceLoader::OnResponseStarted(net::URLRequest* unused, int net_error) {
diff --git a/chromium/content/browser/loader/resource_loader.h b/chromium/content/browser/loader/resource_loader.h
index dbb477bdc4f..8c2ae618f27 100644
--- a/chromium/content/browser/loader/resource_loader.h
+++ b/chromium/content/browser/loader/resource_loader.h
@@ -77,6 +77,7 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
void OnCertificateRequested(net::URLRequest* request,
net::SSLCertRequestInfo* info) override;
void OnSSLCertificateError(net::URLRequest* request,
+ int net_error,
const net::SSLInfo& info,
bool fatal) override;
void OnResponseStarted(net::URLRequest* request, int net_error) override;
diff --git a/chromium/content/browser/loader/resource_loader_unittest.cc b/chromium/content/browser/loader/resource_loader_unittest.cc
index 539689eecaf..fc4fd6d6cb3 100644
--- a/chromium/content/browser/loader/resource_loader_unittest.cc
+++ b/chromium/content/browser/loader/resource_loader_unittest.cc
@@ -1773,4 +1773,37 @@ TEST_F(ResourceLoaderTest, MultiplePauseResumeReadingBodyFromNet) {
StopMonitorBodyReadFromNetBeforePausedHistogram();
}
+// Tests that AuthChallengeInfo is present on a request that requests
+// authentication.
+TEST_F(ResourceLoaderTest, AuthChallengeInfo) {
+ net::EmbeddedTestServer server;
+ server.AddDefaultHandlers(base::FilePath());
+ ASSERT_TRUE(server.Start());
+ SetUpResourceLoaderForUrl(server.GetURL("/auth-basic"));
+ loader_->StartRequest();
+ raw_ptr_resource_handler_->WaitUntilResponseComplete();
+ const base::Optional<net::AuthChallengeInfo>& auth_info =
+ raw_ptr_resource_handler_->resource_response()->head.auth_challenge_info;
+ ASSERT_TRUE(auth_info.has_value());
+ EXPECT_FALSE(auth_info->is_proxy);
+ EXPECT_EQ(url::Origin::Create(server.GetURL("/")), auth_info->challenger);
+ EXPECT_EQ("basic", auth_info->scheme);
+ EXPECT_EQ("testrealm", auth_info->realm);
+ EXPECT_EQ("Basic realm=\"testrealm\"", auth_info->challenge);
+ EXPECT_EQ("/auth-basic", auth_info->path);
+}
+
+// Tests that no AuthChallengeInfo is present on a request that doesn't request
+// authentication.
+TEST_F(ResourceLoaderTest, NoAuthChallengeInfo) {
+ net::EmbeddedTestServer server;
+ server.AddDefaultHandlers(base::FilePath());
+ ASSERT_TRUE(server.Start());
+ SetUpResourceLoaderForUrl(server.GetURL("/"));
+ loader_->StartRequest();
+ raw_ptr_resource_handler_->WaitUntilResponseComplete();
+ EXPECT_FALSE(raw_ptr_resource_handler_->resource_response()
+ ->head.auth_challenge_info.has_value());
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_message_filter.cc b/chromium/content/browser/loader/resource_message_filter.cc
index 7779fd37052..585999c3ba7 100644
--- a/chromium/content/browser/loader/resource_message_filter.cc
+++ b/chromium/content/browser/loader/resource_message_filter.cc
@@ -14,7 +14,6 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_requester_info.h"
#include "content/browser/loader/url_loader_factory_impl.h"
-#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/resource_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
@@ -42,7 +41,6 @@ ResourceMessageFilter::ResourceMessageFilter(
ChromeAppCacheService* appcache_service,
ChromeBlobStorageContext* blob_storage_context,
storage::FileSystemContext* file_system_context,
- ServiceWorkerContextWrapper* service_worker_context,
PrefetchURLLoaderService* prefetch_url_loader_service,
const GetContextsCallback& get_contexts_callback,
const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner)
@@ -54,7 +52,6 @@ ResourceMessageFilter::ResourceMessageFilter(
appcache_service,
blob_storage_context,
file_system_context,
- service_worker_context,
get_contexts_callback)),
prefetch_url_loader_service_(prefetch_url_loader_service),
io_thread_task_runner_(io_thread_runner),
diff --git a/chromium/content/browser/loader/resource_message_filter.h b/chromium/content/browser/loader/resource_message_filter.h
index 061e93339ad..7be03ea9e62 100644
--- a/chromium/content/browser/loader/resource_message_filter.h
+++ b/chromium/content/browser/loader/resource_message_filter.h
@@ -34,7 +34,6 @@ class ChromeBlobStorageContext;
class PrefetchURLLoaderService;
class ResourceContext;
class ResourceRequesterInfo;
-class ServiceWorkerContextWrapper;
// This class filters out incoming IPC messages for network requests and
// processes them on the IPC thread. As a result, network requests are not
@@ -50,8 +49,8 @@ class CONTENT_EXPORT ResourceMessageFilter
ResourceContext**,
net::URLRequestContext**)> GetContextsCallback;
- // |appcache_service|, |blob_storage_context|, |file_system_context|,
- // |service_worker_context| may be nullptr in unittests.
+ // |appcache_service|, |blob_storage_context|, and |file_system_context| may
+ // be nullptr in unittests.
// InitializeForTest() needs to be manually called for unittests where
// OnFilterAdded() would not otherwise be called.
ResourceMessageFilter(
@@ -59,7 +58,6 @@ class CONTENT_EXPORT ResourceMessageFilter
ChromeAppCacheService* appcache_service,
ChromeBlobStorageContext* blob_storage_context,
storage::FileSystemContext* file_system_context,
- ServiceWorkerContextWrapper* service_worker_context,
PrefetchURLLoaderService* prefetch_url_loader_service,
const GetContextsCallback& get_contexts_callback,
const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner);
diff --git a/chromium/content/browser/loader/resource_request_info_impl.cc b/chromium/content/browser/loader/resource_request_info_impl.cc
index 2a166f3ffe2..39fbfc14743 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -8,7 +8,7 @@
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
-#include "content/browser/web_contents/web_contents_getter_registry.h"
+#include "content/browser/web_contents/frame_tree_node_id_registry.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/net/url_request_service_worker_data.h"
#include "content/common/net/url_request_user_data.h"
@@ -194,10 +194,11 @@ ResourceRequestInfo::WebContentsGetter
ResourceRequestInfoImpl::GetWebContentsGetterForRequest() {
// If we have a window id, try to use that.
if (fetch_window_id_) {
- ResourceRequestInfo::WebContentsGetter getter =
- WebContentsGetterRegistry::GetInstance()->Get(fetch_window_id_);
- if (getter)
+ if (auto getter =
+ FrameTreeNodeIdRegistry::GetInstance()->GetWebContentsGetter(
+ fetch_window_id_)) {
return getter;
+ }
}
// Navigation requests are created with a valid FrameTreeNode ID and invalid
diff --git a/chromium/content/browser/loader/resource_requester_info.cc b/chromium/content/browser/loader/resource_requester_info.cc
index 393fb294aa3..dc15adac0bb 100644
--- a/chromium/content/browser/loader/resource_requester_info.cc
+++ b/chromium/content/browser/loader/resource_requester_info.cc
@@ -11,7 +11,6 @@
#include "base/logging.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/browser/resource_context.h"
#include "content/public/common/child_process_host.h"
@@ -23,34 +22,18 @@
namespace content {
-namespace {
-
-void GetContextsCallbackForNavigationPreload(
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- net::URLRequestContext* url_request_context,
- ResourceType resource_type,
- ResourceContext** resource_context_out,
- net::URLRequestContext** request_context_out) {
- *resource_context_out = service_worker_context->resource_context();
- *request_context_out = url_request_context;
-}
-
-} // namespace
-
ResourceRequesterInfo::ResourceRequesterInfo(
RequesterType type,
int child_id,
ChromeAppCacheService* appcache_service,
ChromeBlobStorageContext* blob_storage_context,
storage::FileSystemContext* file_system_context,
- ServiceWorkerContextWrapper* service_worker_context,
const GetContextsCallback& get_contexts_callback)
: type_(type),
child_id_(child_id),
appcache_service_(appcache_service),
blob_storage_context_(blob_storage_context),
file_system_context_(file_system_context),
- service_worker_context_(service_worker_context),
get_contexts_callback_(get_contexts_callback) {}
ResourceRequesterInfo::~ResourceRequesterInfo() {}
@@ -73,11 +56,10 @@ scoped_refptr<ResourceRequesterInfo> ResourceRequesterInfo::CreateForRenderer(
ChromeAppCacheService* appcache_service,
ChromeBlobStorageContext* blob_storage_context,
storage::FileSystemContext* file_system_context,
- ServiceWorkerContextWrapper* service_worker_context,
const GetContextsCallback& get_contexts_callback) {
return scoped_refptr<ResourceRequesterInfo>(new ResourceRequesterInfo(
RequesterType::RENDERER, child_id, appcache_service, blob_storage_context,
- file_system_context, service_worker_context, get_contexts_callback));
+ file_system_context, get_contexts_callback));
}
scoped_refptr<ResourceRequesterInfo>
@@ -85,7 +67,7 @@ ResourceRequesterInfo::CreateForRendererTesting(int child_id) {
return scoped_refptr<ResourceRequesterInfo>(new ResourceRequesterInfo(
RequesterType::RENDERER, child_id, nullptr /* appcache_service */,
nullptr /* blob_storage_context */, nullptr /* file_system_context */,
- nullptr /*service_worker_context */, GetContextsCallback()));
+ GetContextsCallback()));
}
scoped_refptr<ResourceRequesterInfo>
@@ -94,7 +76,7 @@ ResourceRequesterInfo::CreateForBrowserSideNavigation() {
RequesterType::BROWSER_SIDE_NAVIGATION,
ChildProcessHost::kInvalidUniqueID, nullptr /* appcache_service */,
nullptr /* blob_storage_context */, nullptr /* file_system_context */,
- nullptr /* service_worker_context */, GetContextsCallback()));
+ GetContextsCallback()));
}
scoped_refptr<ResourceRequesterInfo>
@@ -102,32 +84,7 @@ ResourceRequesterInfo::CreateForDownloadOrPageSave(int child_id) {
return scoped_refptr<ResourceRequesterInfo>(new ResourceRequesterInfo(
RequesterType::DOWNLOAD_OR_PAGE_SAVE, child_id,
nullptr /* appcache_service */, nullptr /* blob_storage_context */,
- nullptr /* file_system_context */, nullptr /*service_worker_context */,
- GetContextsCallback()));
-}
-
-scoped_refptr<ResourceRequesterInfo>
-ResourceRequesterInfo::CreateForNavigationPreload(
- ResourceRequesterInfo* original_request_info,
- net::URLRequestContext* url_request_context) {
- DCHECK(original_request_info->IsBrowserSideNavigation());
- DCHECK(original_request_info->service_worker_context());
- DCHECK(!original_request_info->get_contexts_callback_);
- // The requester info for browser side navigation doesn't have the
- // get_contexts_callback. So create the callback here which gets the
- // ResourceContext and the URLRequestContext from ServiceWorkerContext.
- auto get_contexts_callback =
- base::BindRepeating(&GetContextsCallbackForNavigationPreload,
- scoped_refptr<ServiceWorkerContextWrapper>(
- original_request_info->service_worker_context()),
- url_request_context);
-
- return scoped_refptr<ResourceRequesterInfo>(new ResourceRequesterInfo(
- RequesterType::NAVIGATION_PRELOAD, ChildProcessHost::kInvalidUniqueID,
- nullptr /* appcache_service */, nullptr /* blob_storage_context */,
- nullptr /* file_system_context */,
- original_request_info->service_worker_context(),
- std::move(get_contexts_callback)));
+ nullptr /* file_system_context */, GetContextsCallback()));
}
scoped_refptr<ResourceRequesterInfo>
@@ -138,7 +95,7 @@ ResourceRequesterInfo::CreateForCertificateFetcherForSignedExchange(
RequesterType::CERTIFICATE_FETCHER_FOR_SIGNED_EXCHANGE,
ChildProcessHost::kInvalidUniqueID, nullptr /* appcache_service */,
nullptr /* blob_storage_context */, nullptr /* file_system_context */,
- nullptr /* service_worker_context */, get_contexts_callback));
+ get_contexts_callback));
}
} // namespace content
diff --git a/chromium/content/browser/loader/resource_requester_info.h b/chromium/content/browser/loader/resource_requester_info.h
index 24027c620f4..e7333dad5cb 100644
--- a/chromium/content/browser/loader/resource_requester_info.h
+++ b/chromium/content/browser/loader/resource_requester_info.h
@@ -26,7 +26,6 @@ class ChromeAppCacheService;
class ChromeBlobStorageContext;
class ResourceContext;
class ResourceMessageFilter;
-class ServiceWorkerContextWrapper;
// This class represents the type of resource requester.
// Currently there are four types:
@@ -50,7 +49,6 @@ class CONTENT_EXPORT ResourceRequesterInfo
ChromeAppCacheService* appcache_service,
ChromeBlobStorageContext* blob_storage_context,
storage::FileSystemContext* file_system_context,
- ServiceWorkerContextWrapper* service_worker_context,
const GetContextsCallback& get_contexts_callback);
// Creates a ResourceRequesterInfo for a requester that requests resources
@@ -67,13 +65,6 @@ class CONTENT_EXPORT ResourceRequesterInfo
static scoped_refptr<ResourceRequesterInfo> CreateForDownloadOrPageSave(
int child_id);
- // Creates a ResourceRequesterInfo for a service worker navigation preload
- // request. When PlzNavigate is enabled, |original_request_info| must be
- // browser side navigation type. Otherwise it must be renderer type.
- static scoped_refptr<ResourceRequesterInfo> CreateForNavigationPreload(
- ResourceRequesterInfo* original_request_info,
- net::URLRequestContext* url_request_context);
-
// Creates a ResourceRequesterInfo for a requester that requests certificates
// for signed exchange.
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html
@@ -85,9 +76,6 @@ class CONTENT_EXPORT ResourceRequesterInfo
bool IsBrowserSideNavigation() const {
return type_ == RequesterType::BROWSER_SIDE_NAVIGATION;
}
- bool IsNavigationPreload() const {
- return type_ == RequesterType::NAVIGATION_PRELOAD;
- }
bool IsCertificateFetcherForSignedExchange() const {
return type_ == RequesterType::CERTIFICATE_FETCHER_FOR_SIGNED_EXCHANGE;
}
@@ -129,14 +117,6 @@ class CONTENT_EXPORT ResourceRequesterInfo
return file_system_context_.get();
}
- // Returns the ServiceWorkerContext associated with the requester. Currently
- // this method is available for renderer type requester, browser side
- // navigation type requester and service worker navigation preload type
- // requester.
- ServiceWorkerContextWrapper* service_worker_context() {
- return service_worker_context_.get();
- }
-
private:
friend class base::RefCountedThreadSafe<ResourceRequesterInfo>;
@@ -144,7 +124,6 @@ class CONTENT_EXPORT ResourceRequesterInfo
RENDERER,
BROWSER_SIDE_NAVIGATION,
DOWNLOAD_OR_PAGE_SAVE,
- NAVIGATION_PRELOAD,
CERTIFICATE_FETCHER_FOR_SIGNED_EXCHANGE
};
@@ -153,7 +132,6 @@ class CONTENT_EXPORT ResourceRequesterInfo
ChromeAppCacheService* appcache_service,
ChromeBlobStorageContext* blob_storage_context,
storage::FileSystemContext* file_system_context,
- ServiceWorkerContextWrapper* service_worker_context,
const GetContextsCallback& get_contexts_callback);
~ResourceRequesterInfo();
@@ -164,7 +142,6 @@ class CONTENT_EXPORT ResourceRequesterInfo
const scoped_refptr<ChromeAppCacheService> appcache_service_;
const scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
const scoped_refptr<storage::FileSystemContext> file_system_context_;
- const scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
const GetContextsCallback get_contexts_callback_;
DISALLOW_COPY_AND_ASSIGN(ResourceRequesterInfo);
diff --git a/chromium/content/browser/loader/sec_fetch_site_resource_handler.cc b/chromium/content/browser/loader/sec_fetch_site_resource_handler.cc
new file mode 100644
index 00000000000..378981de29c
--- /dev/null
+++ b/chromium/content/browser/loader/sec_fetch_site_resource_handler.cc
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights 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/sec_fetch_site_resource_handler.h"
+
+#include "content/browser/loader/resource_request_info_impl.h"
+#include "services/network/sec_fetch_site.h"
+
+namespace content {
+
+SecFetchSiteResourceHandler::SecFetchSiteResourceHandler(
+ net::URLRequest* request,
+ std::unique_ptr<ResourceHandler> next_handler)
+ : LayeredResourceHandler(request, std::move(next_handler)),
+ factory_params_(CreateURLLoaderFactoryParams()) {}
+
+SecFetchSiteResourceHandler::~SecFetchSiteResourceHandler() = default;
+
+void SecFetchSiteResourceHandler::OnWillStart(
+ const GURL& url,
+ std::unique_ptr<ResourceController> controller) {
+ SetHeader(nullptr);
+
+ next_handler_->OnWillStart(url, std::move(controller));
+}
+
+void SecFetchSiteResourceHandler::OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ network::ResourceResponse* response,
+ std::unique_ptr<ResourceController> controller) {
+ SetHeader(&redirect_info.new_url);
+
+ next_handler_->OnRequestRedirected(redirect_info, response,
+ std::move(controller));
+}
+
+void SecFetchSiteResourceHandler::SetHeader(const GURL* new_url_from_redirect) {
+ network::SetSecFetchSiteHeader(request(), new_url_from_redirect,
+ *factory_params_);
+}
+
+network::mojom::URLLoaderFactoryParamsPtr
+SecFetchSiteResourceHandler::CreateURLLoaderFactoryParams() {
+ auto result = network::mojom::URLLoaderFactoryParams::New();
+
+ // Translate |info->GetChildID()| (an int, -1 designates a browser process)
+ // into |result->process_id| (an uint32_t, 0 designates a browser process).
+ ResourceRequestInfoImpl* info = GetRequestInfo();
+ if (!info || info->GetChildID() == -1) {
+ result->process_id = network::mojom::kBrowserProcessId;
+ } else {
+ result->process_id = info->GetChildID();
+ DCHECK_NE(network::mojom::kBrowserProcessId, result->process_id);
+ }
+
+ // |request_initiator_site_lock| is not enforced in the legacy,
+ // pre-NetworkService path, so below we plug in a lock that is obviously
+ // compatible with the request initiator.
+ result->request_initiator_site_lock = request()->initiator();
+
+ // Note that some fields of |result| might be left at their default values at
+ // this point. This is okay - we only care about the two fields that
+ // the network::SetSecFetchSiteHeader function will inspect.
+ return result;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/sec_fetch_site_resource_handler.h b/chromium/content/browser/loader/sec_fetch_site_resource_handler.h
new file mode 100644
index 00000000000..8e8e8750be4
--- /dev/null
+++ b/chromium/content/browser/loader/sec_fetch_site_resource_handler.h
@@ -0,0 +1,52 @@
+// Copyright 2019 The Chromium Authors. All rights 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_SEC_FETCH_SITE_RESOURCE_HANDLER_H_
+#define CONTENT_BROWSER_LOADER_SEC_FETCH_SITE_RESOURCE_HANDLER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "content/browser/loader/layered_resource_handler.h"
+#include "content/browser/loader/resource_controller.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+#include "url/gurl.h"
+
+namespace net {
+struct RedirectInfo;
+class URLRequest;
+} // namespace net
+
+namespace content {
+
+class SecFetchSiteResourceHandler : public LayeredResourceHandler {
+ public:
+ SecFetchSiteResourceHandler(net::URLRequest* request,
+ std::unique_ptr<ResourceHandler> next_handler);
+
+ private:
+ ~SecFetchSiteResourceHandler() override;
+ void OnWillStart(const GURL& url,
+ std::unique_ptr<ResourceController> controller) override;
+ void OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ network::ResourceResponse* response,
+ std::unique_ptr<ResourceController> controller) override;
+
+ // Creates URLLoaderFactoryParams with just enough information filled in to
+ // satisfy the needs of network::SetSecFetchSiteHeader function.
+ network::mojom::URLLoaderFactoryParamsPtr CreateURLLoaderFactoryParams();
+
+ // Sets the Sec-Fetch-Site header (based on the method argument and also on
+ // the state of the |url_request()| and on |factory_params_|).
+ void SetHeader(const GURL* new_url_from_redirect);
+
+ network::mojom::URLLoaderFactoryParamsPtr factory_params_;
+
+ DISALLOW_COPY_AND_ASSIGN(SecFetchSiteResourceHandler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_SEC_FETCH_SITE_RESOURCE_HANDLER_H_
diff --git a/chromium/content/browser/loader/stream_writer.cc b/chromium/content/browser/loader/stream_writer.cc
index 70a7502744b..09db04953ce 100644
--- a/chromium/content/browser/loader/stream_writer.cc
+++ b/chromium/content/browser/loader/stream_writer.cc
@@ -4,7 +4,8 @@
#include "content/browser/loader/stream_writer.h"
-#include "base/callback_helpers.h"
+#include <utility>
+
#include "base/guid.h"
#include "content/browser/loader/resource_controller.h"
#include "content/browser/streams/stream.h"
@@ -95,7 +96,7 @@ void StreamWriter::Finalize(int status) {
}
void StreamWriter::OnSpaceAvailable(Stream* stream) {
- base::ResetAndReturn(&need_more_data_callback_).Run();
+ std::move(need_more_data_callback_).Run();
}
void StreamWriter::OnClose(Stream* stream) {
diff --git a/chromium/content/browser/loader/throttling_resource_handler_unittest.cc b/chromium/content/browser/loader/throttling_resource_handler_unittest.cc
index f5e538cf44c..9318fc11434 100644
--- a/chromium/content/browser/loader/throttling_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/throttling_resource_handler_unittest.cc
@@ -119,7 +119,7 @@ class TestResourceThrottle : public ResourceThrottle {
CancelWithError(net::ERR_UNEXPECTED);
}
- const char* GetNameForLogging() const override { return "Hank"; }
+ const char* GetNameForLogging() override { return "Hank"; }
int will_start_request_called() const { return will_start_request_called_; }
int will_redirect_request_called() const {
diff --git a/chromium/content/browser/loader/url_loader_factory_impl.cc b/chromium/content/browser/loader/url_loader_factory_impl.cc
index 9beee7ae75d..455217a4b62 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl.cc
+++ b/chromium/content/browser/loader/url_loader_factory_impl.cc
@@ -19,7 +19,6 @@ URLLoaderFactoryImpl::URLLoaderFactoryImpl(
: requester_info_(std::move(requester_info)) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK((requester_info_->IsRenderer() && requester_info_->filter()) ||
- requester_info_->IsNavigationPreload() ||
requester_info_->IsCertificateFetcherForSignedExchange());
}
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 21e09fc2e8d..f651d246057 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
+++ b/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
@@ -48,6 +48,7 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_filter.h"
+#include "services/network/public/cpp/constants.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/mojom/url_loader.mojom.h"
@@ -76,7 +77,6 @@ class URLLoaderFactoryImplTest : public ::testing::TestWithParam<size_t> {
nullptr,
nullptr,
nullptr,
- nullptr,
base::Bind(&URLLoaderFactoryImplTest::GetContexts,
base::Unretained(this)),
base::CreateSingleThreadTaskRunnerWithTraits(
@@ -111,7 +111,7 @@ class URLLoaderFactoryImplTest : public ::testing::TestWithParam<size_t> {
rdh_.CancelRequestsForProcess(resource_message_filter_->child_id());
base::RunLoop().RunUntilIdle();
MojoAsyncResourceHandler::SetAllocationSizeForTesting(
- MojoAsyncResourceHandler::kDefaultAllocationSize);
+ network::kDataPipeDefaultAllocationSize);
}
void GetContexts(ResourceType resource_type,
diff --git a/chromium/content/browser/log_console_message.cc b/chromium/content/browser/log_console_message.cc
index ef65a5fd45e..19ef8802aef 100644
--- a/chromium/content/browser/log_console_message.cc
+++ b/chromium/content/browser/log_console_message.cc
@@ -32,14 +32,15 @@ logging::LogSeverity ConsoleMessageLevelToLogSeverity(
return log_severity;
}
-void LogConsoleMessage(int32_t level,
+void LogConsoleMessage(blink::mojom::ConsoleMessageLevel log_level,
const base::string16& message,
int32_t line_number,
bool is_builtin_component,
bool is_off_the_record,
const base::string16& source_id) {
const int32_t resolved_level =
- is_builtin_component ? level : ::logging::LOG_INFO;
+ is_builtin_component ? ConsoleMessageLevelToLogSeverity(log_level)
+ : ::logging::LOG_INFO;
if (::logging::GetMinLogLevel() > resolved_level)
return;
diff --git a/chromium/content/browser/log_console_message.h b/chromium/content/browser/log_console_message.h
index cd550d790d0..9ef73f0dafc 100644
--- a/chromium/content/browser/log_console_message.h
+++ b/chromium/content/browser/log_console_message.h
@@ -16,8 +16,7 @@ logging::LogSeverity ConsoleMessageLevelToLogSeverity(
// Optionally logs a message from the console, depending on the set logging
// levels and incognito state.
-// TODO(devlin): Update |level| to be a logging::LogSeverity.
-void LogConsoleMessage(int32_t level,
+void LogConsoleMessage(blink::mojom::ConsoleMessageLevel log_level,
const base::string16& message,
int32_t line_number,
bool is_builtin_component,
diff --git a/chromium/content/browser/manifest/manifest_browsertest.cc b/chromium/content/browser/manifest/manifest_browsertest.cc
index 1d136dc10ae..e8d62299f79 100644
--- a/chromium/content/browser/manifest/manifest_browsertest.cc
+++ b/chromium/content/browser/manifest/manifest_browsertest.cc
@@ -39,7 +39,7 @@ class MockWebContentsDelegate : public WebContentsDelegate {
}
bool DidAddMessageToConsole(WebContents* source,
- int32_t level,
+ blink::mojom::ConsoleMessageLevel log_level,
const base::string16& message,
int32_t line_no,
const base::string16& source_id) override;
@@ -160,13 +160,14 @@ class ManifestBrowserTest : public ContentBrowserTest,
// to know about |test_|.
bool MockWebContentsDelegate::DidAddMessageToConsole(
WebContents* source,
- int32_t level,
+ blink::mojom::ConsoleMessageLevel log_level,
const base::string16& message,
int32_t line_no,
const base::string16& source_id) {
DCHECK(source == web_contents_);
- if (level == logging::LOG_ERROR || level == logging::LOG_WARNING)
+ if (log_level == blink::mojom::ConsoleMessageLevel::kError ||
+ log_level == blink::mojom::ConsoleMessageLevel::kWarning)
test_->OnReceivedConsoleError();
return false;
}
diff --git a/chromium/content/browser/manifest/manifest_manager_host.h b/chromium/content/browser/manifest/manifest_manager_host.h
index a49af365284..f0015147e63 100644
--- a/chromium/content/browser/manifest/manifest_manager_host.h
+++ b/chromium/content/browser/manifest/manifest_manager_host.h
@@ -8,10 +8,10 @@
#include "base/callback_forward.h"
#include "base/containers/id_map.h"
#include "base/macros.h"
-#include "content/common/manifest_observer.mojom.h"
#include "content/public/browser/web_contents_binding_set.h"
#include "content/public/browser/web_contents_observer.h"
#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
+#include "third_party/blink/public/mojom/manifest/manifest_observer.mojom.h"
namespace blink {
struct Manifest;
@@ -27,7 +27,7 @@ class WebContents;
// IPC messaging with the child process.
// TODO(mlamouri): keep a cached version and a dirty bit here.
class ManifestManagerHost : public WebContentsObserver,
- public mojom::ManifestUrlChangeObserver {
+ public blink::mojom::ManifestUrlChangeObserver {
public:
explicit ManifestManagerHost(WebContents* web_contents);
~ManifestManagerHost() override;
@@ -56,14 +56,14 @@ class ManifestManagerHost : public WebContentsObserver,
const GURL& url,
const blink::Manifest& manifest);
- // mojom::ManifestUrlChangeObserver:
+ // blink::mojom::ManifestUrlChangeObserver:
void ManifestUrlChanged(const base::Optional<GURL>& manifest_url) override;
RenderFrameHost* manifest_manager_frame_ = nullptr;
blink::mojom::ManifestManagerPtr manifest_manager_;
CallbackMap callbacks_;
- WebContentsFrameBindingSet<mojom::ManifestUrlChangeObserver>
+ WebContentsFrameBindingSet<blink::mojom::ManifestUrlChangeObserver>
manifest_url_change_observer_bindings_;
DISALLOW_COPY_AND_ASSIGN(ManifestManagerHost);
diff --git a/chromium/content/browser/media/audio_input_stream_broker.cc b/chromium/content/browser/media/audio_input_stream_broker.cc
index 0fc989df67f..31d686ff59a 100644
--- a/chromium/content/browser/media/audio_input_stream_broker.cc
+++ b/chromium/content/browser/media/audio_input_stream_broker.cc
@@ -80,16 +80,14 @@ AudioInputStreamBroker::AudioInputStreamBroker(
enable_agc_(enable_agc),
deleter_(std::move(deleter)),
processing_config_(std::move(processing_config)),
- renderer_factory_client_(std::move(renderer_factory_client)),
- observer_binding_(this),
- weak_ptr_factory_(this) {
+ renderer_factory_client_(renderer_factory_client.PassInterface()) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(renderer_factory_client_);
DCHECK(deleter_);
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(
+ renderer_factory_client_.set_disconnect_handler(base::BindOnce(
&AudioInputStreamBroker::ClientBindingLost, base::Unretained(this)));
NotifyProcessHostOfStartedStream(render_process_id);
@@ -141,8 +139,8 @@ AudioInputStreamBroker::~AudioInputStreamBroker() {
void AudioInputStreamBroker::CreateStream(
audio::mojom::StreamFactory* factory) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!observer_binding_.is_bound());
- DCHECK(!client_request_);
+ DCHECK(!observer_receiver_.is_bound());
+ DCHECK(!pending_client_receiver_);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("audio", "CreateStream", this, "device id",
device_id_);
awaiting_created_ = true;
@@ -153,18 +151,17 @@ void AudioInputStreamBroker::CreateStream(
user_input_monitor_->EnableKeyPressMonitoringWithMapping();
}
- media::mojom::AudioInputStreamClientPtr client;
- client_request_ = mojo::MakeRequest(&client);
+ mojo::PendingRemote<media::mojom::AudioInputStreamClient> client;
+ pending_client_receiver_ = client.InitWithNewPipeAndPassReceiver();
- media::mojom::AudioInputStreamPtr stream;
- media::mojom::AudioInputStreamRequest stream_request =
- mojo::MakeRequest(&stream);
+ mojo::PendingRemote<media::mojom::AudioInputStream> stream;
+ auto stream_receiver = stream.InitWithNewPipeAndPassReceiver();
- media::mojom::AudioInputStreamObserverPtr observer_ptr;
- observer_binding_.Bind(mojo::MakeRequest(&observer_ptr));
+ mojo::PendingRemote<media::mojom::AudioInputStreamObserver> observer;
+ observer_receiver_.Bind(observer.InitWithNewPipeAndPassReceiver());
// Unretained is safe because |this| owns |observer_binding_|.
- observer_binding_.set_connection_error_with_reason_handler(base::BindOnce(
+ observer_receiver_.set_disconnect_with_reason_handler(base::BindOnce(
&AudioInputStreamBroker::ObserverBindingLost, base::Unretained(this)));
// Note that the component id for AudioLog is used to differentiate between
@@ -172,10 +169,12 @@ void AudioInputStreamBroker::CreateStream(
// stream, the component id used doesn't matter.
constexpr int log_component_id = 0;
factory->CreateInputStream(
- std::move(stream_request), std::move(client), std::move(observer_ptr),
- MediaInternals::GetInstance()->CreateMojoAudioLog(
- media::AudioLogFactory::AudioComponent::AUDIO_INPUT_CONTROLLER,
- log_component_id, render_process_id(), render_frame_id()),
+ std::move(stream_receiver), std::move(client), std::move(observer),
+ MediaInternals::GetInstance()
+ ->CreateMojoAudioLog(
+ media::AudioLogFactory::AudioComponent::AUDIO_INPUT_CONTROLLER,
+ log_component_id, render_process_id(), render_frame_id())
+ .PassInterface(),
device_id_, params_, shared_memory_count_, enable_agc_,
mojo::WrapReadOnlySharedMemoryRegion(std::move(key_press_count_buffer)),
std::move(processing_config_),
@@ -189,7 +188,7 @@ void AudioInputStreamBroker::DidStartRecording() {
}
void AudioInputStreamBroker::StreamCreated(
- media::mojom::AudioInputStreamPtr stream,
+ mojo::PendingRemote<media::mojom::AudioInputStream> stream,
media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
bool initially_muted,
const base::Optional<base::UnguessableToken>& stream_id) {
@@ -208,8 +207,11 @@ void AudioInputStreamBroker::StreamCreated(
DCHECK(stream_id.has_value());
DCHECK(renderer_factory_client_);
renderer_factory_client_->StreamCreated(
- std::move(stream), std::move(client_request_), std::move(data_pipe),
- initially_muted, stream_id);
+ media::mojom::AudioInputStreamPtr(media::mojom::AudioInputStreamPtrInfo(
+ stream.PassPipe(), stream.version())),
+ media::mojom::AudioInputStreamClientRequest(
+ pending_client_receiver_.PassPipe()),
+ std::move(data_pipe), initially_muted, stream_id);
}
void AudioInputStreamBroker::ObserverBindingLost(
uint32_t reason,
diff --git a/chromium/content/browser/media/audio_input_stream_broker.h b/chromium/content/browser/media/audio_input_stream_broker.h
index 397cb49cd8b..cc63cac0f81 100644
--- a/chromium/content/browser/media/audio_input_stream_broker.h
+++ b/chromium/content/browser/media/audio_input_stream_broker.h
@@ -15,7 +15,9 @@
#include "media/base/audio_parameters.h"
#include "media/mojo/interfaces/audio_data_pipe.mojom.h"
#include "media/mojo/interfaces/audio_input_stream.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/audio/public/mojom/audio_processing.mojom.h"
#include "services/audio/public/mojom/stream_factory.mojom.h"
@@ -52,7 +54,7 @@ class CONTENT_EXPORT AudioInputStreamBroker final
void DidStartRecording() final;
private:
- void StreamCreated(media::mojom::AudioInputStreamPtr stream,
+ void StreamCreated(mojo::PendingRemote<media::mojom::AudioInputStream> stream,
media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
bool initially_muted,
const base::Optional<base::UnguessableToken>& stream_id);
@@ -73,15 +75,17 @@ class CONTENT_EXPORT AudioInputStreamBroker final
DeleterCallback deleter_;
audio::mojom::AudioProcessingConfigPtr processing_config_;
- mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client_;
- mojo::Binding<AudioInputStreamObserver> observer_binding_;
- media::mojom::AudioInputStreamClientRequest client_request_;
+ mojo::Remote<mojom::RendererAudioInputStreamFactoryClient>
+ renderer_factory_client_;
+ mojo::Receiver<AudioInputStreamObserver> observer_receiver_{this};
+ mojo::PendingReceiver<media::mojom::AudioInputStreamClient>
+ pending_client_receiver_;
media::mojom::AudioInputStreamObserver::DisconnectReason disconnect_reason_ =
media::mojom::AudioInputStreamObserver::DisconnectReason::
kDocumentDestroyed;
- base::WeakPtrFactory<AudioInputStreamBroker> weak_ptr_factory_;
+ base::WeakPtrFactory<AudioInputStreamBroker> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AudioInputStreamBroker);
};
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 c21c3176141..958997f5032 100644
--- a/chromium/content/browser/media/audio_input_stream_broker_unittest.cc
+++ b/chromium/content/browser/media/audio_input_stream_broker_unittest.cc
@@ -11,6 +11,7 @@
#include "base/test/mock_callback.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/mojo/interfaces/audio_input_stream.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "services/audio/public/cpp/fake_stream_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -42,8 +43,8 @@ using MockDeleterCallback = StrictMock<
class MockRendererAudioInputStreamFactoryClient
: public mojom::RendererAudioInputStreamFactoryClient {
public:
- MockRendererAudioInputStreamFactoryClient() : binding_(this) {}
- ~MockRendererAudioInputStreamFactoryClient() override {}
+ MockRendererAudioInputStreamFactoryClient() = default;
+ ~MockRendererAudioInputStreamFactoryClient() override = default;
mojom::RendererAudioInputStreamFactoryClientPtr MakePtr() {
mojom::RendererAudioInputStreamFactoryClientPtr ret;
@@ -68,7 +69,7 @@ class MockRendererAudioInputStreamFactoryClient
void CloseBinding() { binding_.Close(); }
private:
- mojo::Binding<mojom::RendererAudioInputStreamFactoryClient> binding_;
+ mojo::Binding<mojom::RendererAudioInputStreamFactoryClient> binding_{this};
media::mojom::AudioInputStreamPtr input_stream_;
media::mojom::AudioInputStreamClientRequest client_request_;
DISALLOW_COPY_AND_ASSIGN(MockRendererAudioInputStreamFactoryClient);
@@ -106,26 +107,26 @@ class MockStreamFactory : public audio::FakeStreamFactory {
private:
void CreateInputStream(
- media::mojom::AudioInputStreamRequest stream_request,
- media::mojom::AudioInputStreamClientPtr client,
- media::mojom::AudioInputStreamObserverPtr observer,
- media::mojom::AudioLogPtr log,
+ mojo::PendingReceiver<media::mojom::AudioInputStream> stream_receiver,
+ mojo::PendingRemote<media::mojom::AudioInputStreamClient> client,
+ mojo::PendingRemote<media::mojom::AudioInputStreamObserver> observer,
+ mojo::PendingRemote<media::mojom::AudioLog> log,
const std::string& device_id,
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool enable_agc,
mojo::ScopedSharedBufferHandle key_press_count_buffer,
audio::mojom::AudioProcessingConfigPtr processing_config,
- CreateInputStreamCallback created_callback) final {
+ CreateInputStreamCallback created_callback) override {
// No way to cleanly exit the test here in case of failure, so use CHECK.
CHECK(stream_request_data_);
EXPECT_EQ(stream_request_data_->device_id, device_id);
EXPECT_TRUE(stream_request_data_->params.Equals(params));
stream_request_data_->requested = true;
- stream_request_data_->stream_request = std::move(stream_request);
- stream_request_data_->client = std::move(client);
- stream_request_data_->observer = std::move(observer);
- stream_request_data_->log = std::move(log);
+ stream_request_data_->stream_request = std::move(stream_receiver);
+ stream_request_data_->client.Bind(std::move(client));
+ stream_request_data_->observer.Bind(std::move(observer));
+ stream_request_data_->log.Bind(std::move(log));
stream_request_data_->shared_memory_count = shared_memory_count;
stream_request_data_->enable_agc = enable_agc;
stream_request_data_->key_press_count_buffer =
@@ -158,7 +159,7 @@ struct TestEnvironment {
StrictMock<MockRendererAudioInputStreamFactoryClient> renderer_factory_client;
std::unique_ptr<AudioInputStreamBroker> broker;
MockStreamFactory stream_factory;
- audio::mojom::StreamFactoryPtr factory_ptr = stream_factory.MakePtr();
+ audio::mojom::StreamFactoryPtr factory_ptr{stream_factory.MakeRemote()};
};
} // namespace
diff --git a/chromium/content/browser/media/audio_loopback_stream_broker.cc b/chromium/content/browser/media/audio_loopback_stream_broker.cc
index 1b834987a49..474758e7118 100644
--- a/chromium/content/browser/media/audio_loopback_stream_broker.cc
+++ b/chromium/content/browser/media/audio_loopback_stream_broker.cc
@@ -87,8 +87,9 @@ void AudioLoopbackStreamBroker::CreateStream(
&AudioLoopbackStreamBroker::Cleanup, base::Unretained(this)));
factory->CreateLoopbackStream(
- std::move(stream_request), std::move(client), std::move(observer_ptr),
- params_, shared_memory_count_, source_->GetGroupID(),
+ std::move(stream_request), client.PassInterface(),
+ observer_ptr.PassInterface(), params_, shared_memory_count_,
+ source_->GetGroupID(),
base::BindOnce(&AudioLoopbackStreamBroker::StreamCreated,
weak_ptr_factory_.GetWeakPtr(), std::move(stream)));
}
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 f72c1d64c4b..4e361a213c4 100644
--- a/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc
+++ b/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc
@@ -121,9 +121,9 @@ class MockStreamFactory : public audio::FakeStreamFactory {
private:
void CreateLoopbackStream(
- media::mojom::AudioInputStreamRequest stream_request,
- media::mojom::AudioInputStreamClientPtr client,
- media::mojom::AudioInputStreamObserverPtr observer,
+ mojo::PendingReceiver<media::mojom::AudioInputStream> receiver,
+ mojo::PendingRemote<media::mojom::AudioInputStreamClient> client,
+ mojo::PendingRemote<media::mojom::AudioInputStreamObserver> observer,
const media::AudioParameters& params,
uint32_t shared_memory_count,
const base::UnguessableToken& group_id,
@@ -133,16 +133,17 @@ class MockStreamFactory : public audio::FakeStreamFactory {
EXPECT_EQ(stream_request_data_->group_id, group_id);
EXPECT_TRUE(stream_request_data_->params.Equals(params));
stream_request_data_->requested = true;
- stream_request_data_->stream_request = std::move(stream_request);
- stream_request_data_->client = std::move(client);
- stream_request_data_->observer = std::move(observer);
+ stream_request_data_->stream_request = std::move(receiver);
+ stream_request_data_->client.Bind(std::move(client));
+ stream_request_data_->observer.Bind(std::move(observer));
stream_request_data_->shared_memory_count = shared_memory_count;
stream_request_data_->created_callback = std::move(created_callback);
}
- void BindMuter(audio::mojom::LocalMuterAssociatedRequest request,
- const base::UnguessableToken& group_id) final {
- stream_request_data_->muter_request = std::move(request);
+ void BindMuter(
+ mojo::PendingAssociatedReceiver<audio::mojom::LocalMuter> receiver,
+ const base::UnguessableToken& group_id) final {
+ stream_request_data_->muter_request = std::move(receiver);
IsMuting(group_id);
}
@@ -171,7 +172,7 @@ struct TestEnvironment {
StrictMock<MockRendererAudioInputStreamFactoryClient> renderer_factory_client;
std::unique_ptr<AudioLoopbackStreamBroker> broker;
MockStreamFactory stream_factory;
- audio::mojom::StreamFactoryPtr factory_ptr = stream_factory.MakePtr();
+ audio::mojom::StreamFactoryPtr factory_ptr{stream_factory.MakeRemote()};
};
} // namespace
diff --git a/chromium/content/browser/media/audio_muting_session.cc b/chromium/content/browser/media/audio_muting_session.cc
index 891f5ab8374..e24e5758906 100644
--- a/chromium/content/browser/media/audio_muting_session.cc
+++ b/chromium/content/browser/media/audio_muting_session.cc
@@ -9,14 +9,14 @@ namespace content {
AudioMutingSession::AudioMutingSession(const base::UnguessableToken& group_id)
: group_id_(group_id) {}
-AudioMutingSession::~AudioMutingSession() {}
+AudioMutingSession::~AudioMutingSession() = default;
void AudioMutingSession::Connect(audio::mojom::StreamFactory* factory) {
if (muter_)
muter_.reset();
DCHECK(factory);
- factory->BindMuter(mojo::MakeRequest(&muter_), group_id_);
+ factory->BindMuter(muter_.BindNewEndpointAndPassReceiver(), group_id_);
}
} // namespace content
diff --git a/chromium/content/browser/media/audio_muting_session.h b/chromium/content/browser/media/audio_muting_session.h
index a13c13c17aa..5fe9789f423 100644
--- a/chromium/content/browser/media/audio_muting_session.h
+++ b/chromium/content/browser/media/audio_muting_session.h
@@ -9,6 +9,7 @@
#include "base/unguessable_token.h"
#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
#include "services/audio/public/mojom/stream_factory.mojom.h"
namespace content {
@@ -22,7 +23,7 @@ class CONTENT_EXPORT AudioMutingSession {
private:
const base::UnguessableToken group_id_;
- audio::mojom::LocalMuterAssociatedPtr muter_;
+ mojo::AssociatedRemote<audio::mojom::LocalMuter> muter_;
DISALLOW_COPY_AND_ASSIGN(AudioMutingSession);
};
diff --git a/chromium/content/browser/media/audio_output_stream_broker.cc b/chromium/content/browser/media/audio_output_stream_broker.cc
index 24a8438a4bf..cf1d1c25747 100644
--- a/chromium/content/browser/media/audio_output_stream_broker.cc
+++ b/chromium/content/browser/media/audio_output_stream_broker.cc
@@ -78,7 +78,7 @@ AudioOutputStreamBroker::AudioOutputStreamBroker(
deleter_(std::move(deleter)),
client_(std::move(client)),
observer_(render_process_id, render_frame_id, stream_id),
- observer_binding_(&observer_),
+ observer_receiver_(&observer_),
weak_ptr_factory_(this) {
DCHECK(client_);
DCHECK(deleter_);
@@ -126,38 +126,40 @@ AudioOutputStreamBroker::~AudioOutputStreamBroker() {
void AudioOutputStreamBroker::CreateStream(
audio::mojom::StreamFactory* factory) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
- DCHECK(!observer_binding_.is_bound());
+ DCHECK(!observer_receiver_.is_bound());
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("audio", "CreateStream", this, "device id",
output_device_id_);
stream_creation_start_time_ = base::TimeTicks::Now();
// Set up observer ptr. Unretained is safe because |this| owns
- // |observer_binding_|.
- media::mojom::AudioOutputStreamObserverAssociatedPtrInfo ptr_info;
- observer_binding_.Bind(mojo::MakeRequest(&ptr_info));
- observer_binding_.set_connection_error_with_reason_handler(base::BindOnce(
+ // |observer_receiver_|.
+ mojo::PendingAssociatedRemote<media::mojom::AudioOutputStreamObserver>
+ observer;
+ observer_receiver_.Bind(observer.InitWithNewEndpointAndPassReceiver());
+ observer_receiver_.set_disconnect_with_reason_handler(base::BindOnce(
&AudioOutputStreamBroker::ObserverBindingLost, base::Unretained(this)));
- media::mojom::AudioOutputStreamPtr stream;
- media::mojom::AudioOutputStreamRequest stream_request =
- mojo::MakeRequest(&stream);
+ mojo::PendingRemote<media::mojom::AudioOutputStream> stream;
+ auto stream_receiver = stream.InitWithNewPipeAndPassReceiver();
// Note that the component id for AudioLog is used to differentiate between
// several users of the same audio log. Since this audio log is for a single
// stream, the component id used doesn't matter.
constexpr int log_component_id = 0;
factory->CreateOutputStream(
- std::move(stream_request), std::move(ptr_info),
- MediaInternals::GetInstance()->CreateMojoAudioLog(
- media::AudioLogFactory::AudioComponent::AUDIO_OUTPUT_CONTROLLER,
- log_component_id, render_process_id(), render_frame_id()),
+ std::move(stream_receiver), std::move(observer),
+ MediaInternals::GetInstance()
+ ->CreateMojoAudioLog(
+ media::AudioLogFactory::AudioComponent::AUDIO_OUTPUT_CONTROLLER,
+ log_component_id, render_process_id(), render_frame_id())
+ .PassInterface(),
output_device_id_, params_, group_id_, processing_id_,
base::BindOnce(&AudioOutputStreamBroker::StreamCreated,
weak_ptr_factory_.GetWeakPtr(), std::move(stream)));
}
void AudioOutputStreamBroker::StreamCreated(
- media::mojom::AudioOutputStreamPtr stream,
+ mojo::PendingRemote<media::mojom::AudioOutputStream> stream,
media::mojom::ReadWriteAudioDataPipePtr data_pipe) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "CreateStream", this, "success",
@@ -174,7 +176,8 @@ void AudioOutputStreamBroker::StreamCreated(
return;
}
- client_->Created(std::move(stream), std::move(data_pipe));
+ client_->Created(media::mojom::AudioOutputStreamPtr(std::move(stream)),
+ std::move(data_pipe));
}
void AudioOutputStreamBroker::ObserverBindingLost(
diff --git a/chromium/content/browser/media/audio_output_stream_broker.h b/chromium/content/browser/media/audio_output_stream_broker.h
index 458a78caa6b..89518532341 100644
--- a/chromium/content/browser/media/audio_output_stream_broker.h
+++ b/chromium/content/browser/media/audio_output_stream_broker.h
@@ -17,7 +17,8 @@
#include "content/common/content_export.h"
#include "media/base/audio_parameters.h"
#include "media/mojo/interfaces/audio_output_stream.mojom.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/audio/public/mojom/stream_factory.mojom.h"
namespace content {
@@ -47,8 +48,9 @@ class CONTENT_EXPORT AudioOutputStreamBroker final : public AudioStreamBroker {
using DisconnectReason =
media::mojom::AudioOutputStreamObserver::DisconnectReason;
- void StreamCreated(media::mojom::AudioOutputStreamPtr stream,
- media::mojom::ReadWriteAudioDataPipePtr data_pipe);
+ void StreamCreated(
+ mojo::PendingRemote<media::mojom::AudioOutputStream> stream,
+ media::mojom::ReadWriteAudioDataPipePtr data_pipe);
void ObserverBindingLost(uint32_t reason, const std::string& description);
void Cleanup(DisconnectReason reason);
bool AwaitingCreated() const;
@@ -68,8 +70,8 @@ class CONTENT_EXPORT AudioOutputStreamBroker final : public AudioStreamBroker {
media::mojom::AudioOutputStreamProviderClientPtr client_;
AudioOutputStreamObserverImpl observer_;
- mojo::AssociatedBinding<media::mojom::AudioOutputStreamObserver>
- observer_binding_;
+ mojo::AssociatedReceiver<media::mojom::AudioOutputStreamObserver>
+ observer_receiver_;
DisconnectReason disconnect_reason_ = DisconnectReason::kDocumentDestroyed;
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 59e5b016e01..4a532d56934 100644
--- a/chromium/content/browser/media/audio_output_stream_broker_unittest.cc
+++ b/chromium/content/browser/media/audio_output_stream_broker_unittest.cc
@@ -110,9 +110,10 @@ class MockStreamFactory : public audio::FakeStreamFactory {
private:
void CreateOutputStream(
- media::mojom::AudioOutputStreamRequest stream_request,
- media::mojom::AudioOutputStreamObserverAssociatedPtrInfo observer_info,
- media::mojom::AudioLogPtr log,
+ mojo::PendingReceiver<media::mojom::AudioOutputStream> stream_receiver,
+ mojo::PendingAssociatedRemote<media::mojom::AudioOutputStreamObserver>
+ observer,
+ mojo::PendingRemote<media::mojom::AudioLog> log,
const std::string& output_device_id,
const media::AudioParameters& params,
const base::UnguessableToken& group_id,
@@ -124,9 +125,9 @@ class MockStreamFactory : public audio::FakeStreamFactory {
EXPECT_TRUE(stream_request_data_->params.Equals(params));
EXPECT_EQ(stream_request_data_->group_id, group_id);
stream_request_data_->requested = true;
- stream_request_data_->stream_request = std::move(stream_request);
- stream_request_data_->observer_info = std::move(observer_info);
- stream_request_data_->log = std::move(log);
+ stream_request_data_->stream_request = std::move(stream_receiver);
+ stream_request_data_->observer_info = std::move(observer);
+ stream_request_data_->log.Bind(std ::move(log));
stream_request_data_->created_callback = std::move(created_callback);
}
@@ -157,7 +158,7 @@ struct TestEnvironment {
StrictMock<MockAudioOutputStreamProviderClient> provider_client;
std::unique_ptr<AudioOutputStreamBroker> broker;
MockStreamFactory stream_factory;
- audio::mojom::StreamFactoryPtr factory_ptr = stream_factory.MakePtr();
+ audio::mojom::StreamFactoryPtr factory_ptr{stream_factory.MakeRemote()};
};
} // namespace
diff --git a/chromium/content/browser/media/capture/aura_window_video_capture_device_browsertest.cc b/chromium/content/browser/media/capture/aura_window_video_capture_device_browsertest.cc
index f8757b52dfd..ceedcf70836 100644
--- a/chromium/content/browser/media/capture/aura_window_video_capture_device_browsertest.cc
+++ b/chromium/content/browser/media/capture/aura_window_video_capture_device_browsertest.cc
@@ -24,7 +24,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/aura/window.h"
-#include "ui/base/ui_base_features.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -228,9 +227,6 @@ IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
// stopped.
IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
ErrorsOutWhenWindowIsDestroyed) {
- // TODO(crbug.com/877172): CopyOutputRequests not allowed.
- if (features::IsSingleProcessMash())
- return;
NavigateToInitialDocument();
AllocateAndStartAndWaitForFirstFrame();
@@ -253,9 +249,6 @@ IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
// to be delivered, to ensure the client is up-to-date.
IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
SuspendsAndResumes) {
- // TODO(crbug.com/877172): CopyOutputRequests not allowed.
- if (features::IsSingleProcessMash())
- return;
NavigateToInitialDocument();
AllocateAndStartAndWaitForFirstFrame();
@@ -290,9 +283,6 @@ IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
// content is not changing.
IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
DeliversRefreshFramesUponRequest) {
- // TODO(crbug.com/877172): CopyOutputRequests not allowed.
- if (features::IsSingleProcessMash())
- return;
NavigateToInitialDocument();
AllocateAndStartAndWaitForFirstFrame();
@@ -316,9 +306,6 @@ IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
// Make sure the visibility is set to visible during capture if it's occluded.
IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
CapturesOccludedWindows) {
- // TODO(crbug.com/877172): CopyOutputRequests not allowed.
- if (features::IsSingleProcessMash())
- return;
NavigateToInitialDocument();
AllocateAndStartAndWaitForFirstFrame();
@@ -375,9 +362,6 @@ INSTANTIATE_TEST_SUITE_P(
// compositing.
IN_PROC_BROWSER_TEST_P(AuraWindowVideoCaptureDeviceBrowserTestP,
CapturesContentChanges) {
- // TODO(crbug.com/877172): CopyOutputRequests not allowed.
- if (features::IsSingleProcessMash())
- return;
SCOPED_TRACE(testing::Message()
<< "Test parameters: "
<< (IsSoftwareCompositingTest() ? "Software Compositing"
diff --git a/chromium/content/browser/media/capture/desktop_capture_device.cc b/chromium/content/browser/media/capture/desktop_capture_device.cc
index ef2d53d1884..9a25c234fce 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device.cc
@@ -47,6 +47,7 @@
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
#include "third_party/webrtc/modules/desktop_capture/fake_desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
+#include "ui/gfx/icc_profile.h"
namespace content {
@@ -428,6 +429,13 @@ void DesktopCaptureDevice::Core::OnCaptureResult(
}
}
+ gfx::ColorSpace frame_color_space;
+ if (!frame->icc_profile().empty()) {
+ gfx::ICCProfile icc_profile = gfx::ICCProfile::FromData(
+ frame->icc_profile().data(), frame->icc_profile().size());
+ frame_color_space = icc_profile.GetColorSpace();
+ }
+
base::TimeTicks now = NowTicks();
if (first_ref_time_.is_null())
first_ref_time_ = now;
@@ -436,7 +444,7 @@ void DesktopCaptureDevice::Core::OnCaptureResult(
media::VideoCaptureFormat(
gfx::Size(output_size.width(), output_size.height()),
requested_frame_rate_, media::PIXEL_FORMAT_ARGB),
- 0, now, now - first_ref_time_);
+ frame_color_space, 0, now, now - first_ref_time_);
}
void DesktopCaptureDevice::Core::OnCaptureTimer() {
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
index 3a596dc9ff0..9c31de7bf16 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -218,6 +218,7 @@ class DesktopCaptureDeviceTest : public testing::Test {
void CopyFrame(const uint8_t* frame,
int size,
const media::VideoCaptureFormat&,
+ const gfx::ColorSpace&,
int,
base::TimeTicks,
base::TimeDelta,
@@ -269,7 +270,7 @@ TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
CreateMockVideoCaptureDeviceClient());
EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
EXPECT_CALL(*client, OnStarted());
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _, _))
.WillRepeatedly(
DoAll(SaveArg<1>(&frame_size), SaveArg<2>(&format),
InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
@@ -308,7 +309,7 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
CreateMockVideoCaptureDeviceClient());
EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
EXPECT_CALL(*client, OnStarted());
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _, _))
.WillRepeatedly(
DoAll(WithArg<2>(Invoke(&format_checker,
&FormatChecker::ExpectAcceptableSize)),
@@ -354,7 +355,7 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeFixedAspectRatio) {
CreateMockVideoCaptureDeviceClient());
EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
EXPECT_CALL(*client, OnStarted());
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _, _))
.WillRepeatedly(
DoAll(WithArg<2>(Invoke(&format_checker,
&FormatChecker::ExpectAcceptableSize)),
@@ -404,7 +405,7 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
CreateMockVideoCaptureDeviceClient());
EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
EXPECT_CALL(*client, OnStarted());
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _, _))
.WillRepeatedly(
DoAll(WithArg<2>(Invoke(&format_checker,
&FormatChecker::ExpectAcceptableSize)),
@@ -456,7 +457,7 @@ TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) {
CreateMockVideoCaptureDeviceClient());
EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
EXPECT_CALL(*client, OnStarted());
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _, _))
.WillRepeatedly(
DoAll(Invoke(this, &DesktopCaptureDeviceTest::CopyFrame),
SaveArg<1>(&frame_size),
@@ -505,7 +506,7 @@ TEST_F(DesktopCaptureDeviceTest, InvertedFrame) {
CreateMockVideoCaptureDeviceClient());
EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
EXPECT_CALL(*client, OnStarted());
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _, _))
.WillRepeatedly(
DoAll(Invoke(this, &DesktopCaptureDeviceTest::CopyFrame),
SaveArg<1>(&frame_size),
@@ -571,12 +572,12 @@ class DesktopCaptureDeviceThrottledTest : public DesktopCaptureDeviceTest {
task_runner, task_runner->GetMockTickClock());
}));
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _, _))
.WillRepeatedly(DoAll(
WithArg<2>(
Invoke(&format_checker, &FormatChecker::ExpectAcceptableSize)),
- WithArg<5>(Invoke([&done_event, &nb_frames, &task_runner]
- (base::TimeDelta timestamp) {
+ WithArg<6>(Invoke([&done_event, &nb_frames,
+ &task_runner](base::TimeDelta timestamp) {
++nb_frames;
// Simulate real device capture time. Indeed the time spent
diff --git a/chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc b/chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc
index ca204dd0458..30c5fe70b40 100644
--- a/chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc
+++ b/chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc
@@ -17,10 +17,11 @@ const int kFrameRate = 30;
class MockDeviceClient : public media::VideoCaptureDevice::Client {
public:
- MOCK_METHOD7(OnIncomingCapturedData,
+ MOCK_METHOD8(OnIncomingCapturedData,
void(const uint8_t* data,
int length,
const media::VideoCaptureFormat& frame_format,
+ const gfx::ColorSpace& color_space,
int rotation,
base::TimeTicks reference_time,
base::TimeDelta tiemstamp,
diff --git a/chromium/content/browser/media/capture/web_contents_audio_muter.cc b/chromium/content/browser/media/capture/web_contents_audio_muter.cc
index 95fce2adf2c..386ebee5211 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_muter.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_muter.cc
@@ -52,6 +52,7 @@ class AudioDiscarder : public media::AudioOutputStream {
void SetVolume(double volume) override {}
void GetVolume(double* volume) override { *volume = 0; }
void Close() override { delete this; }
+ void Flush() override {}
private:
~AudioDiscarder() override {}
diff --git a/chromium/content/browser/media/flinging_renderer.cc b/chromium/content/browser/media/flinging_renderer.cc
index 83cf1aa55a7..336efe119e2 100644
--- a/chromium/content/browser/media/flinging_renderer.cc
+++ b/chromium/content/browser/media/flinging_renderer.cc
@@ -4,6 +4,8 @@
#include "content/browser/media/flinging_renderer.h"
+#include <utility>
+
#include "base/memory/ptr_util.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
@@ -15,8 +17,10 @@
namespace content {
FlingingRenderer::FlingingRenderer(
- std::unique_ptr<media::FlingingController> controller)
- : controller_(std::move(controller)) {
+ std::unique_ptr<media::FlingingController> controller,
+ ClientExtensionPtr client_extension)
+ : client_extension_(std::move(client_extension)),
+ controller_(std::move(controller)) {
controller_->AddMediaStatusObserver(this);
}
@@ -27,7 +31,8 @@ FlingingRenderer::~FlingingRenderer() {
// static
std::unique_ptr<FlingingRenderer> FlingingRenderer::Create(
RenderFrameHost* render_frame_host,
- const std::string& presentation_id) {
+ const std::string& presentation_id,
+ ClientExtensionPtr client_extension) {
DVLOG(1) << __func__;
ContentClient* content_client = GetContentClient();
@@ -54,8 +59,8 @@ std::unique_ptr<FlingingRenderer> FlingingRenderer::Create(
if (!flinging_controller)
return nullptr;
- return base::WrapUnique<FlingingRenderer>(
- new FlingingRenderer(std::move(flinging_controller)));
+ return base::WrapUnique<FlingingRenderer>(new FlingingRenderer(
+ std::move(flinging_controller), std::move(client_extension)));
}
// media::Renderer implementation
@@ -158,7 +163,7 @@ void FlingingRenderer::OnMediaStatusUpdated(const media::MediaStatus& status) {
// reached a new stable PlayState without WMPI having asked for it.
// Let WMPI know it should update itself.
if (current_state != target_play_state_)
- client_->OnRemotePlayStateChange(current_state);
+ client_extension_->OnRemotePlayStateChange(current_state);
}
} // namespace content
diff --git a/chromium/content/browser/media/flinging_renderer.h b/chromium/content/browser/media/flinging_renderer.h
index 5279b14e704..f4debfbdfe7 100644
--- a/chromium/content/browser/media/flinging_renderer.h
+++ b/chromium/content/browser/media/flinging_renderer.h
@@ -12,6 +12,7 @@
#include "media/base/media_status_observer.h"
#include "media/base/renderer.h"
#include "media/base/renderer_client.h"
+#include "media/mojo/interfaces/renderer_extensions.mojom.h"
#include "url/gurl.h"
namespace content {
@@ -27,13 +28,16 @@ class RenderFrameHost;
class CONTENT_EXPORT FlingingRenderer : public media::Renderer,
media::MediaStatusObserver {
public:
+ using ClientExtensionPtr = media::mojom::FlingingRendererClientExtensionPtr;
+
// Helper method to create a FlingingRenderer from an already existing
// presentation ID.
// Returns nullptr if there was an error getting the MediaControllor for the
// given presentation ID.
static std::unique_ptr<FlingingRenderer> Create(
RenderFrameHost* render_frame_host,
- const std::string& presentation_id);
+ const std::string& presentation_id,
+ ClientExtensionPtr client_extension);
~FlingingRenderer() override;
@@ -57,7 +61,8 @@ class CONTENT_EXPORT FlingingRenderer : public media::Renderer,
using PlayState = media::MediaStatus::State;
explicit FlingingRenderer(
- std::unique_ptr<media::FlingingController> controller);
+ std::unique_ptr<media::FlingingController> controller,
+ ClientExtensionPtr client_extension);
void SetTargetPlayState(PlayState state);
@@ -69,6 +74,8 @@ class CONTENT_EXPORT FlingingRenderer : public media::Renderer,
media::RendererClient* client_;
+ ClientExtensionPtr client_extension_;
+
std::unique_ptr<media::FlingingController> 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 af57fbbdc3f..b2a9a408777 100644
--- a/chromium/content/browser/media/flinging_renderer_unittest.cc
+++ b/chromium/content/browser/media/flinging_renderer_unittest.cc
@@ -53,7 +53,8 @@ class FlingingRendererTest : public testing::Test {
EXPECT_CALL(*flinging_controller_, RemoveMediaStatusObserver(_));
renderer_ = base::WrapUnique(new FlingingRenderer(
- std::unique_ptr<media::FlingingController>(flinging_controller_)));
+ std::unique_ptr<media::FlingingController>(flinging_controller_),
+ nullptr));
renderer_->Initialize(nullptr, &renderer_client_, base::DoNothing());
}
diff --git a/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc b/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc
index 5401a18ce06..c7c84bb67f8 100644
--- a/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc
+++ b/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc
@@ -19,9 +19,7 @@
#include "content/public/test/test_renderer_host.h"
#include "media/base/audio_parameters.h"
#include "media/mojo/interfaces/audio_output_stream.mojom.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "services/audio/public/cpp/fake_stream_factory.h"
#include "services/audio/public/mojom/constants.mojom.h"
#include "services/audio/public/mojom/stream_factory.mojom.h"
@@ -42,24 +40,23 @@ namespace {
class MockStreamFactory : public audio::FakeStreamFactory,
public audio::mojom::LocalMuter {
public:
- MockStreamFactory() : muter_binding_(this) {}
- ~MockStreamFactory() final {}
+ MockStreamFactory() = default;
+ ~MockStreamFactory() final = default;
- bool IsConnected() {
- return binding_ && !binding_.handle().QuerySignalsState().peer_closed();
- }
- bool IsMuterConnected() { return muter_binding_.is_bound(); }
+ bool IsConnected() const { return receiver_.is_bound(); }
+ bool IsMuterConnected() const { return muter_receiver_.is_bound(); }
private:
- void BindMuter(audio::mojom::LocalMuterAssociatedRequest request,
- const base::UnguessableToken& group_id) final {
- muter_binding_.Bind(std::move(request));
- muter_binding_.set_connection_error_handler(base::BindOnce(
- &MockStreamFactory::MuterUnbound, base::Unretained(this)));
+ void BindMuter(
+ mojo::PendingAssociatedReceiver<audio::mojom::LocalMuter> receiver,
+ const base::UnguessableToken& group_id) final {
+ muter_receiver_.Bind(std::move(receiver));
+ muter_receiver_.set_disconnect_handler(base::BindOnce(
+ &MockStreamFactory::MuterDisconnected, base::Unretained(this)));
}
- void MuterUnbound() { muter_binding_.Close(); }
+ void MuterDisconnected() { muter_receiver_.reset(); }
- mojo::AssociatedBinding<audio::mojom::LocalMuter> muter_binding_;
+ mojo::AssociatedReceiver<audio::mojom::LocalMuter> muter_receiver_{this};
DISALLOW_COPY_AND_ASSIGN(MockStreamFactory);
};
@@ -206,9 +203,13 @@ class ForwardingAudioStreamFactoryTest : public RenderViewHostTestHarness {
RenderFrameHostTester::For(main_rfh())->AppendChild("other_rfh");
}
- void BindFactory(mojo::ScopedMessagePipeHandle factory_request) {
- stream_factory_.binding_.Bind(
- audio::mojom::StreamFactoryRequest(std::move(factory_request)));
+ void BindFactory(mojo::ScopedMessagePipeHandle factory_receiver) {
+ stream_factory_.receiver_.Bind(
+ mojo::PendingReceiver<audio::mojom::StreamFactory>(
+ std::move(factory_receiver)));
+ stream_factory_.receiver_.set_disconnect_handler(
+ base::BindRepeating(&audio::FakeStreamFactory::CloseBinding,
+ base::Unretained(&stream_factory_)));
}
base::WeakPtr<MockBroker> ExpectLoopbackBrokerConstruction(
@@ -639,7 +640,8 @@ TEST_F(ForwardingAudioStreamFactoryTest, LastStreamDeleted_ClearsFactoryPtr) {
// Connection should still be open, since there's still a stream left.
EXPECT_TRUE(stream_factory_.IsConnected());
std::move(main_rfh_output_broker->deleter).Run(&*main_rfh_output_broker);
- base::RunLoop().RunUntilIdle();
+ stream_factory_.WaitForDisconnect();
+
// Now there are no streams left, connection should be broken.
EXPECT_FALSE(stream_factory_.IsConnected());
}
diff --git a/chromium/content/browser/media/hardware_key_media_controller.cc b/chromium/content/browser/media/hardware_key_media_controller.cc
index 402e55e15d2..cbacde7825a 100644
--- a/chromium/content/browser/media/hardware_key_media_controller.cc
+++ b/chromium/content/browser/media/hardware_key_media_controller.cc
@@ -9,6 +9,8 @@
#include <vector>
#include "base/metrics/histogram_macros.h"
+#include "content/browser/browser_main_loop.h"
+#include "content/browser/media/media_keys_listener_manager_impl.h"
#include "content/public/browser/media_keys_listener_manager.h"
#include "services/media_session/public/mojom/constants.mojom.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
@@ -46,7 +48,14 @@ HardwareKeyMediaController::~HardwareKeyMediaController() = default;
void HardwareKeyMediaController::MediaSessionInfoChanged(
media_session::mojom::MediaSessionInfoPtr session_info) {
+ MediaKeysListenerManagerImpl* media_keys_listener_manager_impl =
+ BrowserMainLoop::GetInstance()->media_keys_listener_manager();
+ DCHECK(media_keys_listener_manager_impl);
+
session_info_ = std::move(session_info);
+ media_keys_listener_manager_impl->SetIsMediaPlaying(
+ session_info_ && session_info_->playback_state ==
+ media_session::mojom::MediaPlaybackState::kPlaying);
}
void HardwareKeyMediaController::MediaSessionActionsChanged(
diff --git a/chromium/content/browser/media/key_system_support_impl.cc b/chromium/content/browser/media/key_system_support_impl.cc
index 7edf944070c..f28585a8944 100644
--- a/chromium/content/browser/media/key_system_support_impl.cc
+++ b/chromium/content/browser/media/key_system_support_impl.cc
@@ -115,13 +115,7 @@ void GetHardwareSecureDecryptionCaps(
return;
}
-#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
- if (!base::FeatureList::IsEnabled(media::kMojoVideoDecoder)) {
- DVLOG(1) << "Hardware secure codecs not supported because mojo video "
- "decode was disabled at runtime";
- return;
- }
-#else
+#if !BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
DVLOG(1) << "Hardware secure codecs not supported because mojo video "
"decode was disabled at buildtime";
return;
diff --git a/chromium/content/browser/media/media_experiment_manager.cc b/chromium/content/browser/media/media_experiment_manager.cc
new file mode 100644
index 00000000000..97d91b88589
--- /dev/null
+++ b/chromium/content/browser/media/media_experiment_manager.cc
@@ -0,0 +1,89 @@
+// Copyright 2019 The Chromium Authors. All rights 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/media_experiment_manager.h"
+
+#include <utility>
+
+#include "base/bind_helpers.h"
+
+namespace content {
+
+MediaExperimentManager::ScopedPlayerState::ScopedPlayerState(
+ base::OnceClosure destruction_cb,
+ PlayerState* state)
+ : state_(state), destruction_cb_(std::move(destruction_cb)) {}
+
+MediaExperimentManager::ScopedPlayerState::ScopedPlayerState(
+ ScopedPlayerState&& rhs) {
+ destruction_cb_ = std::move(rhs.destruction_cb_);
+ state_ = rhs.state_;
+}
+
+MediaExperimentManager::ScopedPlayerState::~ScopedPlayerState() {
+ if (destruction_cb_)
+ std::move(destruction_cb_).Run();
+}
+
+MediaExperimentManager::MediaExperimentManager() = default;
+
+MediaExperimentManager::~MediaExperimentManager() = default;
+
+// Keeps track of all media players across all pages, and notifies them when
+// they enter or leave an active experiment.
+void MediaExperimentManager::PlayerCreated(const MediaPlayerId& player_id,
+ Client* client) {
+ // TODO: check that we don't know about it already.
+ player_ids_by_client_[client].insert(player_id);
+ players_[player_id].client = client;
+}
+
+void MediaExperimentManager::PlayerDestroyed(const MediaPlayerId& player_id) {
+ ErasePlayersInternal({player_id});
+}
+
+MediaExperimentManager::ScopedPlayerState
+MediaExperimentManager::GetPlayerState(const MediaPlayerId& player_id) {
+ auto iter = players_.find(player_id);
+ DCHECK(iter != players_.end());
+ // TODO(liberato): Replace this callback with something that checks the
+ // experiment state, to see if an experiment has started / stopped.
+ return ScopedPlayerState(base::DoNothing(), &iter->second);
+}
+
+void MediaExperimentManager::ClientDestroyed(Client* client) {
+ auto by_client = player_ids_by_client_.find(client);
+ // Make a copy, since ErasePlayers will modify the original.
+ ErasePlayersInternal(std::set<MediaPlayerId>(by_client->second));
+}
+
+void MediaExperimentManager::ErasePlayersInternal(
+ const std::set<MediaPlayerId>& player_ids) {
+ for (auto player_id : player_ids) {
+ auto player_iter = players_.find(player_id);
+ DCHECK(player_iter != players_.end());
+
+ // Erase this player from the client, and maybe the client if it's the
+ // only player owned by it.
+ auto by_client_iter =
+ player_ids_by_client_.find(player_iter->second.client);
+ DCHECK(by_client_iter != player_ids_by_client_.end());
+ by_client_iter->second.erase(player_id);
+ if (by_client_iter->second.size() == 0)
+ player_ids_by_client_.erase(by_client_iter);
+
+ players_.erase(player_iter);
+ }
+}
+
+size_t MediaExperimentManager::GetPlayerCountForTesting() const {
+ return players_.size();
+}
+
+// static
+MediaExperimentManager* MediaExperimentManager::Instance() {
+ return nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/media_experiment_manager.h b/chromium/content/browser/media/media_experiment_manager.h
new file mode 100644
index 00000000000..a2eaaa19092
--- /dev/null
+++ b/chromium/content/browser/media/media_experiment_manager.h
@@ -0,0 +1,112 @@
+// Copyright 2019 The Chromium Authors. All rights 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_MEDIA_EXPERIMENT_MANAGER_H_
+#define CONTENT_BROWSER_MEDIA_MEDIA_EXPERIMENT_MANAGER_H_
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/media_player_id.h"
+#include "media/base/video_codecs.h"
+
+namespace content {
+
+// Keeps track of all media players across all pages, and notifies them when
+// they enter or leave an active experiment.
+class CONTENT_EXPORT MediaExperimentManager {
+ public:
+ // The Client interface allows the manager to send messages back to the
+ // player about experiment state.
+ class CONTENT_EXPORT Client {
+ public:
+ Client() = default;
+ virtual ~Client() = default;
+
+ // Called when |player| becomes the focus of some experiment.
+ // TODO: Should include an ExperimentId, so the player knows what to do.
+ virtual void OnExperimentStarted(const MediaPlayerId& player) = 0;
+
+ // Called when |player| stops being the focus of some experiment. Not
+ // called when the player is destroyed, or the player's client is destroyed,
+ // even though it does quit being the focus at that point too.
+ // TODO: Should include an ExperimentId, so the player knows what to do.
+ virtual void OnExperimentStopped(const MediaPlayerId& player) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Client);
+ };
+
+ // State for one media player.
+ struct PlayerState {
+ Client* client = nullptr;
+ bool is_playing = false;
+ bool is_fullscreen = false;
+ bool is_pip = false;
+ };
+
+ class CONTENT_EXPORT ScopedPlayerState {
+ public:
+ ScopedPlayerState(base::OnceClosure destruction_cb, PlayerState* state);
+ ScopedPlayerState(ScopedPlayerState&&);
+ ~ScopedPlayerState();
+
+ PlayerState* operator->() { return state_; }
+
+ private:
+ PlayerState* state_;
+ base::OnceClosure destruction_cb_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedPlayerState);
+ };
+
+ MediaExperimentManager();
+ virtual ~MediaExperimentManager();
+
+ static MediaExperimentManager* Instance();
+
+ // Notifies us that |player| has been created, and is being managed by
+ // |client|. |client| must exist until all its players have been destroyed
+ // via calls to DestroyPlayer, or the client calls ClientDestroyed().
+ virtual void PlayerCreated(const MediaPlayerId& player, Client* client);
+
+ // Called when the given player has been destroyed.
+ virtual void PlayerDestroyed(const MediaPlayerId& player);
+
+ // Notify us that |client| is being destroyed. All players that it created
+ // will be deleted. No further notifications will be sent to it. This is
+ // useful, for example, when a page is being destroyed so that we don't keep
+ // sending notifications while everything is being torn down. It's not an
+ // error if |client| has no active players.
+ virtual void ClientDestroyed(Client* client);
+
+ // Update the player state. When the returned ScopedMediaPlayerState is
+ // destroyed, we will process the changes. One may not create or destroy
+ // players while the ScopedMediaPlayerState exists.
+ virtual ScopedPlayerState GetPlayerState(const MediaPlayerId& player);
+
+ // Return the number of players total.
+ size_t GetPlayerCountForTesting() const;
+
+ private:
+ // Erase all players in |player_ids|. Does not send any notifications, nor
+ // does it FindRunningExperiments.
+ void ErasePlayersInternal(const std::set<MediaPlayerId>& player_ids);
+
+ // Set of all players that we know about.
+ std::map<MediaPlayerId, PlayerState> players_;
+
+ // [client] == set of all player ids that it owns.
+ std::map<Client*, std::set<MediaPlayerId>> player_ids_by_client_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaExperimentManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_MEDIA_EXPERIMENT_MANAGER_H_
diff --git a/chromium/content/browser/media/media_experiment_manager_unittest.cc b/chromium/content/browser/media/media_experiment_manager_unittest.cc
new file mode 100644
index 00000000000..838363652cc
--- /dev/null
+++ b/chromium/content/browser/media/media_experiment_manager_unittest.cc
@@ -0,0 +1,152 @@
+// Copyright 2019 The Chromium Authors. All rights 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/media_experiment_manager.h"
+
+#include "base/bind_helpers.h"
+#include "base/memory/ptr_util.h"
+#include "base/time/time.h"
+#include "base/version.h"
+#include "media/base/media_controller.h"
+#include "media/base/mock_filters.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+using ScopedPlayerState = MediaExperimentManager::ScopedPlayerState;
+
+class MockExperimentClient : public MediaExperimentManager::Client {
+ public:
+ MOCK_METHOD1(OnExperimentStarted, void(const MediaPlayerId& player));
+ MOCK_METHOD1(OnExperimentStopped, void(const MediaPlayerId& player));
+};
+
+class MediaExperimentManagerTest : public testing::Test {
+ public:
+ MediaExperimentManagerTest()
+ : manager_(std::make_unique<MediaExperimentManager>()),
+ player_id_1_(nullptr, 1),
+ player_id_2_(nullptr, 2) {}
+
+ protected:
+ std::unique_ptr<MediaExperimentManager> manager_;
+ // Unique player IDs. Note that we can't CreateMediaPlayerIdForTesting()
+ // since it doesn't return unique IDs.
+ MediaPlayerId player_id_1_;
+ MediaPlayerId player_id_2_;
+};
+
+TEST_F(MediaExperimentManagerTest, CreateAndDestroyPlayer) {
+ MockExperimentClient client;
+
+ EXPECT_EQ(manager_->GetPlayerCountForTesting(), 0u);
+
+ manager_->PlayerCreated(player_id_1_, &client);
+ EXPECT_EQ(manager_->GetPlayerCountForTesting(), 1u);
+
+ manager_->PlayerCreated(player_id_2_, &client);
+ EXPECT_EQ(manager_->GetPlayerCountForTesting(), 2u);
+
+ manager_->PlayerDestroyed(player_id_1_);
+ EXPECT_EQ(manager_->GetPlayerCountForTesting(), 1u);
+
+ manager_->PlayerDestroyed(player_id_2_);
+ EXPECT_EQ(manager_->GetPlayerCountForTesting(), 0u);
+}
+
+TEST_F(MediaExperimentManagerTest, CreatePlayerAndDestroyClient) {
+ // Create two players from one client, and make sure that destroying the
+ // client destroys both players.
+ MockExperimentClient client;
+
+ manager_->PlayerCreated(player_id_1_, &client);
+ manager_->PlayerCreated(player_id_2_, &client);
+ EXPECT_EQ(manager_->GetPlayerCountForTesting(), 2u);
+
+ manager_->ClientDestroyed(&client);
+ EXPECT_EQ(manager_->GetPlayerCountForTesting(), 0u);
+}
+
+TEST_F(MediaExperimentManagerTest, CreateTwoClientsAndDestroyOneClient) {
+ // Create one player each in two clients, and verify that destroying one
+ // client destroys only one player.
+ MockExperimentClient client_1;
+ MockExperimentClient client_2;
+
+ manager_->PlayerCreated(player_id_1_, &client_1);
+ manager_->PlayerCreated(player_id_2_, &client_2);
+ EXPECT_EQ(manager_->GetPlayerCountForTesting(), 2u);
+
+ manager_->ClientDestroyed(&client_1);
+ EXPECT_EQ(manager_->GetPlayerCountForTesting(), 1u);
+}
+
+TEST_F(MediaExperimentManagerTest, ScopedPlayerStateModifiesState) {
+ MockExperimentClient client_1;
+ MockExperimentClient client_2;
+
+ manager_->PlayerCreated(player_id_1_, &client_1);
+ manager_->PlayerCreated(player_id_2_, &client_2);
+ // Set the player state differently for each player. We set two things so
+ // that each player has a non-default value.
+ {
+ ScopedPlayerState state = manager_->GetPlayerState(player_id_1_);
+ state->is_fullscreen = true;
+ state->is_pip = false;
+ }
+
+ {
+ ScopedPlayerState state = manager_->GetPlayerState(player_id_2_);
+ state->is_fullscreen = false;
+ state->is_pip = true;
+ }
+
+ // Make sure that the player state matches what we set for it.
+ {
+ ScopedPlayerState state = manager_->GetPlayerState(player_id_1_);
+ EXPECT_TRUE(state->is_fullscreen);
+ EXPECT_FALSE(state->is_pip);
+ }
+
+ {
+ ScopedPlayerState state = manager_->GetPlayerState(player_id_2_);
+ EXPECT_FALSE(state->is_fullscreen);
+ EXPECT_TRUE(state->is_pip);
+ }
+}
+
+TEST_F(MediaExperimentManagerTest, ScopedPlayerStateCallsCallback) {
+ bool cb_called = false;
+ base::OnceClosure cb = base::BindOnce([](bool* flag) { *flag = true; },
+ base::Unretained(&cb_called));
+ MediaExperimentManager::PlayerState state;
+ state.is_fullscreen = false;
+
+ // Normally, these would not by dynamically allocated. However, this makes
+ // it much easier to control when they're destroyed. This is also why we
+ // reference the underying state as (*scoped_1)-> ; we want tp use the
+ // overloaded -> operator on ScopedPlayerState, not unique_ptr.
+ std::unique_ptr<ScopedPlayerState> scoped_1 =
+ std::make_unique<ScopedPlayerState>(std::move(cb), &state);
+ (*scoped_1)->is_fullscreen = true;
+ EXPECT_TRUE(state.is_fullscreen);
+ EXPECT_FALSE(cb_called);
+
+ // Moving |scoped_1| and deleting it should not call the callback.
+ std::unique_ptr<ScopedPlayerState> scoped_2 =
+ std::make_unique<ScopedPlayerState>(std::move(*scoped_1));
+ scoped_1.reset();
+ EXPECT_FALSE(cb_called);
+
+ // |scoped_2| should now modify |state|.
+ (*scoped_2)->is_fullscreen = false;
+ EXPECT_FALSE(state.is_fullscreen);
+
+ // Deleting |scoped_2| should call the callback.
+ scoped_2.reset();
+ EXPECT_TRUE(cb_called);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/media_interface_proxy.cc b/chromium/content/browser/media/media_interface_proxy.cc
index 800af414b7d..53ac65c8d3f 100644
--- a/chromium/content/browser/media/media_interface_proxy.cc
+++ b/chromium/content/browser/media/media_interface_proxy.cc
@@ -177,13 +177,15 @@ void MediaInterfaceProxy::CreateCastRenderer(
#if defined(OS_ANDROID)
void MediaInterfaceProxy::CreateFlingingRenderer(
const std::string& presentation_id,
+ media::mojom::FlingingRendererClientExtensionPtr client_extension,
media::mojom::RendererRequest request) {
DCHECK(thread_checker_.CalledOnValidThread());
- std::unique_ptr<FlingingRenderer> renderer =
- FlingingRenderer::Create(render_frame_host_, presentation_id);
- media::MojoRendererService::Create(nullptr, std::move(renderer),
- std::move(request));
+ media::MojoRendererService::Create(
+ nullptr,
+ FlingingRenderer::Create(render_frame_host_, presentation_id,
+ std::move(client_extension)),
+ std::move(request));
}
void MediaInterfaceProxy::CreateMediaPlayerRenderer(
diff --git a/chromium/content/browser/media/media_interface_proxy.h b/chromium/content/browser/media/media_interface_proxy.h
index 90221c95972..ae405bd318b 100644
--- a/chromium/content/browser/media/media_interface_proxy.h
+++ b/chromium/content/browser/media/media_interface_proxy.h
@@ -56,8 +56,10 @@ class MediaInterfaceProxy : public media::mojom::InterfaceFactory {
media::mojom::RendererRequest request) final;
#endif
#if defined(OS_ANDROID)
- void CreateFlingingRenderer(const std::string& presentation_id,
- media::mojom::RendererRequest request) final;
+ void CreateFlingingRenderer(
+ const std::string& presentation_id,
+ media::mojom::FlingingRendererClientExtensionPtr client_extension,
+ media::mojom::RendererRequest request) final;
void CreateMediaPlayerRenderer(
media::mojom::MediaPlayerRendererClientExtensionPtr client_extension_ptr,
media::mojom::RendererRequest request,
diff --git a/chromium/content/browser/media/media_internals_ui.cc b/chromium/content/browser/media/media_internals_ui.cc
index 7d4b7fe5fe4..524fc4630b4 100644
--- a/chromium/content/browser/media/media_internals_ui.cc
+++ b/chromium/content/browser/media/media_internals_ui.cc
@@ -24,7 +24,6 @@ WebUIDataSource* CreateMediaInternalsHTMLSource() {
source->AddResourcePath("media_internals.js", IDR_MEDIA_INTERNALS_JS);
source->SetDefaultResource(IDR_MEDIA_INTERNALS_HTML);
- source->UseGzip();
return source;
}
diff --git a/chromium/content/browser/media/media_keys_listener_manager_impl.cc b/chromium/content/browser/media/media_keys_listener_manager_impl.cc
index 6802e42ef0e..a2e879f9179 100644
--- a/chromium/content/browser/media/media_keys_listener_manager_impl.cc
+++ b/chromium/content/browser/media/media_keys_listener_manager_impl.cc
@@ -130,7 +130,7 @@ void MediaKeysListenerManagerImpl::OnMediaKeysAccelerator(
// We should never receive an accelerator that was never registered.
DCHECK(delegate_map_.contains(accelerator.key_code()));
-#if defined(OS_WIN) || defined(OS_MACOSX)
+#if defined(OS_MACOSX)
// For privacy, we don't want to handle media keys when the system is locked.
// On Windows and Mac OS X, this will happen unless we explicitly prevent it.
// TODO(steimel): Consider adding an idle monitor instead and disabling the
@@ -155,6 +155,16 @@ void MediaKeysListenerManagerImpl::OnMediaKeysAccelerator(
delegate.OnMediaKeysAccelerator(accelerator);
}
+void MediaKeysListenerManagerImpl::SetIsMediaPlaying(bool is_playing) {
+ if (is_media_playing_ == is_playing)
+ return;
+
+ is_media_playing_ = is_playing;
+
+ if (media_keys_listener_)
+ media_keys_listener_->SetIsMediaPlaying(is_media_playing_);
+}
+
void MediaKeysListenerManagerImpl::EnsureAuxiliaryServices() {
if (auxiliary_services_started_)
return;
@@ -200,6 +210,8 @@ void MediaKeysListenerManagerImpl::EnsureMediaKeysListener() {
media_keys_listener_ = ui::MediaKeysListener::Create(
this, ui::MediaKeysListener::Scope::kGlobal);
DCHECK(media_keys_listener_);
+
+ media_keys_listener_->SetIsMediaPlaying(is_media_playing_);
}
MediaKeysListenerManagerImpl::ListeningData*
diff --git a/chromium/content/browser/media/media_keys_listener_manager_impl.h b/chromium/content/browser/media/media_keys_listener_manager_impl.h
index 77e60268c32..361d957db5d 100644
--- a/chromium/content/browser/media/media_keys_listener_manager_impl.h
+++ b/chromium/content/browser/media/media_keys_listener_manager_impl.h
@@ -60,6 +60,12 @@ class CONTENT_EXPORT MediaKeysListenerManagerImpl
// ui::MediaKeysListener::Delegate:
void OnMediaKeysAccelerator(const ui::Accelerator& accelerator) override;
+ // Informs the MediaKeysListener whether or not media is playing.
+ // TODO(https://crbug.com/974035): Once the MediaKeysListenerManager has been
+ // refactored to work with system media controls this should no longer be
+ // needed and should be deleted.
+ void SetIsMediaPlaying(bool is_playing);
+
HardwareKeyMediaController* hardware_key_media_controller_for_testing() {
return hardware_key_media_controller_.get();
}
@@ -118,6 +124,8 @@ class CONTENT_EXPORT MediaKeysListenerManagerImpl
// True if auxiliary services have already been started.
bool auxiliary_services_started_;
+ bool is_media_playing_ = false;
+
#if defined(OS_MACOSX)
std::unique_ptr<NowPlayingInfoCenterNotifier>
now_playing_info_center_notifier_;
diff --git a/chromium/content/browser/media/media_keys_listener_manager_impl_browsertest.cc b/chromium/content/browser/media/media_keys_listener_manager_impl_browsertest.cc
index 080921c50b5..2469df326f5 100644
--- a/chromium/content/browser/media/media_keys_listener_manager_impl_browsertest.cc
+++ b/chromium/content/browser/media/media_keys_listener_manager_impl_browsertest.cc
@@ -40,19 +40,25 @@ class MockMediaKeysListener : public ui::MediaKeysListener {
void StopWatchingMediaKey(ui::KeyboardCode key_code) override {
key_codes_.erase(key_code);
}
+ void SetIsMediaPlaying(bool is_playing) override {
+ is_media_playing_ = is_playing;
+ }
void SimulateAccelerator(ui::Accelerator accelerator) {
if (IsWatching(accelerator.key_code()))
delegate_->OnMediaKeysAccelerator(accelerator);
}
- bool IsWatching(ui::KeyboardCode key_code) {
+ bool IsWatching(ui::KeyboardCode key_code) const {
return key_codes_.contains(key_code);
}
+ bool is_media_playing() const { return is_media_playing_; }
+
private:
ui::MediaKeysListener::Delegate* delegate_;
base::flat_set<ui::KeyboardCode> key_codes_;
+ bool is_media_playing_ = false;
DISALLOW_COPY_AND_ASSIGN(MockMediaKeysListener);
};
@@ -158,6 +164,9 @@ IN_PROC_BROWSER_TEST_F(MediaKeysListenerManagerImplTest, PressPlayPauseKey) {
EXPECT_EQ(0, media_controller()->suspend_count());
EXPECT_EQ(0, media_controller()->resume_count());
+ // The MediaKeysListener should know that media is playing.
+ EXPECT_TRUE(media_keys_listener()->is_media_playing());
+
// Press the play/pause media key.
media_keys_listener()->SimulateAccelerator(
ui::Accelerator(ui::VKEY_MEDIA_PLAY_PAUSE, 0));
@@ -176,6 +185,9 @@ IN_PROC_BROWSER_TEST_F(MediaKeysListenerManagerImplTest, PressPlayPauseKey) {
SetSupportedMediaSessionActions({MediaSessionAction::kPlay});
}
+ // The MediaKeysListener should know that media is paused.
+ EXPECT_FALSE(media_keys_listener()->is_media_playing());
+
// Press play/pause.
media_keys_listener()->SimulateAccelerator(
ui::Accelerator(ui::VKEY_MEDIA_PLAY_PAUSE, 0));
diff --git a/chromium/content/browser/media/media_web_contents_observer.cc b/chromium/content/browser/media/media_web_contents_observer.cc
index b5dfc643016..5c029100eea 100644
--- a/chromium/content/browser/media/media_web_contents_observer.cc
+++ b/chromium/content/browser/media/media_web_contents_observer.cc
@@ -9,10 +9,8 @@
#include "build/build_config.h"
#include "content/browser/media/audible_metrics.h"
#include "content/browser/media/audio_stream_monitor.h"
-#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"
diff --git a/chromium/content/browser/media/session/audio_focus_delegate_android.cc b/chromium/content/browser/media/session/audio_focus_delegate_android.cc
index bb4e9cc7943..f835e2b8922 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate_android.cc
+++ b/chromium/content/browser/media/session/audio_focus_delegate_android.cc
@@ -7,6 +7,7 @@
#include "base/android/jni_android.h"
#include "content/browser/media/session/media_session_impl.h"
#include "jni/AudioFocusDelegate_jni.h"
+#include "media/base/media_switches.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"
using base::android::JavaParamRef;
@@ -61,7 +62,8 @@ AudioFocusDelegateAndroid::GetCurrentFocusType() const {
void AudioFocusDelegateAndroid::OnSuspend(JNIEnv*,
const JavaParamRef<jobject>&) {
- if (!media_session_->IsActive())
+ if (!media_session_->IsActive() ||
+ !base::FeatureList::IsEnabled(media::kAudioFocusLossSuspendMediaSession))
return;
media_session_->Suspend(MediaSession::SuspendType::kSystem);
diff --git a/chromium/content/browser/media/session/audio_focus_delegate_android.h b/chromium/content/browser/media/session/audio_focus_delegate_android.h
index f4a3b13c9aa..e8f44368704 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate_android.h
+++ b/chromium/content/browser/media/session/audio_focus_delegate_android.h
@@ -62,7 +62,6 @@ class AudioFocusDelegateAndroid : public AudioFocusDelegate {
// Weak pointer because |this| is owned by |media_session_|.
MediaSessionImpl* media_session_;
base::android::ScopedJavaGlobalRef<jobject> j_media_session_delegate_;
-
DISALLOW_COPY_AND_ASSIGN(AudioFocusDelegateAndroid);
};
diff --git a/chromium/content/browser/media/session/media_session_browsertest.cc b/chromium/content/browser/media/session/media_session_browsertest.cc
index add1dd5fcd3..4c8ff9ca53d 100644
--- a/chromium/content/browser/media/session/media_session_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_browsertest.cc
@@ -9,6 +9,7 @@
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/lock.h"
#include "base/test/scoped_feature_list.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
@@ -132,6 +133,7 @@ class MediaSessionBrowserTest : public ContentBrowserTest {
}
bool WasURLVisited(const GURL& url) {
+ base::AutoLock lock(visited_urls_lock_);
return base::ContainsKey(visited_urls_, url);
}
@@ -201,9 +203,15 @@ class MediaSessionBrowserTest : public ContentBrowserTest {
};
void OnServerRequest(const net::test_server::HttpRequest& request) {
+ // Note this method is called on the EmbeddedTestServer's background thread.
+ base::AutoLock lock(visited_urls_lock_);
visited_urls_.insert(request.GetURL());
}
+ // visited_urls_ is accessed both on the main thread and on the
+ // EmbeddedTestServer's background thread via OnServerRequest(), so it must be
+ // locked.
+ base::Lock visited_urls_lock_;
std::set<GURL> visited_urls_;
base::test::ScopedFeatureList disabled_feature_list_;
diff --git a/chromium/content/browser/media/session/media_session_impl.cc b/chromium/content/browser/media/session/media_session_impl.cc
index 7e21f846a42..6c6796564f8 100644
--- a/chromium/content/browser/media/session/media_session_impl.cc
+++ b/chromium/content/browser/media/session/media_session_impl.cc
@@ -14,6 +14,7 @@
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "components/url_formatter/elide_url.h"
+#include "content/app/strings/grit/content_strings.h"
#include "content/browser/media/session/audio_focus_delegate.h"
#include "content/browser/media/session/media_session_controller.h"
#include "content/browser/media/session/media_session_player_observer.h"
@@ -23,6 +24,7 @@
#include "content/public/browser/media_session.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_client.h"
#include "media/base/media_content_type.h"
#include "services/media_session/public/cpp/media_image_manager.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"
@@ -1156,9 +1158,15 @@ void MediaSessionImpl::RebuildAndNotifyMetadataChanged() {
if (metadata.title.empty())
metadata.title = SanitizeMediaTitle(web_contents()->GetTitle());
+ const ContentClient* content_client = content::GetContentClient();
+ const GURL& url = web_contents()->GetLastCommittedURL();
+
+ // If the url is a file then we should display a placeholder.
base::string16 formatted_origin =
- url_formatter::FormatOriginForSecurityDisplay(
- url::Origin::Create(web_contents()->GetLastCommittedURL()));
+ url.SchemeIsFile()
+ ? content_client->GetLocalizedString(IDS_MEDIA_SESSION_FILE_SOURCE)
+ : url_formatter::FormatOriginForSecurityDisplay(
+ url::Origin::Create(url));
if (metadata.artist.empty()) {
metadata.artist = formatted_origin;
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 27123201847..b7a7728240a 100644
--- a/chromium/content/browser/media/session/media_session_impl_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_impl_browsertest.cc
@@ -2423,3 +2423,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, Async_Unducking_Suspended) {
ResolveAudioFocusSuccess();
EXPECT_TRUE(IsDucking());
}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, MetadataWhenFileUrlScheme) {
+ NavigateToURL(shell(), GURL("file:///"));
+
+ media_session::test::MockMediaSessionMojoObserver observer(*media_session_);
+
+ media_session::MediaMetadata expected_metadata;
+ expected_metadata.title = shell()->web_contents()->GetTitle();
+ expected_metadata.artist = base::ASCIIToUTF16("Local File");
+ observer.WaitForExpectedMetadata(expected_metadata);
+}
diff --git a/chromium/content/browser/media/session/media_session_impl_unittest.cc b/chromium/content/browser/media/session/media_session_impl_unittest.cc
index a0ffe56a7a3..4b122ecef57 100644
--- a/chromium/content/browser/media/session/media_session_impl_unittest.cc
+++ b/chromium/content/browser/media/session/media_session_impl_unittest.cc
@@ -197,7 +197,6 @@ TEST_F(MediaSessionImplTest, SessionInfoState) {
{
MockMediaSessionMojoObserver observer(*GetMediaSession());
RequestAudioFocus(GetMediaSession(), AudioFocusType::kGain);
- FlushForTesting(GetMediaSession());
observer.WaitForState(MediaSessionInfo::SessionState::kActive);
EXPECT_TRUE(observer.session_info().Equals(
@@ -207,7 +206,6 @@ TEST_F(MediaSessionImplTest, SessionInfoState) {
{
MockMediaSessionMojoObserver observer(*GetMediaSession());
GetMediaSession()->StartDucking();
- FlushForTesting(GetMediaSession());
observer.WaitForState(MediaSessionInfo::SessionState::kDucking);
EXPECT_TRUE(observer.session_info().Equals(
@@ -217,7 +215,6 @@ TEST_F(MediaSessionImplTest, SessionInfoState) {
{
MockMediaSessionMojoObserver observer(*GetMediaSession());
GetMediaSession()->StopDucking();
- FlushForTesting(GetMediaSession());
observer.WaitForState(MediaSessionInfo::SessionState::kActive);
EXPECT_TRUE(observer.session_info().Equals(
@@ -227,7 +224,6 @@ TEST_F(MediaSessionImplTest, SessionInfoState) {
{
MockMediaSessionMojoObserver observer(*GetMediaSession());
GetMediaSession()->Suspend(MediaSession::SuspendType::kSystem);
- FlushForTesting(GetMediaSession());
observer.WaitForState(MediaSessionInfo::SessionState::kSuspended);
EXPECT_TRUE(observer.session_info().Equals(
@@ -237,7 +233,6 @@ TEST_F(MediaSessionImplTest, SessionInfoState) {
{
MockMediaSessionMojoObserver observer(*GetMediaSession());
GetMediaSession()->Resume(MediaSession::SuspendType::kSystem);
- FlushForTesting(GetMediaSession());
observer.WaitForState(MediaSessionInfo::SessionState::kActive);
EXPECT_TRUE(observer.session_info().Equals(
@@ -247,7 +242,6 @@ TEST_F(MediaSessionImplTest, SessionInfoState) {
{
MockMediaSessionMojoObserver observer(*GetMediaSession());
AbandonAudioFocus(GetMediaSession());
- FlushForTesting(GetMediaSession());
observer.WaitForState(MediaSessionInfo::SessionState::kInactive);
EXPECT_TRUE(observer.session_info().Equals(
diff --git a/chromium/content/browser/media/system_media_controls_notifier.cc b/chromium/content/browser/media/system_media_controls_notifier.cc
index 2d701e28bfc..c5fdb389961 100644
--- a/chromium/content/browser/media/system_media_controls_notifier.cc
+++ b/chromium/content/browser/media/system_media_controls_notifier.cc
@@ -7,15 +7,28 @@
#include <memory>
#include <utility>
+#include "base/bind.h"
+#include "base/time/time.h"
+#include "content/public/browser/content_browser_client.h"
#include "services/media_session/public/mojom/constants.mojom.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
+#include "ui/base/idle/idle.h"
#include "ui/base/win/system_media_controls/system_media_controls_service.h"
namespace content {
using ABI::Windows::Media::MediaPlaybackStatus;
+const int kMinImageSize = 71;
+const int kDesiredImageSize = 150;
+
+constexpr base::TimeDelta kScreenLockPollInterval =
+ base::TimeDelta::FromSeconds(1);
+constexpr int kHideSmtcDelaySeconds = 5;
+constexpr base::TimeDelta kHideSmtcDelay =
+ base::TimeDelta::FromSeconds(kHideSmtcDelaySeconds);
+
SystemMediaControlsNotifier::SystemMediaControlsNotifier(
service_manager::Connector* connector)
: connector_(connector) {}
@@ -23,6 +36,8 @@ SystemMediaControlsNotifier::SystemMediaControlsNotifier(
SystemMediaControlsNotifier::~SystemMediaControlsNotifier() = default;
void SystemMediaControlsNotifier::Initialize() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
// |service_| can be set in tests.
if (!service_)
service_ = system_media_controls::SystemMediaControlsService::GetInstance();
@@ -32,6 +47,11 @@ void SystemMediaControlsNotifier::Initialize() {
if (!service_)
return;
+ lock_polling_timer_.Start(
+ FROM_HERE, kScreenLockPollInterval,
+ base::BindRepeating(&SystemMediaControlsNotifier::CheckLockState,
+ base::Unretained(this)));
+
// |connector_| can be null in tests.
if (!connector_)
return;
@@ -46,20 +66,92 @@ void SystemMediaControlsNotifier::Initialize() {
// Observe the active media controller for changes to playback state and
// supported actions.
- media_session::mojom::MediaControllerObserverPtr media_controller_observer;
+ media_session::mojom::MediaControllerObserverPtr
+ media_controller_observer_ptr;
media_controller_observer_binding_.Bind(
- mojo::MakeRequest(&media_controller_observer));
- media_controller_ptr_->AddObserver(std::move(media_controller_observer));
+ mojo::MakeRequest(&media_controller_observer_ptr));
+ media_controller_ptr_->AddObserver(std::move(media_controller_observer_ptr));
+
+ // Observe the active media controller for changes to provided artwork.
+ media_session::mojom::MediaControllerImageObserverPtr image_observer_ptr;
+ media_controller_image_observer_binding_.Bind(
+ mojo::MakeRequest(&image_observer_ptr));
+ media_controller_ptr_->ObserveImages(
+ media_session::mojom::MediaSessionImageType::kArtwork, kMinImageSize,
+ kDesiredImageSize, std::move(image_observer_ptr));
+}
+
+void SystemMediaControlsNotifier::CheckLockState() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ bool new_state = ui::CheckIdleStateIsLocked();
+ if (screen_locked_ == new_state)
+ return;
+
+ screen_locked_ = new_state;
+ if (screen_locked_)
+ OnScreenLocked();
+ else
+ OnScreenUnlocked();
+}
+
+void SystemMediaControlsNotifier::OnScreenLocked() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(service_);
+
+ // If media is currently playing, don't hide the SMTC.
+ if (session_info_ptr_ &&
+ session_info_ptr_->playback_state ==
+ media_session::mojom::MediaPlaybackState::kPlaying) {
+ return;
+ }
+
+ // Otherwise, hide them.
+ service_->SetEnabled(false);
+}
+
+void SystemMediaControlsNotifier::OnScreenUnlocked() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(service_);
+
+ StopHideSmtcTimer();
+ service_->SetEnabled(true);
+}
+
+void SystemMediaControlsNotifier::StartHideSmtcTimer() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ hide_smtc_timer_.Start(
+ FROM_HERE, kHideSmtcDelay,
+ base::BindOnce(&SystemMediaControlsNotifier::HideSmtcTimerFired,
+ base::Unretained(this)));
+}
+
+void SystemMediaControlsNotifier::StopHideSmtcTimer() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ hide_smtc_timer_.Stop();
+}
+
+void SystemMediaControlsNotifier::HideSmtcTimerFired() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(service_);
+
+ service_->SetEnabled(false);
}
void SystemMediaControlsNotifier::MediaSessionInfoChanged(
- media_session::mojom::MediaSessionInfoPtr session_info) {
+ media_session::mojom::MediaSessionInfoPtr session_info_ptr) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(service_);
- session_info_ = std::move(session_info);
- if (session_info_) {
- if (session_info_->playback_state ==
+ bool is_playing = false;
+
+ session_info_ptr_ = std::move(session_info_ptr);
+ if (session_info_ptr_) {
+ if (session_info_ptr_->playback_state ==
media_session::mojom::MediaPlaybackState::kPlaying) {
+ is_playing = true;
service_->SetPlaybackStatus(
MediaPlaybackStatus::MediaPlaybackStatus_Playing);
} else {
@@ -69,6 +161,67 @@ void SystemMediaControlsNotifier::MediaSessionInfoChanged(
} else {
service_->SetPlaybackStatus(
MediaPlaybackStatus::MediaPlaybackStatus_Stopped);
+
+ // These steps reference the Media Session Standard
+ // https://wicg.github.io/mediasession/#metadata
+ // 5.3.1 If the active media session is null, unset the media metadata
+ // presented to the platform, and terminate these steps.
+ service_->ClearMetadata();
+ }
+
+ if (screen_locked_) {
+ if (is_playing)
+ StopHideSmtcTimer();
+ else if (!hide_smtc_timer_.IsRunning())
+ StartHideSmtcTimer();
+ }
+}
+
+void SystemMediaControlsNotifier::MediaSessionMetadataChanged(
+ const base::Optional<media_session::MediaMetadata>& metadata) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(service_);
+
+ if (metadata.has_value()) {
+ // 5.3.3 Update the media metadata presented to the platform to match the
+ // metadata for the active media session.
+ // If no title was provided, the title of the tab will be in the title
+ // property.
+ service_->SetTitle(metadata->title);
+
+ // If no artist was provided, then the source URL will be in the artist
+ // property.
+ service_->SetArtist(metadata->artist);
+ service_->UpdateDisplay();
+ } else {
+ // 5.3.2 If the metadata of the active media session is an empty metadata,
+ // unset the media metadata presented to the platform.
+ service_->ClearMetadata();
+ }
+}
+
+void SystemMediaControlsNotifier::MediaControllerImageChanged(
+ media_session::mojom::MediaSessionImageType type,
+ const SkBitmap& bitmap) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(service_);
+
+ if (!bitmap.empty()) {
+ // 5.3.4.4.3 If the image format is supported, use the image as the artwork
+ // for display in the platform UI. Otherwise the fetch image algorithm fails
+ // and terminates.
+ service_->SetThumbnail(bitmap);
+ } else {
+ // 5.3.4.2 If metadata's artwork is empty, terminate these steps.
+ // If no images are fetched in the fetch image algorithm, the user agent
+ // may have fallback behavior such as displaying a default image as artwork.
+ // We display the application icon if no artwork is provided.
+ base::Optional<gfx::ImageSkia> icon =
+ GetContentClient()->browser()->GetProductLogo();
+ if (icon.has_value())
+ service_->SetThumbnail(*icon->bitmap());
+ else
+ service_->ClearThumbnail();
}
}
diff --git a/chromium/content/browser/media/system_media_controls_notifier.h b/chromium/content/browser/media/system_media_controls_notifier.h
index ed7bc8e66ee..23aaf87263d 100644
--- a/chromium/content/browser/media/system_media_controls_notifier.h
+++ b/chromium/content/browser/media/system_media_controls_notifier.h
@@ -8,6 +8,8 @@
#include <memory>
#include <vector>
+#include "base/sequence_checker.h"
+#include "base/timer/timer.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/media_session/public/mojom/media_controller.mojom.h"
@@ -27,7 +29,8 @@ namespace content {
// metadata. It observes changes to the active Media Session and updates the
// SMTC accordingly.
class CONTENT_EXPORT SystemMediaControlsNotifier
- : public media_session::mojom::MediaControllerObserver {
+ : public media_session::mojom::MediaControllerObserver,
+ public media_session::mojom::MediaControllerImageObserver {
public:
explicit SystemMediaControlsNotifier(service_manager::Connector* connector);
~SystemMediaControlsNotifier() override;
@@ -38,19 +41,45 @@ class CONTENT_EXPORT SystemMediaControlsNotifier
void MediaSessionInfoChanged(
media_session::mojom::MediaSessionInfoPtr session_info) override;
void MediaSessionMetadataChanged(
- const base::Optional<media_session::MediaMetadata>& metadata) override {}
+ const base::Optional<media_session::MediaMetadata>& metadata) override;
void MediaSessionActionsChanged(
const std::vector<media_session::mojom::MediaSessionAction>& actions)
override {}
void MediaSessionChanged(
const base::Optional<base::UnguessableToken>& request_id) override {}
+ // media_session::mojom::MediaControllerImageObserver implementation.
+ void MediaControllerImageChanged(
+ ::media_session::mojom::MediaSessionImageType type,
+ const SkBitmap& bitmap) override;
+
void SetSystemMediaControlsServiceForTesting(
system_media_controls::SystemMediaControlsService* service) {
service_ = service;
}
private:
+ friend class SystemMediaControlsNotifierTest;
+
+ // Polls the current idle state of the system.
+ void CheckLockState();
+
+ // Called when the idle state changes from unlocked to locked.
+ void OnScreenLocked();
+
+ // Called when the idle state changes from locked to unlocked.
+ void OnScreenUnlocked();
+
+ // Helper functions for dealing with the timer that hides the System Media
+ // Transport Controls on the lock screen 5 seconds after the user pauses.
+ void StartHideSmtcTimer();
+ void StopHideSmtcTimer();
+ void HideSmtcTimerFired();
+
+ bool screen_locked_ = false;
+ base::RepeatingTimer lock_polling_timer_;
+ base::OneShotTimer hide_smtc_timer_;
+
// Our connection to Window's System Media Transport Controls.
system_media_controls::SystemMediaControlsService* service_ = nullptr;
@@ -59,11 +88,15 @@ class CONTENT_EXPORT SystemMediaControlsNotifier
// Tracks current media session state/metadata.
media_session::mojom::MediaControllerPtr media_controller_ptr_;
- media_session::mojom::MediaSessionInfoPtr session_info_;
+ media_session::mojom::MediaSessionInfoPtr session_info_ptr_;
// Used to receive updates to the active media controller.
mojo::Binding<media_session::mojom::MediaControllerObserver>
media_controller_observer_binding_{this};
+ mojo::Binding<media_session::mojom::MediaControllerImageObserver>
+ media_controller_image_observer_binding_{this};
+
+ SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(SystemMediaControlsNotifier);
};
diff --git a/chromium/content/browser/media/system_media_controls_notifier_unittest.cc b/chromium/content/browser/media/system_media_controls_notifier_unittest.cc
index ab905528d21..b3e39184082 100644
--- a/chromium/content/browser/media/system_media_controls_notifier_unittest.cc
+++ b/chromium/content/browser/media/system_media_controls_notifier_unittest.cc
@@ -7,9 +7,11 @@
#include <memory>
#include <utility>
+#include "base/test/scoped_task_environment.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/idle/scoped_set_idle_state.h"
#include "ui/base/win/system_media_controls/mock_system_media_controls_service.h"
namespace content {
@@ -18,11 +20,14 @@ using ABI::Windows::Media::MediaPlaybackStatus;
using media_session::mojom::MediaPlaybackState;
using media_session::mojom::MediaSessionInfo;
using media_session::mojom::MediaSessionInfoPtr;
+using testing::_;
using testing::Expectation;
class SystemMediaControlsNotifierTest : public testing::Test {
public:
- SystemMediaControlsNotifierTest() = default;
+ SystemMediaControlsNotifierTest()
+ : scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
~SystemMediaControlsNotifierTest() override = default;
void SetUp() override {
@@ -48,13 +53,43 @@ class SystemMediaControlsNotifierTest : public testing::Test {
void SimulateStopped() { notifier_->MediaSessionInfoChanged(nullptr); }
+ void SimulateMetadataChanged(bool empty,
+ base::string16 title,
+ base::string16 artist) {
+ if (!empty) {
+ media_session::MediaMetadata metadata;
+ metadata.title = title;
+ metadata.artist = artist;
+ notifier_->MediaSessionMetadataChanged(
+ base::Optional<media_session::MediaMetadata>(metadata));
+ } else {
+ notifier_->MediaSessionMetadataChanged(base::nullopt);
+ }
+ }
+
+ void SimulateImageChanged() {
+ // Need a non-empty SkBitmap so MediaControllerImageChanged doesn't try to
+ // get the icon from ChromeContentBrowserClient.
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(1, 1);
+ notifier_->MediaControllerImageChanged(
+ media_session::mojom::MediaSessionImageType::kArtwork, bitmap);
+ }
+
SystemMediaControlsNotifier& notifier() { return *notifier_; }
system_media_controls::testing::MockSystemMediaControlsService&
mock_system_media_controls_service() {
return mock_system_media_controls_service_;
}
+ base::RepeatingTimer& lock_polling_timer() {
+ return notifier_->lock_polling_timer_;
+ }
+
+ base::OneShotTimer& hide_smtc_timer() { return notifier_->hide_smtc_timer_; }
+
private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<SystemMediaControlsNotifier> notifier_;
system_media_controls::testing::MockSystemMediaControlsService
mock_system_media_controls_service_;
@@ -71,14 +106,122 @@ TEST_F(SystemMediaControlsNotifierTest, ProperlyUpdatesPlaybackState) {
mock_system_media_controls_service(),
SetPlaybackStatus(MediaPlaybackStatus::MediaPlaybackStatus_Paused))
.After(playing);
- EXPECT_CALL(
+ Expectation stopped =
+ EXPECT_CALL(
+ mock_system_media_controls_service(),
+ SetPlaybackStatus(MediaPlaybackStatus::MediaPlaybackStatus_Stopped))
+ .After(paused);
+ EXPECT_CALL(mock_system_media_controls_service(), ClearMetadata())
+ .After(stopped);
+
+ SimulatePlaying();
+ SimulatePaused();
+ SimulateStopped();
+}
+
+TEST_F(SystemMediaControlsNotifierTest, ProperlyUpdatesMetadata) {
+ base::string16 title = L"title";
+ base::string16 artist = L"artist";
+
+ EXPECT_CALL(mock_system_media_controls_service(), SetTitle(title));
+ EXPECT_CALL(mock_system_media_controls_service(), SetArtist(artist));
+ EXPECT_CALL(mock_system_media_controls_service(), ClearMetadata()).Times(0);
+ EXPECT_CALL(mock_system_media_controls_service(), UpdateDisplay());
+
+ SimulateMetadataChanged(false, title, artist);
+}
+
+TEST_F(SystemMediaControlsNotifierTest, ProperlyUpdatesNullMetadata) {
+ EXPECT_CALL(mock_system_media_controls_service(), SetTitle(_)).Times(0);
+ EXPECT_CALL(mock_system_media_controls_service(), SetArtist(_)).Times(0);
+ EXPECT_CALL(mock_system_media_controls_service(), ClearMetadata());
+
+ SimulateMetadataChanged(true, L"", L"");
+}
+
+TEST_F(SystemMediaControlsNotifierTest, ProperlyUpdatesImage) {
+ EXPECT_CALL(mock_system_media_controls_service(), SetThumbnail(_));
+
+ SimulateImageChanged();
+}
+
+TEST_F(SystemMediaControlsNotifierTest, DisablesOnLockAndEnablesOnUnlock) {
+ EXPECT_CALL(mock_system_media_controls_service(), SetEnabled(false));
+
+ {
+ // Lock the screen.
+ ui::ScopedSetIdleState locked(ui::IDLE_STATE_LOCKED);
+
+ // Make sure that the lock polling timer is running and then force it to
+ // fire so that we don't need to wait. This should disable the service.
+ EXPECT_TRUE(lock_polling_timer().IsRunning());
+ lock_polling_timer().user_task().Run();
+ }
+
+ // Ensure that the service was disabled.
+ testing::Mock::VerifyAndClearExpectations(
+ &mock_system_media_controls_service());
+
+ // The service should be reenabled on unlock.
+ EXPECT_CALL(mock_system_media_controls_service(), SetEnabled(true));
+
+ {
+ // Unlock the screen.
+ ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_ACTIVE);
+
+ // Make sure that the lock polling timer is running and then force it to
+ // fire so that we don't need to wait. This should enable the service.
+ EXPECT_TRUE(lock_polling_timer().IsRunning());
+ lock_polling_timer().user_task().Run();
+ }
+}
+
+TEST_F(SystemMediaControlsNotifierTest, DoesNotDisableOnLockWhenPlaying) {
+ EXPECT_CALL(mock_system_media_controls_service(), SetEnabled(_)).Times(0);
+
+ SimulatePlaying();
+
+ // Lock the screen.
+ ui::ScopedSetIdleState locked(ui::IDLE_STATE_LOCKED);
+
+ // Make sure that the lock polling timer is running and then force it to
+ // fire so that we don't need to wait. This should not disable the service.
+ EXPECT_TRUE(lock_polling_timer().IsRunning());
+ lock_polling_timer().user_task().Run();
+}
+
+TEST_F(SystemMediaControlsNotifierTest, DisablesAfterPausingOnLockScreen) {
+ Expectation playing = EXPECT_CALL(
mock_system_media_controls_service(),
- SetPlaybackStatus(MediaPlaybackStatus::MediaPlaybackStatus_Stopped))
+ SetPlaybackStatus(MediaPlaybackStatus::MediaPlaybackStatus_Playing));
+ Expectation paused =
+ EXPECT_CALL(
+ mock_system_media_controls_service(),
+ SetPlaybackStatus(MediaPlaybackStatus::MediaPlaybackStatus_Paused))
+ .After(playing);
+ EXPECT_CALL(mock_system_media_controls_service(), SetEnabled(false))
.After(paused);
SimulatePlaying();
+
+ // Lock the screen.
+ ui::ScopedSetIdleState locked(ui::IDLE_STATE_LOCKED);
+
+ // Make sure that the lock polling timer is running and then force it to
+ // fire so that we don't need to wait. This should not disable the service.
+ EXPECT_TRUE(lock_polling_timer().IsRunning());
+ lock_polling_timer().user_task().Run();
+
+ // Since we're playing, the timer to hide the SMTC should not be running.
+ EXPECT_FALSE(hide_smtc_timer().IsRunning());
+
SimulatePaused();
- SimulateStopped();
+
+ // Now that we're paused, the timer to hide the SMTC should be running.
+ EXPECT_TRUE(hide_smtc_timer().IsRunning());
+
+ // Force the timer to fire now. This should disable the service.
+ hide_smtc_timer().FireNow();
}
} // namespace content
diff --git a/chromium/content/browser/media/url_provision_fetcher.cc b/chromium/content/browser/media/url_provision_fetcher.cc
index ae55d7c6ff5..e72f880f4f0 100644
--- a/chromium/content/browser/media/url_provision_fetcher.cc
+++ b/chromium/content/browser/media/url_provision_fetcher.cc
@@ -5,9 +5,12 @@
#include "content/browser/media/url_provision_fetcher.h"
#include "base/bind.h"
+#include "base/metrics/histogram_functions.h"
#include "content/public/browser/provision_fetcher_factory.h"
#include "media/base/bind_to_current_loop.h"
+#include "media/base/media_switches.h"
#include "net/base/load_flags.h"
+#include "net/http/http_util.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -29,6 +32,13 @@ void URLProvisionFetcher::Retrieve(
const std::string& default_url,
const std::string& request_data,
const media::ProvisionFetcher::ResponseCB& response_cb) {
+ // For testing, don't actually do provisioning if the feature is enabled,
+ // just indicate that the request failed.
+ if (base::FeatureList::IsEnabled(media::kFailUrlProvisionFetcherForTesting)) {
+ response_cb.Run(false, std::string());
+ return;
+ }
+
response_cb_ = response_cb;
const std::string request_string =
@@ -83,21 +93,28 @@ void URLProvisionFetcher::Retrieve(
void URLProvisionFetcher::OnSimpleLoaderComplete(
std::unique_ptr<std::string> response_body) {
bool success = false;
+ int response_code = simple_url_loader_->NetError();
std::string response;
+ const auto& headers = simple_url_loader_->ResponseInfo()
+ ? simple_url_loader_->ResponseInfo()->headers
+ : nullptr;
+ if (headers) {
+ // If there is a valid header, use the HTTP response code instead of the
+ // net::Error status.
+ response_code =
+ net::HttpUtil::MapStatusCodeForHistogram(headers->response_code());
+ }
+
if (response_body) {
success = true;
response = std::move(*response_body);
} else {
- int response_code = -1;
- if (simple_url_loader_->ResponseInfo() &&
- simple_url_loader_->ResponseInfo()->headers) {
- response_code =
- simple_url_loader_->ResponseInfo()->headers->response_code();
- }
DVLOG(1) << "CDM provision: server returned error code " << response_code;
}
simple_url_loader_.reset();
+ base::UmaHistogramSparse("Media.EME.UrlProvisionFetcher.ResponseCode",
+ response_code);
response_cb_.Run(success, response);
}
diff --git a/chromium/content/browser/media/video_decoder_proxy.cc b/chromium/content/browser/media/video_decoder_proxy.cc
index 437b5632089..ef825a5392c 100644
--- a/chromium/content/browser/media/video_decoder_proxy.cc
+++ b/chromium/content/browser/media/video_decoder_proxy.cc
@@ -55,6 +55,7 @@ void VideoDecoderProxy::CreateCastRenderer(
#if defined(OS_ANDROID)
void VideoDecoderProxy::CreateFlingingRenderer(
const std::string& audio_device_id,
+ media::mojom::FlingingRendererClientExtensionPtr client_extenion,
media::mojom::RendererRequest request) {}
void VideoDecoderProxy::CreateMediaPlayerRenderer(
diff --git a/chromium/content/browser/media/video_decoder_proxy.h b/chromium/content/browser/media/video_decoder_proxy.h
index 6ea82334262..aaf0330cc22 100644
--- a/chromium/content/browser/media/video_decoder_proxy.h
+++ b/chromium/content/browser/media/video_decoder_proxy.h
@@ -43,8 +43,10 @@ class VideoDecoderProxy : public media::mojom::InterfaceFactory {
media::mojom::RendererRequest request,
media::mojom::MediaPlayerRendererExtensionRequest
renderer_extension_request) final;
- void CreateFlingingRenderer(const std::string& presentation_id,
- media::mojom::RendererRequest request) final;
+ void CreateFlingingRenderer(
+ const std::string& presentation_id,
+ media::mojom::FlingingRendererClientExtensionPtr client_extension,
+ media::mojom::RendererRequest request) final;
#endif // defined(OS_ANDROID)
void CreateCdm(const std::string& key_system,
media::mojom::ContentDecryptionModuleRequest request) final;
diff --git a/chromium/content/browser/native_file_system/OWNERS b/chromium/content/browser/native_file_system/OWNERS
new file mode 100644
index 00000000000..a7940d04a71
--- /dev/null
+++ b/chromium/content/browser/native_file_system/OWNERS
@@ -0,0 +1,5 @@
+mek@chromium.org
+pwnall@chromium.org
+
+# TEAM: storage-dev@chromium.org
+# COMPONENT: Blink>Storage>FileSystem
diff --git a/chromium/content/browser/native_file_system/README.md b/chromium/content/browser/native_file_system/README.md
new file mode 100644
index 00000000000..fef0319bcbd
--- /dev/null
+++ b/chromium/content/browser/native_file_system/README.md
@@ -0,0 +1,15 @@
+# Native File System API
+
+This directory contains part of the browser side implementation of the
+native file system API.
+
+See https://wicg.github.io/native-file-system/ for the spec for this API.
+
+## Related directories
+
+[`//storage/browser/fileapi/`](../../../storage/browser/fileapi) contains the
+backend this API is built on top of,
+[`blink/renderer/modules/native_file_system`](../../../third_party/blink/renderer/modules/native_file_system)
+contains the renderer side implementation and
+[`blink/public/mojom/native_file_system`](../../../third_party/blink/public/mojom/native_file_system)
+contains the mojom interfaces for these APIs.
diff --git a/chromium/content/browser/fileapi/file_system_chooser.cc b/chromium/content/browser/native_file_system/file_system_chooser.cc
index e36025673d1..2c9ca2eccb1 100644
--- a/chromium/content/browser/fileapi/file_system_chooser.cc
+++ b/chromium/content/browser/native_file_system/file_system_chooser.cc
@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/fileapi/file_system_chooser.h"
+#include "content/browser/native_file_system/file_system_chooser.h"
#include "base/bind.h"
+#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
@@ -53,7 +54,8 @@ bool GetFileTypesFromAcceptsOption(
}
void ConvertAcceptsToFileTypeInfo(
- const std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr>& accepts,
+ const std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr>&
+ accepts,
bool include_accepts_all,
ui::SelectFileDialog::FileTypeInfo* file_types) {
file_types->include_all_files = include_accepts_all;
@@ -90,8 +92,8 @@ void FileSystemChooser::CreateAndShow(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHost* rfh = RenderFrameHost::FromID(render_process_id, frame_id);
WebContents* web_contents = WebContents::FromRenderFrameHost(rfh);
- auto* listener = new FileSystemChooser(
- render_process_id, type, std::move(callback), std::move(callback_runner));
+ auto* listener = new FileSystemChooser(type, std::move(callback),
+ std::move(callback_runner));
listener->dialog_ = ui::SelectFileDialog::Create(
listener,
GetContentClient()->browser()->CreateSelectFilePolicy(web_contents));
@@ -128,12 +130,10 @@ void FileSystemChooser::CreateAndShow(
}
FileSystemChooser::FileSystemChooser(
- int render_process_id,
blink::mojom::ChooseFileSystemEntryType type,
ResultCallback callback,
scoped_refptr<base::TaskRunner> callback_runner)
- : render_process_id_(render_process_id),
- callback_(std::move(callback)),
+ : callback_(std::move(callback)),
callback_runner_(std::move(callback_runner)),
type_(type) {}
@@ -154,37 +154,6 @@ void FileSystemChooser::MultiFilesSelected(
auto* isolated_context = storage::IsolatedContext::GetInstance();
DCHECK(isolated_context);
- auto* security_policy = ChildProcessSecurityPolicy::GetInstance();
- DCHECK(security_policy);
-
- std::vector<blink::mojom::FileSystemEntryPtr> result;
- result.reserve(files.size());
- for (const auto& path : files) {
- auto entry = blink::mojom::FileSystemEntry::New();
- entry->file_system_id = isolated_context->RegisterFileSystemForPath(
- storage::kFileSystemTypeNativeLocal, std::string(), path,
- &entry->base_name);
-
- security_policy->GrantReadFileSystem(render_process_id_,
- entry->file_system_id);
- // TODO(https://crbug.com/878585): Don't grant write/modify permissions
- // unless a website already has the appropriate permissions.
- if (type_ == blink::mojom::ChooseFileSystemEntryType::kOpenDirectory) {
- // Only grant Create permissions if we're opening a directory. And
- // just granting Create permissions on top of Write and Delete does not
- // actually grant the same permissions as calling this method.
- security_policy->GrantCreateReadWriteFileSystem(render_process_id_,
- entry->file_system_id);
- } else {
- security_policy->GrantWriteFileSystem(render_process_id_,
- entry->file_system_id);
- security_policy->GrantDeleteFromFileSystem(render_process_id_,
- entry->file_system_id);
- }
-
- result.push_back(std::move(entry));
- }
-
if (type_ == blink::mojom::ChooseFileSystemEntryType::kSaveFile) {
// Create files if they don't yet exist.
// TODO(mek): If we change FileSystemFileHandle to be able to represent a
@@ -194,7 +163,6 @@ void FileSystemChooser::MultiFilesSelected(
FROM_HERE, {base::TaskPriority::USER_BLOCKING, base::MayBlock()},
base::BindOnce(
[](const std::vector<base::FilePath>& files,
- std::vector<blink::mojom::FileSystemEntryPtr> result,
scoped_refptr<base::TaskRunner> callback_runner,
ResultCallback callback) {
for (const auto& path : files) {
@@ -213,32 +181,38 @@ void FileSystemChooser::MultiFilesSelected(
if (!file.IsValid()) {
callback_runner->PostTask(
FROM_HERE,
- base::BindOnce(
- std::move(callback), base::File::FILE_ERROR_FAILED,
- std::vector<blink::mojom::FileSystemEntryPtr>()));
+ base::BindOnce(std::move(callback),
+ blink::mojom::NativeFileSystemError::New(
+ base::File::FILE_ERROR_FAILED),
+ std::vector<base::FilePath>()));
return;
}
}
callback_runner->PostTask(
FROM_HERE,
- base::BindOnce(std::move(callback), base::File::FILE_OK,
- std::move(result)));
+ base::BindOnce(std::move(callback),
+ blink::mojom::NativeFileSystemError::New(
+ base::File::FILE_OK),
+ std::move(files)));
},
- files, std::move(result), callback_runner_, std::move(callback_)));
+ files, callback_runner_, std::move(callback_)));
delete this;
return;
}
callback_runner_->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback_), base::File::FILE_OK,
- std::move(result)));
+ FROM_HERE, base::BindOnce(std::move(callback_),
+ blink::mojom::NativeFileSystemError::New(
+ base::File::FILE_OK),
+ std::move(files)));
delete this;
}
void FileSystemChooser::FileSelectionCanceled(void* params) {
callback_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(callback_), base::File::FILE_ERROR_ABORT,
- std::vector<blink::mojom::FileSystemEntryPtr>()));
+ FROM_HERE, base::BindOnce(std::move(callback_),
+ blink::mojom::NativeFileSystemError::New(
+ base::File::FILE_ERROR_ABORT),
+ std::vector<base::FilePath>()));
delete this;
}
diff --git a/chromium/content/browser/fileapi/file_system_chooser.h b/chromium/content/browser/native_file_system/file_system_chooser.h
index 56a2498bccc..0017005b563 100644
--- a/chromium/content/browser/fileapi/file_system_chooser.h
+++ b/chromium/content/browser/native_file_system/file_system_chooser.h
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_CHOOSER_H_
-#define CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_CHOOSER_H_
+#ifndef CONTENT_BROWSER_NATIVE_FILE_SYSTEM_FILE_SYSTEM_CHOOSER_H_
+#define CONTENT_BROWSER_NATIVE_FILE_SYSTEM_FILE_SYSTEM_CHOOSER_H_
#include "base/files/file.h"
+#include "base/files/file_path.h"
#include "base/task_runner.h"
#include "content/common/content_export.h"
-#include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom.h"
#include "ui/shell_dialogs/select_file_dialog.h"
namespace content {
@@ -21,8 +23,8 @@ namespace content {
class CONTENT_EXPORT FileSystemChooser : public ui::SelectFileDialog::Listener {
public:
using ResultCallback =
- base::OnceCallback<void(base::File::Error,
- std::vector<blink::mojom::FileSystemEntryPtr>)>;
+ base::OnceCallback<void(blink::mojom::NativeFileSystemErrorPtr,
+ std::vector<base::FilePath>)>;
static void CreateAndShow(
int render_process_id,
@@ -33,8 +35,7 @@ class CONTENT_EXPORT FileSystemChooser : public ui::SelectFileDialog::Listener {
ResultCallback callback,
scoped_refptr<base::TaskRunner> callback_runner);
- FileSystemChooser(int render_process_id,
- blink::mojom::ChooseFileSystemEntryType type,
+ FileSystemChooser(blink::mojom::ChooseFileSystemEntryType type,
ResultCallback callback,
scoped_refptr<base::TaskRunner> callback_runner);
@@ -49,7 +50,6 @@ class CONTENT_EXPORT FileSystemChooser : public ui::SelectFileDialog::Listener {
void* params) override;
void FileSelectionCanceled(void* params) override;
- int render_process_id_;
ResultCallback callback_;
scoped_refptr<base::TaskRunner> callback_runner_;
blink::mojom::ChooseFileSystemEntryType type_;
@@ -59,4 +59,4 @@ class CONTENT_EXPORT FileSystemChooser : public ui::SelectFileDialog::Listener {
} // namespace content
-#endif // CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_CHOOSER_H_
+#endif // CONTENT_BROWSER_NATIVE_FILE_SYSTEM_FILE_SYSTEM_CHOOSER_H_
diff --git a/chromium/content/browser/fileapi/file_system_chooser_browsertest.cc b/chromium/content/browser/native_file_system/file_system_chooser_browsertest.cc
index 131c076adad..08b3797c91e 100644
--- a/chromium/content/browser/fileapi/file_system_chooser_browsertest.cc
+++ b/chromium/content/browser/native_file_system/file_system_chooser_browsertest.cc
@@ -2,14 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
-#include "content/browser/fileapi/file_system_chooser_test_helpers.h"
+#include "content/browser/native_file_system/file_system_chooser_test_helpers.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 "net/test/embedded_test_server/embedded_test_server.h"
#include "third_party/blink/public/common/features.h"
#include "ui/shell_dialogs/select_file_dialog.h"
@@ -25,7 +27,7 @@ class FileSystemChooserBrowserTest : public ContentBrowserTest {
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
scoped_feature_list_.InitAndEnableFeature(
- blink::features::kNativeFilesystemAPI);
+ blink::features::kNativeFileSystemAPI);
ASSERT_TRUE(embedded_test_server()->Start());
@@ -84,6 +86,8 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenFile) {
" self.selected_entry = e;"
" return e.name; })()"));
EXPECT_EQ(ui::SelectFileDialog::SELECT_OPEN_FILE, dialog_params.type);
+ EXPECT_EQ(shell()->web_contents()->GetTopLevelNativeWindow(),
+ dialog_params.owning_window);
EXPECT_EQ(
file_contents,
EvalJs(shell(),
diff --git a/chromium/content/browser/fileapi/file_system_chooser_test_helpers.cc b/chromium/content/browser/native_file_system/file_system_chooser_test_helpers.cc
index 958f652817c..317f0d0997d 100644
--- a/chromium/content/browser/fileapi/file_system_chooser_test_helpers.cc
+++ b/chromium/content/browser/native_file_system/file_system_chooser_test_helpers.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 "file_system_chooser_test_helpers.h"
+#include "content/browser/native_file_system/file_system_chooser_test_helpers.h"
namespace content {
@@ -31,6 +31,7 @@ class CancellingSelectFileDialog : public ui::SelectFileDialog {
out_params_->file_types = *file_types;
else
out_params_->file_types = base::nullopt;
+ out_params_->owning_window = owning_window;
}
listener_->FileSelectionCanceled(params);
}
@@ -71,6 +72,7 @@ class FakeSelectFileDialog : public ui::SelectFileDialog {
out_params_->file_types = *file_types;
else
out_params_->file_types = base::nullopt;
+ out_params_->owning_window = owning_window;
}
if (result_.size() == 1)
listener_->FileSelected(result_[0], 0, params);
diff --git a/chromium/content/browser/fileapi/file_system_chooser_test_helpers.h b/chromium/content/browser/native_file_system/file_system_chooser_test_helpers.h
index a26fc2d71b7..1fc6f1f36a7 100644
--- a/chromium/content/browser/fileapi/file_system_chooser_test_helpers.h
+++ b/chromium/content/browser/native_file_system/file_system_chooser_test_helpers.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_FILEAPI_FILE_SYSTEM_CHOOSER_TEST_HELPERS_H_
-#define CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_CHOOSER_TEST_HELPERS_H_
+#ifndef CONTENT_BROWSER_NATIVE_FILE_SYSTEM_FILE_SYSTEM_CHOOSER_TEST_HELPERS_H_
+#define CONTENT_BROWSER_NATIVE_FILE_SYSTEM_FILE_SYSTEM_CHOOSER_TEST_HELPERS_H_
#include "base/optional.h"
+#include "ui/gfx/native_widget_types.h"
#include "ui/shell_dialogs/select_file_dialog.h"
#include "ui/shell_dialogs/select_file_dialog_factory.h"
#include "ui/shell_dialogs/select_file_policy.h"
@@ -20,6 +21,7 @@ struct SelectFileDialogParams {
ui::SelectFileDialog::Type type = ui::SelectFileDialog::SELECT_NONE;
base::Optional<ui::SelectFileDialog::FileTypeInfo> file_types;
+ gfx::NativeWindow owning_window = {};
};
// A fake ui::SelectFileDialog, which will cancel the file selection instead of
@@ -57,4 +59,4 @@ class FakeSelectFileDialogFactory : public ui::SelectFileDialogFactory {
} // namespace content
-#endif // CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_CHOOSER_TEST_HELPERS_H_ \ No newline at end of file
+#endif // CONTENT_BROWSER_NATIVE_FILE_SYSTEM_FILE_SYSTEM_CHOOSER_TEST_HELPERS_H_ \ No newline at end of file
diff --git a/chromium/content/browser/fileapi/file_system_chooser_unittest.cc b/chromium/content/browser/native_file_system/file_system_chooser_unittest.cc
index b95cb53404b..0c30b8e3b3f 100644
--- a/chromium/content/browser/fileapi/file_system_chooser_unittest.cc
+++ b/chromium/content/browser/native_file_system/file_system_chooser_unittest.cc
@@ -2,14 +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/fileapi/file_system_chooser.h"
+#include "content/browser/native_file_system/file_system_chooser.h"
+#include "base/files/file_path.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
-#include "content/browser/fileapi/file_system_chooser_test_helpers.h"
+#include "content/browser/native_file_system/file_system_chooser_test_helpers.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/shell_dialogs/select_file_dialog.h"
@@ -30,10 +31,8 @@ class FileSystemChooserTest : public testing::Test {
0, 0, blink::mojom::ChooseFileSystemEntryType::kOpenFile,
std::move(accepts), include_accepts_all,
base::BindLambdaForTesting(
- [&](base::File::Error,
- std::vector<blink::mojom::FileSystemEntryPtr>) {
- loop.Quit();
- }),
+ [&](blink::mojom::NativeFileSystemErrorPtr,
+ std::vector<base::FilePath>) { loop.Quit(); }),
base::SequencedTaskRunnerHandle::Get());
loop.Run();
}
diff --git a/chromium/content/browser/native_file_system/native_file_system_directory_handle_impl.cc b/chromium/content/browser/native_file_system/native_file_system_directory_handle_impl.cc
new file mode 100644
index 00000000000..bc77b0ec587
--- /dev/null
+++ b/chromium/content/browser/native_file_system/native_file_system_directory_handle_impl.cc
@@ -0,0 +1,300 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/native_file_system/native_file_system_directory_handle_impl.h"
+
+#include "base/strings/strcat.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "content/browser/native_file_system/native_file_system_transfer_token_impl.h"
+#include "net/base/escape.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/common/fileapi/file_system_util.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_file_handle.mojom.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_transfer_token.mojom.h"
+
+using blink::mojom::NativeFileSystemEntry;
+using blink::mojom::NativeFileSystemEntryPtr;
+using blink::mojom::NativeFileSystemError;
+using blink::mojom::NativeFileSystemHandle;
+using blink::mojom::NativeFileSystemTransferTokenPtr;
+using blink::mojom::NativeFileSystemTransferTokenRequest;
+
+namespace content {
+
+struct NativeFileSystemDirectoryHandleImpl::ReadDirectoryState {
+ GetEntriesCallback callback;
+ std::vector<NativeFileSystemEntryPtr> entries;
+};
+
+NativeFileSystemDirectoryHandleImpl::NativeFileSystemDirectoryHandleImpl(
+ NativeFileSystemManagerImpl* manager,
+ const BindingContext& context,
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system)
+ : NativeFileSystemHandleBase(manager,
+ context,
+ url,
+ std::move(file_system)) {}
+
+NativeFileSystemDirectoryHandleImpl::~NativeFileSystemDirectoryHandleImpl() =
+ default;
+
+void NativeFileSystemDirectoryHandleImpl::GetFile(const std::string& name,
+ bool create,
+ GetFileCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ storage::FileSystemURL child_url = GetChildURL(name);
+ if (create) {
+ operation_runner()->CreateFile(
+ child_url, /*exclusive=*/false,
+ base::BindOnce(&NativeFileSystemDirectoryHandleImpl::DidGetFile,
+ weak_factory_.GetWeakPtr(), child_url,
+ std::move(callback)));
+ } else {
+ operation_runner()->FileExists(
+ child_url,
+ base::BindOnce(&NativeFileSystemDirectoryHandleImpl::DidGetFile,
+ weak_factory_.GetWeakPtr(), child_url,
+ std::move(callback)));
+ }
+}
+
+void NativeFileSystemDirectoryHandleImpl::GetDirectory(
+ const std::string& name,
+ bool create,
+ GetDirectoryCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ storage::FileSystemURL child_url = GetChildURL(name);
+ if (create) {
+ operation_runner()->CreateDirectory(
+ child_url, /*exclusive=*/false, /*recursive=*/false,
+ base::BindOnce(&NativeFileSystemDirectoryHandleImpl::DidGetDirectory,
+ weak_factory_.GetWeakPtr(), child_url,
+ std::move(callback)));
+ } else {
+ operation_runner()->DirectoryExists(
+ child_url,
+ base::BindOnce(&NativeFileSystemDirectoryHandleImpl::DidGetDirectory,
+ weak_factory_.GetWeakPtr(), child_url,
+ std::move(callback)));
+ }
+}
+
+void NativeFileSystemDirectoryHandleImpl::GetEntries(
+ GetEntriesCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ operation_runner()->ReadDirectory(
+ url(), base::BindRepeating(
+ &NativeFileSystemDirectoryHandleImpl::DidReadDirectory,
+ weak_factory_.GetWeakPtr(),
+ base::Owned(new ReadDirectoryState{std::move(callback)})));
+}
+
+void NativeFileSystemDirectoryHandleImpl::MoveFrom(
+ NativeFileSystemTransferTokenPtr source,
+ const std::string& name,
+ MoveFromCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ manager()->ResolveTransferToken(
+ std::move(source),
+ base::BindOnce(&NativeFileSystemDirectoryHandleImpl::DoCopyOrMoveFrom,
+ weak_factory_.GetWeakPtr(), name, /*is_copy=*/false,
+ std::move(callback)));
+}
+
+void NativeFileSystemDirectoryHandleImpl::CopyFrom(
+ NativeFileSystemTransferTokenPtr source,
+ const std::string& name,
+ CopyFromCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ manager()->ResolveTransferToken(
+ std::move(source),
+ base::BindOnce(&NativeFileSystemDirectoryHandleImpl::DoCopyOrMoveFrom,
+ weak_factory_.GetWeakPtr(), name, /*is_copy=*/true,
+ std::move(callback)));
+}
+
+void NativeFileSystemDirectoryHandleImpl::Remove(bool recurse,
+ RemoveCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ operation_runner()->Remove(
+ url(), recurse,
+ base::BindOnce(
+ [](RemoveCallback callback, base::File::Error result) {
+ std::move(callback).Run(NativeFileSystemError::New(result));
+ },
+ std::move(callback)));
+}
+
+void NativeFileSystemDirectoryHandleImpl::Transfer(
+ NativeFileSystemTransferTokenRequest token) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ manager()->CreateTransferToken(*this, std::move(token));
+}
+
+void NativeFileSystemDirectoryHandleImpl::DidGetFile(storage::FileSystemURL url,
+ GetFileCallback callback,
+ base::File::Error result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (result != base::File::FILE_OK) {
+ std::move(callback).Run(NativeFileSystemError::New(result), nullptr);
+ return;
+ }
+
+ std::move(callback).Run(
+ NativeFileSystemError::New(base::File::FILE_OK),
+ manager()->CreateFileHandle(context(), url, file_system()));
+}
+
+void NativeFileSystemDirectoryHandleImpl::DidGetDirectory(
+ storage::FileSystemURL url,
+ GetDirectoryCallback callback,
+ base::File::Error result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (result != base::File::FILE_OK) {
+ std::move(callback).Run(NativeFileSystemError::New(result), nullptr);
+ return;
+ }
+
+ std::move(callback).Run(
+ NativeFileSystemError::New(base::File::FILE_OK),
+ manager()->CreateDirectoryHandle(context(), url, file_system()));
+}
+
+void NativeFileSystemDirectoryHandleImpl::DidReadDirectory(
+ ReadDirectoryState* state,
+ base::File::Error result,
+ std::vector<filesystem::mojom::DirectoryEntry> file_list,
+ bool has_more) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (result != base::File::FILE_OK) {
+ DCHECK(!has_more);
+ std::move(state->callback).Run(NativeFileSystemError::New(result), {});
+ return;
+ }
+
+ for (const auto& entry : file_list) {
+ std::string name = storage::FilePathToString(entry.name);
+ state->entries.push_back(
+ CreateEntry(name, GetChildURL(name),
+ entry.type == filesystem::mojom::FsFileType::DIRECTORY));
+ }
+
+ // TODO(mek): Change API so we can stream back entries as they come in, rather
+ // than waiting till we have retrieved them all.
+ if (!has_more) {
+ std::move(state->callback)
+ .Run(NativeFileSystemError::New(base::File::FILE_OK),
+ std::move(state->entries));
+ }
+}
+
+void NativeFileSystemDirectoryHandleImpl::DoCopyOrMoveFrom(
+ const std::string& new_name,
+ bool is_copy,
+ CopyOrMoveCallback callback,
+ NativeFileSystemTransferTokenImpl* source) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!source) {
+ std::move(callback).Run(
+ NativeFileSystemError::New(base::File::FILE_ERROR_NOT_FOUND), nullptr);
+ return;
+ }
+
+ storage::FileSystemURL url = GetChildURL(new_name);
+ if (url == source->url()) {
+ std::move(callback).Run(
+ NativeFileSystemError::New(base::File::FILE_ERROR_INVALID_OPERATION),
+ nullptr);
+ return;
+ }
+
+ auto result_callback = base::BindOnce(
+ &NativeFileSystemDirectoryHandleImpl::DidCopyOrMove,
+ weak_factory_.GetWeakPtr(), std::move(callback), new_name, url,
+ source->type() ==
+ NativeFileSystemTransferTokenImpl::HandleType::kDirectory);
+ if (is_copy) {
+ operation_runner()->Copy(
+ source->url(), url, storage::FileSystemOperation::OPTION_NONE,
+ storage::FileSystemOperation::ERROR_BEHAVIOR_ABORT,
+ /*progress_callback=*/base::NullCallback(), std::move(result_callback));
+ } else {
+ operation_runner()->Move(source->url(), url,
+ storage::FileSystemOperation::OPTION_NONE,
+ std::move(result_callback));
+ }
+}
+
+void NativeFileSystemDirectoryHandleImpl::DidCopyOrMove(
+ CopyOrMoveCallback callback,
+ const std::string& new_name,
+ const storage::FileSystemURL& new_url,
+ bool is_directory,
+ base::File::Error result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (result != base::File::FILE_OK) {
+ std::move(callback).Run(NativeFileSystemError::New(result), nullptr);
+ return;
+ }
+
+ std::move(callback).Run(NativeFileSystemError::New(base::File::FILE_OK),
+ CreateEntry(new_name, new_url, is_directory));
+}
+
+storage::FileSystemURL NativeFileSystemDirectoryHandleImpl::GetChildURL(
+ const std::string& name) {
+ // TODO(mek): Rather than doing URL serialization and parsing we should just
+ // have a way to get a child FileSystemURL directly from its parent.
+ // TODO(https://crbug.com/960411): Also we need a way for GetChildURL to fail,
+ // to indicate invalid input, for example containing ".." or "/".
+
+ std::string escaped_name =
+ net::EscapeQueryParamValue(name, /*use_plus=*/false);
+
+ GURL parent_url = url().ToGURL();
+ std::string path = base::StrCat({parent_url.path(), "/", escaped_name});
+ GURL::Replacements replacements;
+ replacements.SetPathStr(path);
+ GURL child_url = parent_url.ReplaceComponents(replacements);
+
+ return file_system_context()->CrackURL(child_url);
+}
+
+NativeFileSystemEntryPtr NativeFileSystemDirectoryHandleImpl::CreateEntry(
+ const std::string& name,
+ const storage::FileSystemURL& url,
+ bool is_directory) {
+ if (is_directory) {
+ return NativeFileSystemEntry::New(
+ NativeFileSystemHandle::NewDirectory(
+ manager()
+ ->CreateDirectoryHandle(context(), url, file_system())
+ .PassInterface()),
+ name);
+ }
+ return NativeFileSystemEntry::New(
+ NativeFileSystemHandle::NewFile(
+ manager()
+ ->CreateFileHandle(context(), url, file_system())
+ .PassInterface()),
+ name);
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/native_file_system/native_file_system_directory_handle_impl.h b/chromium/content/browser/native_file_system/native_file_system_directory_handle_impl.h
new file mode 100644
index 00000000000..a84b51d85d5
--- /dev/null
+++ b/chromium/content/browser/native_file_system/native_file_system_directory_handle_impl.h
@@ -0,0 +1,98 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_DIRECTORY_HANDLE_IMPL_H_
+#define CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_DIRECTORY_HANDLE_IMPL_H_
+
+#include "base/files/file.h"
+#include "base/memory/weak_ptr.h"
+#include "components/services/filesystem/public/interfaces/types.mojom.h"
+#include "content/browser/native_file_system/native_file_system_handle_base.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom.h"
+
+
+namespace content {
+class NativeFileSystemTransferTokenImpl;
+
+// This is the browser side implementation of the
+// NativeFileSystemDirectoryHandle mojom interface. Instances of this class are
+// owned by the NativeFileSystemManagerImpl instance passed in to the
+// constructor.
+//
+// This class is not thread safe, all methods should be called on the same
+// sequence as storage::FileSystemContext, which today always is the IO thread.
+class NativeFileSystemDirectoryHandleImpl
+ : public NativeFileSystemHandleBase,
+ public blink::mojom::NativeFileSystemDirectoryHandle {
+ public:
+ NativeFileSystemDirectoryHandleImpl(
+ NativeFileSystemManagerImpl* manager,
+ const BindingContext& context,
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system);
+ ~NativeFileSystemDirectoryHandleImpl() override;
+
+ // blink::mojom::NativeFileSystemDirectoryHandle:
+ void GetFile(const std::string& name,
+ bool create,
+ GetFileCallback callback) override;
+ void GetDirectory(const std::string& name,
+ bool create,
+ GetDirectoryCallback callback) override;
+ void GetEntries(GetEntriesCallback callback) override;
+ void MoveFrom(blink::mojom::NativeFileSystemTransferTokenPtr source,
+ const std::string& name,
+ MoveFromCallback callback) override;
+ void CopyFrom(blink::mojom::NativeFileSystemTransferTokenPtr source,
+ const std::string& name,
+ CopyFromCallback callback) override;
+ void Remove(bool recurse, RemoveCallback callback) override;
+ void Transfer(
+ blink::mojom::NativeFileSystemTransferTokenRequest token) override;
+
+ private:
+ // State that is kept for the duration of a GetEntries/ReadDirectory call.
+ struct ReadDirectoryState;
+
+ void DidGetFile(storage::FileSystemURL url,
+ GetFileCallback callback,
+ base::File::Error result);
+ void DidGetDirectory(storage::FileSystemURL url,
+ GetDirectoryCallback callback,
+ base::File::Error result);
+ void DidReadDirectory(
+ ReadDirectoryState* state,
+ base::File::Error result,
+ std::vector<filesystem::mojom::DirectoryEntry> file_list,
+ bool has_more);
+
+ using CopyOrMoveCallback = MoveFromCallback;
+ void DoCopyOrMoveFrom(const std::string& new_name,
+ bool is_copy,
+ CopyOrMoveCallback callback,
+ NativeFileSystemTransferTokenImpl* source);
+ void DidCopyOrMove(CopyOrMoveCallback callback,
+ const std::string& new_name,
+ const storage::FileSystemURL& new_url,
+ bool is_directory,
+ base::File::Error result);
+
+ // Returns a FileSystemURL for a (direct) child of this directory with the
+ // given name.
+ storage::FileSystemURL GetChildURL(const std::string& name);
+
+ // Helper to create a blink::mojom::NativeFileSystemEntry struct.
+ blink::mojom::NativeFileSystemEntryPtr CreateEntry(
+ const std::string& name,
+ const storage::FileSystemURL& url,
+ bool is_directory);
+
+ base::WeakPtrFactory<NativeFileSystemDirectoryHandleImpl> weak_factory_{this};
+ DISALLOW_COPY_AND_ASSIGN(NativeFileSystemDirectoryHandleImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_DIRECTORY_HANDLE_IMPL_H_
diff --git a/chromium/content/browser/native_file_system/native_file_system_file_handle_impl.cc b/chromium/content/browser/native_file_system/native_file_system_file_handle_impl.cc
new file mode 100644
index 00000000000..92ed65f7442
--- /dev/null
+++ b/chromium/content/browser/native_file_system/native_file_system_file_handle_impl.cc
@@ -0,0 +1,240 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/native_file_system/native_file_system_file_handle_impl.h"
+
+#include "base/guid.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 "storage/browser/fileapi/file_system_operation_runner.h"
+#include "third_party/blink/public/mojom/blob/blob.mojom.h"
+#include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_transfer_token.mojom.h"
+
+using blink::mojom::NativeFileSystemError;
+using storage::BlobDataHandle;
+using storage::BlobImpl;
+using storage::FileSystemOperation;
+
+namespace content {
+
+struct NativeFileSystemFileHandleImpl::WriteState {
+ WriteCallback callback;
+ uint64_t bytes_written = 0;
+};
+
+NativeFileSystemFileHandleImpl::NativeFileSystemFileHandleImpl(
+ NativeFileSystemManagerImpl* manager,
+ const BindingContext& context,
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system)
+ : NativeFileSystemHandleBase(manager,
+ context,
+ url,
+ std::move(file_system)) {}
+
+NativeFileSystemFileHandleImpl::~NativeFileSystemFileHandleImpl() = default;
+
+void NativeFileSystemFileHandleImpl::AsBlob(AsBlobCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // TODO(mek): Check backend::SupportsStreaming and create snapshot file if
+ // streaming is not supported.
+ operation_runner()->GetMetadata(
+ url(),
+ FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY |
+ FileSystemOperation::GET_METADATA_FIELD_SIZE |
+ FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
+ base::BindOnce(&NativeFileSystemFileHandleImpl::DidGetMetaDataForBlob,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void NativeFileSystemFileHandleImpl::Remove(RemoveCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ operation_runner()->RemoveFile(
+ url(), base::BindOnce(
+ [](RemoveCallback callback, base::File::Error result) {
+ std::move(callback).Run(NativeFileSystemError::New(result));
+ },
+ std::move(callback)));
+}
+
+void NativeFileSystemFileHandleImpl::Write(uint64_t offset,
+ blink::mojom::BlobPtr data,
+ WriteCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ blob_context()->GetBlobDataFromBlobPtr(
+ std::move(data),
+ base::BindOnce(&NativeFileSystemFileHandleImpl::DoWriteBlob,
+ weak_factory_.GetWeakPtr(), std::move(callback), offset));
+}
+
+void NativeFileSystemFileHandleImpl::WriteStream(
+ uint64_t offset,
+ mojo::ScopedDataPipeConsumerHandle stream,
+ WriteStreamCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // FileSystemOperationRunner assumes that positions passed to Write are always
+ // valid, and will NOTREACHED() if that is not the case, so first check the
+ // size of the file to make sure the position passed in from the renderer is
+ // in fact valid.
+ // Of course the file could still change between checking its size and the
+ // write operation being started, but this is at least a lot better than the
+ // old implementation where the renderer only checks against how big it thinks
+ // the file currently is.
+ // TODO(https://crbug.com/957214): Fix this situation.
+ operation_runner()->GetMetadata(
+ url(), FileSystemOperation::GET_METADATA_FIELD_SIZE,
+ base::BindOnce(&NativeFileSystemFileHandleImpl::DoWriteStreamWithFileInfo,
+ weak_factory_.GetWeakPtr(), std::move(callback), offset,
+ std::move(stream)));
+}
+
+void NativeFileSystemFileHandleImpl::Truncate(uint64_t length,
+ TruncateCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ operation_runner()->Truncate(
+ url(), length,
+ base::BindOnce(
+ [](TruncateCallback callback, base::File::Error result) {
+ std::move(callback).Run(NativeFileSystemError::New(result));
+ },
+ std::move(callback)));
+}
+
+void NativeFileSystemFileHandleImpl::Transfer(
+ blink::mojom::NativeFileSystemTransferTokenRequest token) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ manager()->CreateTransferToken(*this, std::move(token));
+}
+
+void NativeFileSystemFileHandleImpl::DidGetMetaDataForBlob(
+ AsBlobCallback callback,
+ base::File::Error result,
+ const base::File::Info& info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (result != base::File::FILE_OK) {
+ std::move(callback).Run(NativeFileSystemError::New(result), nullptr);
+ return;
+ }
+
+ std::string uuid = base::GenerateGUID();
+ auto blob_builder = std::make_unique<storage::BlobDataBuilder>(uuid);
+ // Use AppendFileSystemFile here, since we're streaming the file directly
+ // from the file system backend, and the file thus might not actually be
+ // backed by a file on disk.
+ blob_builder->AppendFileSystemFile(url().ToGURL(), 0, -1, info.last_modified,
+ file_system_context());
+ std::unique_ptr<BlobDataHandle> blob_handle =
+ blob_context()->AddFinishedBlob(std::move(blob_builder));
+ if (blob_handle->IsBroken()) {
+ std::move(callback).Run(
+ NativeFileSystemError::New(base::File::FILE_ERROR_FAILED), nullptr);
+ return;
+ }
+
+ blink::mojom::BlobPtr blob_ptr;
+ BlobImpl::Create(std::move(blob_handle), mojo::MakeRequest(&blob_ptr));
+
+ // TODO(mek): Figure out what mime-type to use for these files. The old
+ // file system API implementation uses net::GetWellKnownMimeTypeFromExtension
+ // to figure out a reasonable mime type based on the extension.
+ std::move(callback).Run(
+ NativeFileSystemError::New(base::File::FILE_OK),
+ blink::mojom::SerializedBlob::New(uuid, "application/octet-stream",
+ info.size, blob_ptr.PassInterface()));
+}
+
+void NativeFileSystemFileHandleImpl::DoWriteBlob(
+ WriteCallback callback,
+ uint64_t position,
+ std::unique_ptr<BlobDataHandle> blob) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!blob) {
+ std::move(callback).Run(
+ NativeFileSystemError::New(base::File::FILE_ERROR_FAILED), 0);
+ return;
+ }
+
+ // FileSystemOperationRunner assumes that positions passed to Write are always
+ // valid, and will NOTREACHED() if that is not the case, so first check the
+ // size of the file to make sure the position passed in from the renderer is
+ // in fact valid.
+ // Of course the file could still change between checking its size and the
+ // write operation being started, but this is at least a lot better than the
+ // old implementation where the renderer only checks against how big it thinks
+ // the file currently is.
+ // TODO(https://crbug.com/957214): Fix this situation.
+ operation_runner()->GetMetadata(
+ url(), FileSystemOperation::GET_METADATA_FIELD_SIZE,
+ base::BindOnce(&NativeFileSystemFileHandleImpl::DoWriteBlobWithFileInfo,
+ weak_factory_.GetWeakPtr(), std::move(callback), position,
+ std::move(blob)));
+}
+
+void NativeFileSystemFileHandleImpl::DoWriteBlobWithFileInfo(
+ WriteCallback callback,
+ uint64_t position,
+ std::unique_ptr<BlobDataHandle> blob,
+ base::File::Error result,
+ const base::File::Info& file_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (file_info.size < 0 || position > static_cast<uint64_t>(file_info.size)) {
+ std::move(callback).Run(
+ NativeFileSystemError::New(base::File::FILE_ERROR_FAILED), 0);
+ return;
+ }
+
+ operation_runner()->Write(
+ url(), std::move(blob), position,
+ base::BindRepeating(&NativeFileSystemFileHandleImpl::DidWrite,
+ weak_factory_.GetWeakPtr(),
+ base::Owned(new WriteState{std::move(callback)})));
+}
+
+void NativeFileSystemFileHandleImpl::DoWriteStreamWithFileInfo(
+ WriteStreamCallback callback,
+ uint64_t position,
+ mojo::ScopedDataPipeConsumerHandle data_pipe,
+ base::File::Error result,
+ const base::File::Info& file_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (file_info.size < 0 || position > static_cast<uint64_t>(file_info.size)) {
+ std::move(callback).Run(
+ NativeFileSystemError::New(base::File::FILE_ERROR_FAILED), 0);
+ return;
+ }
+
+ operation_runner()->Write(
+ url(), std::move(data_pipe), position,
+ base::BindRepeating(&NativeFileSystemFileHandleImpl::DidWrite,
+ weak_factory_.GetWeakPtr(),
+ base::Owned(new WriteState{std::move(callback)})));
+}
+
+void NativeFileSystemFileHandleImpl::DidWrite(WriteState* state,
+ base::File::Error result,
+ int64_t bytes,
+ bool complete) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ DCHECK(state);
+ state->bytes_written += bytes;
+ if (complete) {
+ std::move(state->callback)
+ .Run(NativeFileSystemError::New(result), state->bytes_written);
+ }
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/native_file_system/native_file_system_file_handle_impl.h b/chromium/content/browser/native_file_system/native_file_system_file_handle_impl.h
new file mode 100644
index 00000000000..b303c8055a4
--- /dev/null
+++ b/chromium/content/browser/native_file_system/native_file_system_file_handle_impl.h
@@ -0,0 +1,91 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_FILE_HANDLE_IMPL_H_
+#define CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_FILE_HANDLE_IMPL_H_
+
+#include "base/files/file.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/native_file_system/native_file_system_handle_base.h"
+#include "content/browser/native_file_system/native_file_system_manager_impl.h"
+#include "content/common/content_export.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_file_handle.mojom.h"
+
+namespace storage {
+class BlobDataHandle;
+} // namespace storage
+
+namespace content {
+
+// This is the browser side implementation of the
+// NativeFileSystemFileHandle mojom interface. Instances of this class are
+// owned by the NativeFileSystemManagerImpl instance passed in to the
+// constructor.
+//
+// This class is not thread safe, all methods should be called on the IO thread.
+// The link to the IO thread is due to its dependencies on both the blob system
+// (via storage::BlobStorageContext) and the file system backends (via
+// storage::FileSystemContext and storage::FileSystemOperationRunner, which both
+// expect some of their methods to always be called on the IO thread).
+// See https://crbug.com/957249 for some thoughts about the blob system aspect
+// of this.
+class CONTENT_EXPORT NativeFileSystemFileHandleImpl
+ : public NativeFileSystemHandleBase,
+ public blink::mojom::NativeFileSystemFileHandle {
+ public:
+ NativeFileSystemFileHandleImpl(
+ NativeFileSystemManagerImpl* manager,
+ const BindingContext& context,
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system);
+ ~NativeFileSystemFileHandleImpl() override;
+
+ // blink::mojom::NativeFileSystemFileHandle:
+ void AsBlob(AsBlobCallback callback) override;
+ void Remove(RemoveCallback callback) override;
+ void Write(uint64_t offset,
+ blink::mojom::BlobPtr data,
+ WriteCallback callback) override;
+ void WriteStream(uint64_t offset,
+ mojo::ScopedDataPipeConsumerHandle stream,
+ WriteStreamCallback callback) override;
+ void Truncate(uint64_t length, TruncateCallback callback) override;
+ void Transfer(
+ blink::mojom::NativeFileSystemTransferTokenRequest token) override;
+
+ private:
+ // State that is kept for the duration of a write operation, to keep track of
+ // progress until the write completes.
+ struct WriteState;
+
+ void DidGetMetaDataForBlob(AsBlobCallback callback,
+ base::File::Error result,
+ const base::File::Info& info);
+
+ void DoWriteBlob(WriteCallback callback,
+ uint64_t position,
+ std::unique_ptr<storage::BlobDataHandle> blob);
+ void DoWriteBlobWithFileInfo(WriteCallback callback,
+ uint64_t position,
+ std::unique_ptr<storage::BlobDataHandle> blob,
+ base::File::Error result,
+ const base::File::Info& file_info);
+ void DoWriteStreamWithFileInfo(WriteStreamCallback callback,
+ uint64_t position,
+ mojo::ScopedDataPipeConsumerHandle data_pipe,
+ base::File::Error result,
+ const base::File::Info& file_info);
+ void DidWrite(WriteState* state,
+ base::File::Error result,
+ int64_t bytes,
+ bool complete);
+
+ base::WeakPtrFactory<NativeFileSystemFileHandleImpl> weak_factory_{this};
+ DISALLOW_COPY_AND_ASSIGN(NativeFileSystemFileHandleImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_FILE_HANDLE_IMPL_H_
diff --git a/chromium/content/browser/native_file_system/native_file_system_file_handle_impl_unittest.cc b/chromium/content/browser/native_file_system/native_file_system_file_handle_impl_unittest.cc
new file mode 100644
index 00000000000..56fba97cffd
--- /dev/null
+++ b/chromium/content/browser/native_file_system/native_file_system_file_handle_impl_unittest.cc
@@ -0,0 +1,294 @@
+// 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/native_file_system/native_file_system_file_handle_impl.h"
+
+#include <limits>
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/guid.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "mojo/public/cpp/system/string_data_pipe_producer.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.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 "storage/browser/fileapi/file_stream_reader.h"
+#include "storage/browser/test/async_file_test_helper.h"
+#include "storage/browser/test/test_file_system_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+
+using storage::FileSystemURL;
+
+namespace content {
+
+class NativeFileSystemFileHandleImplTest : public testing::Test {
+ public:
+ NativeFileSystemFileHandleImplTest()
+ : scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::IO) {
+ scoped_feature_list_.InitAndEnableFeature(
+ blink::features::kNativeFileSystemAPI);
+ }
+
+ void SetUp() override {
+ ASSERT_TRUE(dir_.CreateUniqueTempDir());
+ file_system_context_ = CreateFileSystemContextForTesting(
+ /*quota_manager_proxy=*/nullptr, dir_.GetPath());
+
+ test_url_ = file_system_context_->CreateCrackedFileSystemURL(
+ GURL("http://example.com"), storage::kFileSystemTypeTest,
+ base::FilePath::FromUTF8Unsafe("test"));
+
+ ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::CreateFile(
+ file_system_context_.get(), test_url_));
+
+ chrome_blob_context_ = base::MakeRefCounted<ChromeBlobStorageContext>();
+ chrome_blob_context_->InitializeOnIOThread(base::FilePath(), nullptr);
+ blob_context_ = chrome_blob_context_->context();
+
+ manager_ = base::MakeRefCounted<NativeFileSystemManagerImpl>(
+ file_system_context_, chrome_blob_context_);
+
+ handle_ = std::make_unique<NativeFileSystemFileHandleImpl>(
+ manager_.get(),
+ NativeFileSystemManagerImpl::BindingContext(
+ test_url_.origin(), /*process_id=*/1,
+ /*frame_id=*/MSG_ROUTING_NONE),
+ test_url_, storage::IsolatedContext::ScopedFSHandle());
+ }
+
+ blink::mojom::BlobPtr CreateBlob(const std::string& contents) {
+ auto builder =
+ std::make_unique<storage::BlobDataBuilder>(base::GenerateGUID());
+ builder->AppendData(contents);
+ auto handle = blob_context_->AddFinishedBlob(std::move(builder));
+ blink::mojom::BlobPtr result;
+ storage::BlobImpl::Create(std::move(handle), MakeRequest(&result));
+ return result;
+ }
+
+ mojo::ScopedDataPipeConsumerHandle CreateStream(const std::string& contents) {
+ // Test with a relatively low capacity pipe to make sure it isn't all
+ // written/read in one go.
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(MojoCreateDataPipeOptions);
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+ options.element_num_bytes = 1;
+ options.capacity_num_bytes = 16;
+ mojo::CreateDataPipe(&options, &producer_handle, &consumer_handle);
+ CHECK(producer_handle.is_valid());
+ auto producer = std::make_unique<mojo::StringDataPipeProducer>(
+ std::move(producer_handle));
+ auto* producer_raw = producer.get();
+ producer_raw->Write(
+ contents,
+ mojo::StringDataPipeProducer::AsyncWritingMode::
+ STRING_MAY_BE_INVALIDATED_BEFORE_COMPLETION,
+ base::BindOnce(
+ base::DoNothing::Once<std::unique_ptr<mojo::StringDataPipeProducer>,
+ MojoResult>(),
+ std::move(producer)));
+ return consumer_handle;
+ }
+
+ std::string ReadFile(const FileSystemURL& url) {
+ std::unique_ptr<storage::FileStreamReader> reader =
+ file_system_context_->CreateFileStreamReader(
+ url, 0, std::numeric_limits<int64_t>::max(), base::Time());
+ std::string result;
+ while (true) {
+ auto buf = base::MakeRefCounted<net::IOBufferWithSize>(4096);
+ net::TestCompletionCallback callback;
+ int rv = reader->Read(buf.get(), buf->size(), callback.callback());
+ if (rv == net::ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ EXPECT_GE(rv, 0);
+ if (rv < 0)
+ return "(read failure)";
+ if (rv == 0)
+ return result;
+ result.append(buf->data(), rv);
+ }
+ }
+
+ base::File::Error WriteBlobSync(uint64_t position,
+ blink::mojom::BlobPtr blob,
+ uint64_t* bytes_written_out) {
+ base::RunLoop loop;
+ base::File::Error result_out;
+ handle_->Write(position, std::move(blob),
+ base::BindLambdaForTesting(
+ [&](blink::mojom::NativeFileSystemErrorPtr result,
+ uint64_t bytes_written) {
+ result_out = result->error_code;
+ *bytes_written_out = bytes_written;
+ loop.Quit();
+ }));
+ loop.Run();
+ return result_out;
+ }
+
+ base::File::Error WriteStreamSync(
+ uint64_t position,
+ mojo::ScopedDataPipeConsumerHandle data_pipe,
+ uint64_t* bytes_written_out) {
+ base::RunLoop loop;
+ base::File::Error result_out;
+ handle_->WriteStream(position, std::move(data_pipe),
+ base::BindLambdaForTesting(
+ [&](blink::mojom::NativeFileSystemErrorPtr result,
+ uint64_t bytes_written) {
+ result_out = result->error_code;
+ *bytes_written_out = bytes_written;
+ loop.Quit();
+ }));
+ loop.Run();
+ return result_out;
+ }
+
+ base::File::Error TruncateSync(uint64_t length) {
+ base::RunLoop loop;
+ base::File::Error result_out;
+ handle_->Truncate(length,
+ base::BindLambdaForTesting(
+ [&](blink::mojom::NativeFileSystemErrorPtr result) {
+ result_out = result->error_code;
+ loop.Quit();
+ }));
+ loop.Run();
+ return result_out;
+ }
+
+ virtual bool WriteUsingBlobs() { return true; }
+
+ base::File::Error WriteSync(uint64_t position,
+ const std::string& contents,
+ uint64_t* bytes_written_out) {
+ if (WriteUsingBlobs())
+ return WriteBlobSync(position, CreateBlob(contents), bytes_written_out);
+ return WriteStreamSync(position, CreateStream(contents), bytes_written_out);
+ }
+
+ protected:
+ base::test::ScopedFeatureList scoped_feature_list_;
+ TestBrowserThreadBundle scoped_task_environment_;
+
+ base::ScopedTempDir dir_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
+ scoped_refptr<ChromeBlobStorageContext> chrome_blob_context_;
+ storage::BlobStorageContext* blob_context_;
+ scoped_refptr<NativeFileSystemManagerImpl> manager_;
+
+ FileSystemURL test_url_;
+
+ std::unique_ptr<NativeFileSystemFileHandleImpl> handle_;
+};
+
+class NativeFileSystemFileHandleImplWriteTest
+ : public NativeFileSystemFileHandleImplTest,
+ public testing::WithParamInterface<bool> {
+ public:
+ bool WriteUsingBlobs() override { return GetParam(); }
+};
+
+INSTANTIATE_TEST_SUITE_P(NativeFileSystemFileHandleImplTest,
+ NativeFileSystemFileHandleImplWriteTest,
+ ::testing::Bool());
+
+TEST_F(NativeFileSystemFileHandleImplTest, WriteInvalidBlob) {
+ blink::mojom::BlobPtr blob;
+ MakeRequest(&blob);
+
+ uint64_t bytes_written;
+ base::File::Error result = WriteBlobSync(0, std::move(blob), &bytes_written);
+ EXPECT_EQ(result, base::File::FILE_ERROR_FAILED);
+ EXPECT_EQ(bytes_written, 0u);
+
+ EXPECT_EQ("", ReadFile(test_url_));
+}
+
+TEST_P(NativeFileSystemFileHandleImplWriteTest, WriteValidEmptyString) {
+ uint64_t bytes_written;
+ base::File::Error result = WriteSync(0, "", &bytes_written);
+ EXPECT_EQ(result, base::File::FILE_OK);
+ EXPECT_EQ(bytes_written, 0u);
+
+ EXPECT_EQ("", ReadFile(test_url_));
+}
+
+TEST_P(NativeFileSystemFileHandleImplWriteTest, WriteValidNonEmpty) {
+ std::string test_data("abcdefghijklmnopqrstuvwxyz");
+ uint64_t bytes_written;
+ base::File::Error result = WriteSync(0, test_data, &bytes_written);
+ EXPECT_EQ(result, base::File::FILE_OK);
+ EXPECT_EQ(bytes_written, test_data.size());
+
+ EXPECT_EQ(test_data, ReadFile(test_url_));
+}
+
+TEST_P(NativeFileSystemFileHandleImplWriteTest, WriteWithOffsetInFile) {
+ uint64_t bytes_written;
+ base::File::Error result;
+
+ result = WriteSync(0, "1234567890", &bytes_written);
+ EXPECT_EQ(result, base::File::FILE_OK);
+ EXPECT_EQ(bytes_written, 10u);
+
+ result = WriteSync(4, "abc", &bytes_written);
+ EXPECT_EQ(result, base::File::FILE_OK);
+ EXPECT_EQ(bytes_written, 3u);
+
+ EXPECT_EQ("1234abc890", ReadFile(test_url_));
+}
+
+TEST_P(NativeFileSystemFileHandleImplWriteTest, WriteWithOffsetPastFile) {
+ uint64_t bytes_written;
+ base::File::Error result = WriteSync(4, "abc", &bytes_written);
+ EXPECT_EQ(result, base::File::FILE_ERROR_FAILED);
+ EXPECT_EQ(bytes_written, 0u);
+
+ EXPECT_EQ("", ReadFile(test_url_));
+}
+
+TEST_F(NativeFileSystemFileHandleImplTest, TruncateShrink) {
+ uint64_t bytes_written;
+ base::File::Error result;
+
+ result = WriteSync(0, "1234567890", &bytes_written);
+ EXPECT_EQ(result, base::File::FILE_OK);
+ EXPECT_EQ(bytes_written, 10u);
+
+ result = TruncateSync(5);
+ EXPECT_EQ(result, base::File::FILE_OK);
+
+ EXPECT_EQ("12345", ReadFile(test_url_));
+}
+
+TEST_F(NativeFileSystemFileHandleImplTest, TruncateGrow) {
+ uint64_t bytes_written;
+ base::File::Error result;
+
+ result = WriteSync(0, "abc", &bytes_written);
+ EXPECT_EQ(result, base::File::FILE_OK);
+ EXPECT_EQ(bytes_written, 3u);
+
+ result = TruncateSync(5);
+ EXPECT_EQ(result, base::File::FILE_OK);
+
+ EXPECT_EQ(std::string("abc\0\0", 5), ReadFile(test_url_));
+}
+
+// TODO(mek): More tests, particularly for error conditions.
+
+} // namespace content
diff --git a/chromium/content/browser/native_file_system/native_file_system_handle_base.cc b/chromium/content/browser/native_file_system/native_file_system_handle_base.cc
new file mode 100644
index 00000000000..c3ebad3efc9
--- /dev/null
+++ b/chromium/content/browser/native_file_system/native_file_system_handle_base.cc
@@ -0,0 +1,26 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/native_file_system/native_file_system_handle_base.h"
+
+namespace content {
+
+NativeFileSystemHandleBase::NativeFileSystemHandleBase(
+ NativeFileSystemManagerImpl* manager,
+ const BindingContext& context,
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system)
+ : manager_(manager),
+ context_(context),
+ url_(url),
+ file_system_(std::move(file_system)) {
+ DCHECK(manager_);
+ DCHECK_EQ(url_.mount_type() == storage::kFileSystemTypeIsolated,
+ file_system_.is_valid())
+ << url_.mount_type();
+}
+
+NativeFileSystemHandleBase::~NativeFileSystemHandleBase() = default;
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/native_file_system/native_file_system_handle_base.h b/chromium/content/browser/native_file_system/native_file_system_handle_base.h
new file mode 100644
index 00000000000..6f2c1a3718a
--- /dev/null
+++ b/chromium/content/browser/native_file_system/native_file_system_handle_base.h
@@ -0,0 +1,73 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_HANDLE_BASE_H_
+#define CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_HANDLE_BASE_H_
+
+#include <vector>
+
+#include "content/browser/native_file_system/native_file_system_manager_impl.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
+
+namespace storage {
+class FileSystemContext;
+class FileSystemOperationRunner;
+class BlobStorageContext;
+} // namespace storage
+
+namespace content {
+
+// Base class for File and Directory handle implementations. Holds data that is
+// common to both and (will) deal with functionality that is common as well,
+// such as permission requests. Instances of this class should be owned by the
+// NativeFileSystemManagerImpl instance passed in to the constructor.
+//
+// This class is not thread safe, all methods should only be called on the IO
+// thread. This is because code interacts directly with the file system backends
+// (via storage::FileSystemContext and store::FileSystemOperationRunner, which
+// both expect some of their methods to only be called on the IO thread).
+class NativeFileSystemHandleBase {
+ public:
+ using BindingContext = NativeFileSystemManagerImpl::BindingContext;
+
+ NativeFileSystemHandleBase(
+ NativeFileSystemManagerImpl* manager,
+ const BindingContext& context,
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system);
+ virtual ~NativeFileSystemHandleBase();
+
+ const storage::FileSystemURL& url() const { return url_; }
+ const storage::IsolatedContext::ScopedFSHandle& file_system() const {
+ return file_system_;
+ }
+
+ protected:
+ NativeFileSystemManagerImpl* manager() { return manager_; }
+ const BindingContext& context() { return context_; }
+ storage::FileSystemOperationRunner* operation_runner() {
+ return manager()->operation_runner();
+ }
+ storage::FileSystemContext* file_system_context() {
+ return manager()->context();
+ }
+ storage::BlobStorageContext* blob_context() {
+ return manager()->blob_context();
+ }
+
+ private:
+ // The NativeFileSystemManagerImpl that owns this instance.
+ NativeFileSystemManagerImpl* const manager_;
+ const BindingContext context_;
+ const storage::FileSystemURL url_;
+ const storage::IsolatedContext::ScopedFSHandle file_system_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeFileSystemHandleBase);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_HANDLE_BASE_H_
diff --git a/chromium/content/browser/native_file_system/native_file_system_manager_impl.cc b/chromium/content/browser/native_file_system/native_file_system_manager_impl.cc
new file mode 100644
index 00000000000..24313daa392
--- /dev/null
+++ b/chromium/content/browser/native_file_system/native_file_system_manager_impl.cc
@@ -0,0 +1,299 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/native_file_system/native_file_system_manager_impl.h"
+
+#include "base/files/file_path.h"
+#include "base/task/post_task.h"
+#include "content/browser/native_file_system/file_system_chooser.h"
+#include "content/browser/native_file_system/native_file_system_directory_handle_impl.h"
+#include "content/browser/native_file_system/native_file_system_file_handle_impl.h"
+#include "content/browser/native_file_system/native_file_system_transfer_token_impl.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
+#include "mojo/public/cpp/bindings/callback_helpers.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "storage/common/fileapi/file_system_util.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom.h"
+#include "url/origin.h"
+
+using blink::mojom::NativeFileSystemError;
+
+namespace content {
+
+NativeFileSystemManagerImpl::NativeFileSystemManagerImpl(
+ scoped_refptr<storage::FileSystemContext> context,
+ scoped_refptr<ChromeBlobStorageContext> blob_context)
+ : context_(std::move(context)), blob_context_(std::move(blob_context)) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(context_);
+ DCHECK(blob_context_);
+}
+
+NativeFileSystemManagerImpl::~NativeFileSystemManagerImpl() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+void NativeFileSystemManagerImpl::BindRequest(
+ const BindingContext& binding_context,
+ blink::mojom::NativeFileSystemManagerRequest request) {
+ DCHECK(base::FeatureList::IsEnabled(blink::features::kNativeFileSystemAPI));
+
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ bindings_.AddBinding(this, std::move(request), binding_context);
+}
+
+void NativeFileSystemManagerImpl::GetSandboxedFileSystem(
+ GetSandboxedFileSystemCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ url::Origin origin = bindings_.dispatch_context().origin;
+
+ context()->OpenFileSystem(
+ origin.GetURL(), storage::kFileSystemTypeTemporary,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::BindOnce(&NativeFileSystemManagerImpl::DidOpenSandboxedFileSystem,
+ weak_factory_.GetWeakPtr(), bindings_.dispatch_context(),
+ std::move(callback)));
+}
+
+void NativeFileSystemManagerImpl::ChooseEntries(
+ blink::mojom::ChooseFileSystemEntryType type,
+ std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts,
+ bool include_accepts_all,
+ ChooseEntriesCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const BindingContext& context = bindings_.dispatch_context();
+
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(
+ &FileSystemChooser::CreateAndShow, context.process_id,
+ context.frame_id, type, std::move(accepts), include_accepts_all,
+ base::BindOnce(&NativeFileSystemManagerImpl::DidChooseEntries,
+ weak_factory_.GetWeakPtr(), context, type,
+ std::move(callback)),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})));
+}
+
+blink::mojom::NativeFileSystemFileHandlePtr
+NativeFileSystemManagerImpl::CreateFileHandle(
+ const BindingContext& binding_context,
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(url.is_valid());
+ DCHECK_EQ(url.mount_type() == storage::kFileSystemTypeIsolated,
+ file_system.is_valid())
+ << url.mount_type();
+
+ blink::mojom::NativeFileSystemFileHandlePtr result;
+ file_bindings_.AddBinding(
+ std::make_unique<NativeFileSystemFileHandleImpl>(
+ this, binding_context, url, std::move(file_system)),
+ mojo::MakeRequest(&result));
+ return result;
+}
+
+blink::mojom::NativeFileSystemDirectoryHandlePtr
+NativeFileSystemManagerImpl::CreateDirectoryHandle(
+ const BindingContext& binding_context,
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(url.is_valid());
+ DCHECK_EQ(url.mount_type() == storage::kFileSystemTypeIsolated,
+ file_system.is_valid())
+ << url.mount_type();
+
+ blink::mojom::NativeFileSystemDirectoryHandlePtr result;
+ directory_bindings_.AddBinding(
+ std::make_unique<NativeFileSystemDirectoryHandleImpl>(
+ this, binding_context, url, std::move(file_system)),
+ mojo::MakeRequest(&result));
+ return result;
+}
+
+blink::mojom::NativeFileSystemEntryPtr
+NativeFileSystemManagerImpl::CreateFileEntryFromPath(
+ const BindingContext& binding_context,
+ const base::FilePath& file_path) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ auto url = CreateFileSystemURLFromPath(binding_context.origin, file_path);
+
+ return blink::mojom::NativeFileSystemEntry::New(
+ blink::mojom::NativeFileSystemHandle::NewFile(
+ CreateFileHandle(binding_context, url.url, std::move(url.file_system))
+ .PassInterface()),
+ url.base_name);
+}
+
+blink::mojom::NativeFileSystemEntryPtr
+NativeFileSystemManagerImpl::CreateDirectoryEntryFromPath(
+ const BindingContext& binding_context,
+ const base::FilePath& directory_path) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ auto url =
+ CreateFileSystemURLFromPath(binding_context.origin, directory_path);
+
+ return blink::mojom::NativeFileSystemEntry::New(
+ blink::mojom::NativeFileSystemHandle::NewDirectory(
+ CreateDirectoryHandle(binding_context, url.url,
+ std::move(url.file_system))
+ .PassInterface()),
+ url.base_name);
+}
+
+void NativeFileSystemManagerImpl::CreateTransferToken(
+ const NativeFileSystemFileHandleImpl& file,
+ blink::mojom::NativeFileSystemTransferTokenRequest request) {
+ return CreateTransferTokenImpl(file.url(), file.file_system(),
+ /*is_directory=*/false, std::move(request));
+}
+
+void NativeFileSystemManagerImpl::CreateTransferToken(
+ const NativeFileSystemDirectoryHandleImpl& directory,
+ blink::mojom::NativeFileSystemTransferTokenRequest request) {
+ return CreateTransferTokenImpl(directory.url(), directory.file_system(),
+ /*is_directory=*/true, std::move(request));
+}
+
+void NativeFileSystemManagerImpl::ResolveTransferToken(
+ blink::mojom::NativeFileSystemTransferTokenPtr token,
+ ResolvedTokenCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ auto* raw_token = token.get();
+ raw_token->GetInternalID(mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce(&NativeFileSystemManagerImpl::DoResolveTransferToken,
+ weak_factory_.GetWeakPtr(), std::move(token),
+ std::move(callback)),
+ base::UnguessableToken()));
+}
+
+storage::FileSystemOperationRunner*
+NativeFileSystemManagerImpl::operation_runner() {
+ if (!operation_runner_)
+ operation_runner_ = context()->CreateFileSystemOperationRunner();
+ return operation_runner_.get();
+}
+
+void NativeFileSystemManagerImpl::DidOpenSandboxedFileSystem(
+ const BindingContext& binding_context,
+ GetSandboxedFileSystemCallback callback,
+ const GURL& root,
+ const std::string& filesystem_name,
+ base::File::Error result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (result != base::File::FILE_OK) {
+ std::move(callback).Run(NativeFileSystemError::New(result), nullptr);
+ return;
+ }
+
+ std::move(callback).Run(
+ NativeFileSystemError::New(base::File::FILE_OK),
+ CreateDirectoryHandle(binding_context, context()->CrackURL(root),
+ /*file_system=*/{}));
+}
+
+void NativeFileSystemManagerImpl::DidChooseEntries(
+ const BindingContext& binding_context,
+ blink::mojom::ChooseFileSystemEntryType type,
+ ChooseEntriesCallback callback,
+ blink::mojom::NativeFileSystemErrorPtr result,
+ std::vector<base::FilePath> entries) {
+ std::vector<blink::mojom::NativeFileSystemEntryPtr> result_entries;
+ if (result->error_code != base::File::FILE_OK) {
+ std::move(callback).Run(std::move(result), std::move(result_entries));
+ return;
+ }
+ result_entries.reserve(entries.size());
+ for (const auto& entry : entries) {
+ if (type == blink::mojom::ChooseFileSystemEntryType::kOpenDirectory) {
+ result_entries.push_back(
+ CreateDirectoryEntryFromPath(binding_context, entry));
+ } else {
+ result_entries.push_back(CreateFileEntryFromPath(binding_context, entry));
+ }
+ }
+ std::move(callback).Run(std::move(result), std::move(result_entries));
+}
+
+void NativeFileSystemManagerImpl::CreateTransferTokenImpl(
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system,
+ bool is_directory,
+ blink::mojom::NativeFileSystemTransferTokenRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ auto token_impl = std::make_unique<NativeFileSystemTransferTokenImpl>(
+ url, std::move(file_system),
+ is_directory ? NativeFileSystemTransferTokenImpl::HandleType::kDirectory
+ : NativeFileSystemTransferTokenImpl::HandleType::kFile);
+ auto token = token_impl->token();
+ blink::mojom::NativeFileSystemTransferTokenPtr result;
+ auto emplace_result = transfer_tokens_.emplace(
+ std::piecewise_construct, std::forward_as_tuple(token),
+ std::forward_as_tuple(std::move(token_impl), std::move(request)));
+ DCHECK(emplace_result.second);
+ emplace_result.first->second.set_connection_error_handler(base::BindOnce(
+ &NativeFileSystemManagerImpl::TransferTokenConnectionErrorHandler,
+ base::Unretained(this), token));
+}
+
+void NativeFileSystemManagerImpl::TransferTokenConnectionErrorHandler(
+ const base::UnguessableToken& token) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ size_t count_removed = transfer_tokens_.erase(token);
+ DCHECK_EQ(1u, count_removed);
+}
+
+void NativeFileSystemManagerImpl::DoResolveTransferToken(
+ blink::mojom::NativeFileSystemTransferTokenPtr,
+ ResolvedTokenCallback callback,
+ const base::UnguessableToken& token) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ auto it = transfer_tokens_.find(token);
+ if (it == transfer_tokens_.end()) {
+ std::move(callback).Run(nullptr);
+ } else {
+ std::move(callback).Run(
+ static_cast<NativeFileSystemTransferTokenImpl*>(it->second.impl()));
+ }
+}
+
+NativeFileSystemManagerImpl::FileSystemURLAndFSHandle
+NativeFileSystemManagerImpl::CreateFileSystemURLFromPath(
+ const url::Origin& origin,
+ const base::FilePath& path) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ auto* isolated_context = storage::IsolatedContext::GetInstance();
+ DCHECK(isolated_context);
+
+ FileSystemURLAndFSHandle result;
+
+ result.file_system = isolated_context->RegisterFileSystemForPath(
+ storage::kFileSystemTypeNativeLocal, std::string(), path,
+ &result.base_name);
+
+ base::FilePath root_path =
+ isolated_context->CreateVirtualRootPath(result.file_system.id());
+ base::FilePath isolated_path = root_path.AppendASCII(result.base_name);
+
+ result.url = context()->CreateCrackedFileSystemURL(
+ origin.GetURL(), storage::kFileSystemTypeIsolated, isolated_path);
+ return result;
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/native_file_system/native_file_system_manager_impl.h b/chromium/content/browser/native_file_system/native_file_system_manager_impl.h
new file mode 100644
index 00000000000..d3e41e25531
--- /dev/null
+++ b/chromium/content/browser/native_file_system/native_file_system_manager_impl.h
@@ -0,0 +1,191 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_MANAGER_IMPL_H_
+#define CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_MANAGER_IMPL_H_
+
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/native_file_system/file_system_chooser.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_thread.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/strong_binding_set.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom.h"
+
+namespace storage {
+class FileSystemContext;
+class FileSystemOperationRunner;
+} // namespace storage
+
+namespace content {
+class NativeFileSystemFileHandleImpl;
+class NativeFileSystemDirectoryHandleImpl;
+class NativeFileSystemTransferTokenImpl;
+
+// This is the browser side implementation of the
+// NativeFileSystemManager mojom interface. This is the main entry point for
+// the native file system API in the browser process.Instances of this class are
+// owned by StoragePartitionImpl.
+//
+// This class owns all the NativeFileSystemFileHandleImpl,
+// NativeFileSystemDirectoryHandleImpl and NativeFileSystemTransferTokenImpl
+// instances for a specific storage partition.
+//
+// This class is not thread safe, it is constructed on the UI thread, and after
+// that all methods should be called on the IO thread.
+class CONTENT_EXPORT NativeFileSystemManagerImpl
+ : public base::RefCountedThreadSafe<NativeFileSystemManagerImpl,
+ BrowserThread::DeleteOnIOThread>,
+ public blink::mojom::NativeFileSystemManager {
+ public:
+ struct BindingContext {
+ BindingContext(const url::Origin& origin, int process_id, int frame_id)
+ : origin(origin), process_id(process_id), frame_id(frame_id) {}
+ url::Origin origin;
+ int process_id;
+ int frame_id;
+ };
+
+ NativeFileSystemManagerImpl(
+ scoped_refptr<storage::FileSystemContext> context,
+ scoped_refptr<ChromeBlobStorageContext> blob_context);
+
+ void BindRequest(const BindingContext& binding_context,
+ blink::mojom::NativeFileSystemManagerRequest request);
+
+ // blink::mojom::NativeFileSystemManager:
+ void GetSandboxedFileSystem(GetSandboxedFileSystemCallback callback) override;
+ void ChooseEntries(
+ blink::mojom::ChooseFileSystemEntryType type,
+ std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts,
+ bool include_accepts_all,
+ ChooseEntriesCallback callback) override;
+
+ // Creates a new NativeFileSystemFileHandleImpl for a given url. Assumes the
+ // passed in URL is valid and represents a file.
+ blink::mojom::NativeFileSystemFileHandlePtr CreateFileHandle(
+ const BindingContext& binding_context,
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system);
+
+ // Creates a new NativeFileSystemDirectoryHandleImpl for a given url. Assumes
+ // the passed in URL is valid and represents a directory.
+ blink::mojom::NativeFileSystemDirectoryHandlePtr CreateDirectoryHandle(
+ const BindingContext& context,
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system);
+
+ // Creates a new NativeFileSystemEntryPtr from the path to a file. Assumes the
+ // passed in path is valid and represents a file.
+ blink::mojom::NativeFileSystemEntryPtr CreateFileEntryFromPath(
+ const BindingContext& binding_context,
+ const base::FilePath& file_path);
+
+ // Creates a new NativeFileSystemEntryPtr from the path to a directory.
+ // Assumes the passed in path is valid and represents a directory.
+ blink::mojom::NativeFileSystemEntryPtr CreateDirectoryEntryFromPath(
+ const BindingContext& binding_context,
+ const base::FilePath& directory_path);
+
+ // Create a transfer token for a specific file or directory.
+ void CreateTransferToken(
+ const NativeFileSystemFileHandleImpl& file,
+ blink::mojom::NativeFileSystemTransferTokenRequest request);
+ void CreateTransferToken(
+ const NativeFileSystemDirectoryHandleImpl& directory,
+ blink::mojom::NativeFileSystemTransferTokenRequest request);
+
+ // Given a mojom transfer token, looks up the token in our internal list of
+ // valid tokens. Calls the callback with the found token, or nullptr if no
+ // valid token was found.
+ using ResolvedTokenCallback =
+ base::OnceCallback<void(NativeFileSystemTransferTokenImpl*)>;
+ void ResolveTransferToken(
+ blink::mojom::NativeFileSystemTransferTokenPtr token,
+ ResolvedTokenCallback callback);
+
+ storage::FileSystemContext* context() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return context_.get();
+ }
+ storage::BlobStorageContext* blob_context() {
+ return blob_context_->context();
+ }
+ storage::FileSystemOperationRunner* operation_runner();
+
+ private:
+ friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
+ friend class base::DeleteHelper<NativeFileSystemManagerImpl>;
+ ~NativeFileSystemManagerImpl() override;
+
+ void DidOpenSandboxedFileSystem(const BindingContext& binding_context,
+ GetSandboxedFileSystemCallback callback,
+ const GURL& root,
+ const std::string& filesystem_name,
+ base::File::Error result);
+
+ void DidChooseEntries(const BindingContext& binding_context,
+ blink::mojom::ChooseFileSystemEntryType type,
+ ChooseEntriesCallback callback,
+ blink::mojom::NativeFileSystemErrorPtr result,
+ std::vector<base::FilePath> entries);
+
+ void CreateTransferTokenImpl(
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system,
+ bool is_directory,
+ blink::mojom::NativeFileSystemTransferTokenRequest request);
+ void TransferTokenConnectionErrorHandler(const base::UnguessableToken& token);
+ void DoResolveTransferToken(blink::mojom::NativeFileSystemTransferTokenPtr,
+ ResolvedTokenCallback callback,
+ const base::UnguessableToken& token);
+
+ // Creates a FileSystemURL which corresponds to a FilePath and Origin.
+ struct FileSystemURLAndFSHandle {
+ storage::FileSystemURL url;
+ std::string base_name;
+ storage::IsolatedContext::ScopedFSHandle file_system;
+ };
+ FileSystemURLAndFSHandle CreateFileSystemURLFromPath(
+ const url::Origin& origin,
+ const base::FilePath& path);
+
+ const scoped_refptr<storage::FileSystemContext> context_;
+ const scoped_refptr<ChromeBlobStorageContext> blob_context_;
+ std::unique_ptr<storage::FileSystemOperationRunner> operation_runner_;
+
+ // All the mojo bindings for this NativeFileSystemManager itself. Keeps track
+ // of associated origin and other state as well to not have to rely on the
+ // renderer passing that in, and to be able to do security checks around
+ // transferability etc.
+ mojo::BindingSet<blink::mojom::NativeFileSystemManager, BindingContext>
+ bindings_;
+
+ // All the bindings for file and directory handles that have references to
+ // them.
+ mojo::StrongBindingSet<blink::mojom::NativeFileSystemFileHandle>
+ file_bindings_;
+ mojo::StrongBindingSet<blink::mojom::NativeFileSystemDirectoryHandle>
+ directory_bindings_;
+
+ // Transfer token bindings are stored in what is effectively a
+ // StrongBindingMap. The Binding instances own the implementation, and tokens
+ // are removed from this map when the mojo connection is closed.
+ using TransferTokenBinding =
+ mojo::Binding<blink::mojom::NativeFileSystemTransferToken,
+ mojo::UniquePtrImplRefTraits<
+ blink::mojom::NativeFileSystemTransferToken>>;
+ std::map<base::UnguessableToken, TransferTokenBinding> transfer_tokens_;
+
+ base::WeakPtrFactory<NativeFileSystemManagerImpl> weak_factory_{this};
+ DISALLOW_COPY_AND_ASSIGN(NativeFileSystemManagerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_MANAGER_IMPL_H_
diff --git a/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.cc b/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.cc
new file mode 100644
index 00000000000..1fe718c22bc
--- /dev/null
+++ b/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.cc
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/native_file_system/native_file_system_transfer_token_impl.h"
+
+namespace content {
+
+NativeFileSystemTransferTokenImpl::NativeFileSystemTransferTokenImpl(
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system,
+ HandleType type)
+ : token_(base::UnguessableToken::Create()),
+ url_(url),
+ file_system_(std::move(file_system)),
+ type_(type) {
+ DCHECK_EQ(url_.mount_type() == storage::kFileSystemTypeIsolated,
+ file_system_.is_valid())
+ << url_.mount_type();
+}
+
+void NativeFileSystemTransferTokenImpl::GetInternalID(
+ GetInternalIDCallback callback) {
+ std::move(callback).Run(token_);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.h b/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.h
new file mode 100644
index 00000000000..473d60f03b6
--- /dev/null
+++ b/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.h
@@ -0,0 +1,47 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_TRANSFER_TOKEN_IMPL_H_
+#define CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_TRANSFER_TOKEN_IMPL_H_
+
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_transfer_token.mojom.h"
+
+namespace content {
+
+// This is the browser side implementation of the NativeFileSystemTransferToken
+// mojom interface.
+//
+// Instances of this class are immutable, but since this implements a mojo
+// interface all its methods are called on the same sequence anyway.
+class NativeFileSystemTransferTokenImpl
+ : public blink::mojom::NativeFileSystemTransferToken {
+ public:
+ enum class HandleType { kFile, kDirectory };
+
+ NativeFileSystemTransferTokenImpl(
+ const storage::FileSystemURL& url,
+ storage::IsolatedContext::ScopedFSHandle file_system,
+ HandleType type);
+
+ const base::UnguessableToken& token() const { return token_; }
+ const storage::FileSystemURL& url() const { return url_; }
+ HandleType type() const { return type_; }
+
+ // blink::mojom::NativeFileSystemTransferToken:
+ void GetInternalID(GetInternalIDCallback callback) override;
+
+ private:
+ const base::UnguessableToken token_;
+ const storage::FileSystemURL url_;
+ const storage::IsolatedContext::ScopedFSHandle file_system_;
+ const HandleType type_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeFileSystemTransferTokenImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_TRANSFER_TOKEN_IMPL_H_
diff --git a/chromium/content/browser/navigation_browsertest.cc b/chromium/content/browser/navigation_browsertest.cc
index 93ce013e719..d76074bbcab 100644
--- a/chromium/content/browser/navigation_browsertest.cc
+++ b/chromium/content/browser/navigation_browsertest.cc
@@ -236,10 +236,12 @@ class NavigationBrowserTest : public NavigationBaseBrowserTest {
base::RunLoop run_loop;
base::OnceClosure quit_closure = run_loop.QuitClosure();
+ base::Lock lock;
// Intercept network requests and record them.
URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
[&](URLLoaderInterceptor::RequestParams* params) -> bool {
+ base::AutoLock top_frame_origins_lock(lock);
(*top_frame_origins)[params->url_request.url] =
*params->url_request.top_frame_origin;
@@ -663,14 +665,19 @@ IN_PROC_BROWSER_TEST_F(NavigationDisableWebSecurityTest,
base::TimeTicks::Now() /* navigation_start */, "GET",
nullptr /* post_data */, base::Optional<SourceLocation>(),
false /* started_from_context_menu */, false /* has_user_gesture */,
- InitiatorCSPInfo(), std::string() /* href_translate */);
+ InitiatorCSPInfo(),
+ std::vector<int>() /* initiator_origin_trial_features */,
+ std::string() /* href_translate */,
+ false /* is_history_navigation_in_new_child_frame */);
mojom::BeginNavigationParamsPtr begin_params =
mojom::BeginNavigationParams::New(
std::string() /* headers */, net::LOAD_NORMAL,
false /* skip_service_worker */,
blink::mojom::RequestContextType::LOCATION,
blink::WebMixedContentContextType::kBlockable,
- false /* is_form_submission */, GURL() /* searchable_form_url */,
+ false /* is_form_submission */,
+ false /* was_initiated_by_link_click */,
+ GURL() /* searchable_form_url */,
std::string() /* searchable_form_encoding */,
GURL() /* client_side_redirect_url */,
base::nullopt /* devtools_initiator_info */);
@@ -785,8 +792,9 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, BrowserNavigationTopFrameOrigin) {
std::map<GURL, url::Origin> top_frame_origins;
GURL url(embedded_test_server()->GetURL("/title1.html"));
- NavigateAndRecordTopFrameOrigins(url, url /*final_resource*/,
- false /*from_renderer*/, &top_frame_origins);
+ NavigateAndRecordTopFrameOrigins(url, url /* final_resource */,
+ false /* from_renderer */,
+ &top_frame_origins);
EXPECT_EQ(url::Origin::Create(url), top_frame_origins[url]);
}
@@ -794,8 +802,9 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, RenderNavigationTopFrameOrigin) {
std::map<GURL, url::Origin> top_frame_origins;
GURL url(embedded_test_server()->GetURL("/title2.html"));
- NavigateAndRecordTopFrameOrigins(url, url /*final_resource*/,
- true /*from_renderer*/, &top_frame_origins);
+ NavigateAndRecordTopFrameOrigins(url, url /* final_resource */,
+ true /* from_renderer */,
+ &top_frame_origins);
EXPECT_EQ(url::Origin::Create(url), top_frame_origins[url]);
}
@@ -804,8 +813,9 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SubframeTopFrameOrigin) {
GURL url(embedded_test_server()->GetURL("/page_with_iframe.html"));
GURL iframe_document = embedded_test_server()->GetURL("/title1.html");
- NavigateAndRecordTopFrameOrigins(url, iframe_document /*final_resource*/,
- false /*from_renderer*/, &top_frame_origins);
+ NavigateAndRecordTopFrameOrigins(url, iframe_document /* final_resource */,
+ false /* from_renderer */,
+ &top_frame_origins);
EXPECT_EQ(url::Origin::Create(url), top_frame_origins[url]);
EXPECT_EQ(url::Origin::Create(url), top_frame_origins[iframe_document]);
}
@@ -815,14 +825,167 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SubresourceTopFrameOrigin) {
GURL url(embedded_test_server()->GetURL("/page_with_iframe_and_image.html"));
GURL blank_image = embedded_test_server()->GetURL("/blank.jpg");
- NavigateAndRecordTopFrameOrigins(url, blank_image /*final_resource*/,
- false /*from_renderer*/, &top_frame_origins);
+ NavigateAndRecordTopFrameOrigins(url, blank_image /* final_resource */,
+ false /* from_renderer */,
+ &top_frame_origins);
EXPECT_EQ(url::Origin::Create(url), top_frame_origins[url]);
EXPECT_EQ(url::Origin::Create(url),
top_frame_origins[embedded_test_server()->GetURL("/image.jpg")]);
EXPECT_EQ(url::Origin::Create(url), top_frame_origins[blank_image]);
}
+// Helper class to extract the initiator values from URLLoaderFactory calls
+class InitiatorInterceptor {
+ public:
+ explicit InitiatorInterceptor(const GURL& final_url) {
+ // Intercept network requests and record them.
+ interceptor_ =
+ std::make_unique<URLLoaderInterceptor>(base::BindLambdaForTesting(
+ [&final_url,
+ this](URLLoaderInterceptor::RequestParams* params) -> bool {
+ base::AutoLock initiators_lock(lock_);
+ (initiators_)[params->url_request.url] =
+ params->url_request.request_initiator;
+
+ if (params->url_request.url == final_url)
+ std::move(run_loop_.QuitClosure()).Run();
+ return false;
+ }));
+ }
+
+ void Run() {
+ // Wait until the last resource we care about has been requested.
+ run_loop_.Run();
+ }
+
+ // This method should be used only if the key already exists in the map.
+ const base::Optional<url::Origin>& GetInitiatorForURL(const GURL& url) const {
+ auto initiator_iterator = initiators_.find(url);
+ DCHECK(initiator_iterator != initiators_.end());
+
+ return initiator_iterator->second;
+ }
+
+ private:
+ std::map<GURL, base::Optional<url::Origin>> initiators_;
+ std::unique_ptr<URLLoaderInterceptor> interceptor_;
+ base::Lock lock_;
+ base::RunLoop run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(InitiatorInterceptor);
+};
+
+// Tests that the initiator is not set for a browser initiated top frame
+// navigation.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, BrowserNavigationInitiator) {
+ GURL url(embedded_test_server()->GetURL("/title1.html"));
+
+ InitiatorInterceptor test_interceptor(url);
+
+ // Perform the actual navigation.
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ test_interceptor.Run();
+
+ ASSERT_FALSE(test_interceptor.GetInitiatorForURL(url).has_value());
+}
+
+// Test that the initiator is set to the starting page when a renderer initiated
+// navigation goes from the starting page to another page.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, RendererNavigationInitiator) {
+ GURL starting_page(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ url::Origin starting_page_origin;
+ starting_page_origin = starting_page_origin.Create(starting_page);
+
+ NavigateToURL(shell(), starting_page);
+
+ GURL url(embedded_test_server()->GetURL("/title2.html"));
+
+ InitiatorInterceptor test_interceptor(url);
+
+ // Perform the actual navigation.
+ EXPECT_TRUE(NavigateToURLFromRenderer(shell(), url));
+ test_interceptor.Run();
+
+ EXPECT_EQ(starting_page_origin, test_interceptor.GetInitiatorForURL(url));
+}
+
+// Test that the initiator is set to the starting page when a sub frame is
+// navigated by Javascript from some starting page to another page.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SubFrameJsNavigationInitiator) {
+ GURL starting_page(embedded_test_server()->GetURL("/frame_tree/top.html"));
+ NavigateToURL(shell(), starting_page);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // The root and subframe should each have a live RenderFrame.
+ EXPECT_TRUE(
+ root->current_frame_host()->render_view_host()->IsRenderViewLive());
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+
+ GURL url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+
+ InitiatorInterceptor test_interceptor(url);
+ std::string script = "location.href='" + url.spec() + "'";
+
+ // Perform the actual navigation.
+ EXPECT_TRUE(ExecJs(root->child_at(0)->current_frame_host(), script));
+ test_interceptor.Run();
+
+ EXPECT_TRUE(
+ root->current_frame_host()->render_view_host()->IsRenderViewLive());
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+
+ url::Origin starting_page_origin;
+ starting_page_origin = starting_page_origin.Create(starting_page);
+
+ EXPECT_EQ(starting_page_origin, test_interceptor.GetInitiatorForURL(url));
+}
+
+// Test that the initiator is set to the starting page when a sub frame,
+// selected by Id, is navigated by Javascript from some starting page to another
+// page.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
+ SubframeNavigationByTopFrameInitiator) {
+ // Go to a page on a.com with an iframe that is on b.com
+ GURL starting_page(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ NavigateToURL(shell(), starting_page);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // The root and subframe should each have a live RenderFrame.
+ EXPECT_TRUE(
+ root->current_frame_host()->render_view_host()->IsRenderViewLive());
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+
+ GURL url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+
+ InitiatorInterceptor test_interceptor(url);
+
+ // Perform the actual navigation.
+ NavigateIframeToURL(shell()->web_contents(), "child-0", url);
+ test_interceptor.Run();
+
+ EXPECT_TRUE(
+ root->current_frame_host()->render_view_host()->IsRenderViewLive());
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+
+ url::Origin starting_page_origin;
+ starting_page_origin = starting_page_origin.Create(starting_page);
+
+ EXPECT_EQ(starting_page_origin, test_interceptor.GetInitiatorForURL(url));
+}
+
// Navigation are started in the browser process. After the headers are
// received, the URLLoaderClient is transferred from the browser process to the
// renderer process. This test ensures that when the the URLLoader is deleted
@@ -1770,7 +1933,7 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, WebViewRendererKillReload) {
notification_registrar.Add(&crash_observer,
content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
content::NotificationService::AllSources());
- NavigateToURLBlockUntilNavigationsComplete(web_contents, GURL("chrome:crash"),
+ NavigateToURLBlockUntilNavigationsComplete(web_contents, GetWebUIURL("crash"),
1);
// Wait for navigation in new WebContents to finish.
diff --git a/chromium/content/common/navigation_subresource_loader_params.cc b/chromium/content/browser/navigation_subresource_loader_params.cc
index 279d0559857..67223dbb98b 100644
--- a/chromium/content/common/navigation_subresource_loader_params.cc
+++ b/chromium/content/browser/navigation_subresource_loader_params.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/common/navigation_subresource_loader_params.h"
+#include "content/browser/navigation_subresource_loader_params.h"
namespace content {
@@ -21,6 +21,7 @@ SubresourceLoaderParams& SubresourceLoaderParams::operator=(
std::move(other.controller_service_worker_info);
controller_service_worker_object_host =
other.controller_service_worker_object_host;
+ prefetched_signed_exchanges = std::move(other.prefetched_signed_exchanges);
return *this;
}
diff --git a/chromium/content/common/navigation_subresource_loader_params.h b/chromium/content/browser/navigation_subresource_loader_params.h
index 66486a5d204..7011f3bdedd 100644
--- a/chromium/content/common/navigation_subresource_loader_params.h
+++ b/chromium/content/browser/navigation_subresource_loader_params.h
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_NAVIGATION_SUBRESOURCE_LOADER_PARAMS_H_
-#define CONTENT_COMMON_NAVIGATION_SUBRESOURCE_LOADER_PARAMS_H_
+#ifndef CONTENT_BROWSER_NAVIGATION_SUBRESOURCE_LOADER_PARAMS_H_
+#define CONTENT_BROWSER_NAVIGATION_SUBRESOURCE_LOADER_PARAMS_H_
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
+#include "content/common/prefetched_signed_exchange_info.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
@@ -41,8 +42,16 @@ struct CONTENT_EXPORT SubresourceLoaderParams {
// ServiceWorkerObjectHost::CreateIncompleteObjectInfo() for details.
blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info;
base::WeakPtr<ServiceWorkerObjectHost> controller_service_worker_object_host;
+
+ // For SignedExchangeSubresourcePrefetch.
+ // When signed exchanges were prefetched in the previous page and were stored
+ // to the PrefetchedSignedExchangeCache, and the main resource for the
+ // navigation was served from the cache, |prefetched_signed_exchanges|
+ // contains the all prefetched signed exchanges and they will be passed to the
+ // renderer.
+ std::vector<PrefetchedSignedExchangeInfo> prefetched_signed_exchanges;
};
} // namespace content
-#endif // CONTENT_COMMON_NAVIGATION_SUBRESOURCE_LOADER_PARAMS_H_
+#endif // CONTENT_BROWSER_NAVIGATION_SUBRESOURCE_LOADER_PARAMS_H_
diff --git a/chromium/content/browser/net/accept_header_browsertest.cc b/chromium/content/browser/net/accept_header_browsertest.cc
index f89d6e7728e..c4ab85ad880 100644
--- a/chromium/content/browser/net/accept_header_browsertest.cc
+++ b/chromium/content/browser/net/accept_header_browsertest.cc
@@ -165,9 +165,13 @@ IN_PROC_BROWSER_TEST_F(AcceptHeaderTest, Check) {
IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, PluginAcceptHeader) {
net::EmbeddedTestServer server(net::EmbeddedTestServer::TYPE_HTTP);
server.ServeFilesFromSourceDirectory("ppapi/tests");
+ base::Lock plugin_accept_header_lock;
std::string plugin_accept_header;
server.RegisterRequestMonitor(base::BindLambdaForTesting(
[&](const net::test_server::HttpRequest& request) {
+ // Note this callback runs on the EmbeddedTestServer's background
+ // thread.
+ base::AutoLock lock(plugin_accept_header_lock);
if (request.relative_url == "/test_url_loader_data/hello.txt") {
auto it = request.headers.find("Accept");
if (it != request.headers.end())
@@ -179,7 +183,10 @@ IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, PluginAcceptHeader) {
RunTestURL(
server.GetURL(BuildQuery("/test_case.html?", "URLLoader_BasicGET")));
- ASSERT_EQ("*/*", plugin_accept_header);
+ {
+ base::AutoLock lock(plugin_accept_header_lock);
+ ASSERT_EQ("*/*", plugin_accept_header);
+ }
// Since the server uses local variables.
ASSERT_TRUE(server.ShutdownAndWaitUntilComplete());
diff --git a/chromium/content/browser/net/quota_policy_cookie_store.cc b/chromium/content/browser/net/quota_policy_cookie_store.cc
index ef27c43c53f..85a9fec85cd 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store.cc
+++ b/chromium/content/browser/net/quota_policy_cookie_store.cc
@@ -44,8 +44,7 @@ QuotaPolicyCookieStore::~QuotaPolicyCookieStore() {
CookieStoreConfig::CookieStoreConfig()
: restore_old_session_cookies(false),
persist_session_cookies(false),
- crypto_delegate(nullptr),
- channel_id_service(nullptr) {
+ crypto_delegate(nullptr) {
// Default to an in-memory cookie store.
}
@@ -58,8 +57,7 @@ CookieStoreConfig::CookieStoreConfig(
restore_old_session_cookies(restore_old_session_cookies),
persist_session_cookies(persist_session_cookies),
storage_policy(storage_policy),
- crypto_delegate(nullptr),
- channel_id_service(nullptr) {
+ crypto_delegate(nullptr) {
CHECK(!path.empty() ||
(!restore_old_session_cookies && !persist_session_cookies));
}
diff --git a/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc b/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
index 8d4e5d3670c..eda510f18b4 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
+++ b/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
@@ -98,7 +98,7 @@ class QuotaPolicyCookieStoreTest : public testing::Test {
void DestroyStore() {
store_ = nullptr;
// Ensure that |store_|'s destructor has run by flushing ThreadPool.
- base::ThreadPool::GetInstance()->FlushForTesting();
+ base::ThreadPoolInstance::Get()->FlushForTesting();
}
void SetUp() override {
diff --git a/chromium/content/browser/net/reporting_service_proxy.cc b/chromium/content/browser/net/reporting_service_proxy.cc
index a2523069ed1..38b403759c1 100644
--- a/chromium/content/browser/net/reporting_service_proxy.cc
+++ b/chromium/content/browser/net/reporting_service_proxy.cc
@@ -36,11 +36,13 @@ class ReportingServiceProxyImpl : public blink::mojom::ReportingServiceProxy {
// blink::mojom::ReportingServiceProxy:
void QueueInterventionReport(const GURL& url,
+ const std::string& id,
const std::string& message,
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);
body->SetString("message", message);
if (source_file)
body->SetString("sourceFile", *source_file);
@@ -74,36 +76,36 @@ class ReportingServiceProxyImpl : public blink::mojom::ReportingServiceProxy {
void QueueCspViolationReport(const GURL& url,
const std::string& group,
- const std::string& document_uri,
- const std::string& referrer,
- const std::string& violated_directive,
+ const std::string& document_url,
+ const base::Optional<std::string>& referrer,
+ const base::Optional<std::string>& blocked_url,
const std::string& effective_directive,
const std::string& original_policy,
- const std::string& disposition,
- const std::string& blocked_uri,
- int line_number,
- int column_number,
const base::Optional<std::string>& source_file,
+ const base::Optional<std::string>& script_sample,
+ const std::string& disposition,
uint16_t status_code,
- const std::string& script_sample) override {
+ int line_number,
+ int column_number) override {
auto body = std::make_unique<base::DictionaryValue>();
- body->SetString("document-uri", document_uri);
- body->SetString("referrer", referrer);
- body->SetString("violated-directive", violated_directive);
- body->SetString("effective-directive", effective_directive);
- body->SetString("original-policy", original_policy);
+ body->SetString("documentURL", document_url);
+ if (referrer)
+ body->SetString("referrer", *referrer);
+ if (blocked_url)
+ body->SetString("blockedURL", *blocked_url);
+ body->SetString("effectiveDirective", effective_directive);
+ body->SetString("originalPolicy", original_policy);
+ if (source_file)
+ body->SetString("sourceFile", *source_file);
+ if (script_sample)
+ body->SetString("sample", *script_sample);
body->SetString("disposition", disposition);
- body->SetString("blocked-uri", blocked_uri);
+ body->SetInteger("statusCode", status_code);
if (line_number)
- body->SetInteger("line-number", line_number);
+ body->SetInteger("lineNumber", line_number);
if (column_number)
- body->SetInteger("column-number", column_number);
- if (source_file)
- body->SetString("sourceFile", *source_file);
- if (status_code)
- body->SetInteger("status-code", status_code);
- body->SetString("script-sample", script_sample);
- QueueReport(url, group, "csp", std::move(body));
+ body->SetInteger("columnNumber", column_number);
+ QueueReport(url, group, "csp-violation", std::move(body));
}
void QueueFeaturePolicyViolationReport(
diff --git a/chromium/content/browser/network_service_browsertest.cc b/chromium/content/browser/network_service_browsertest.cc
index 0789ba39a56..1693e74f328 100644
--- a/chromium/content/browser/network_service_browsertest.cc
+++ b/chromium/content/browser/network_service_browsertest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/bind.h"
+#include "base/files/file_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
@@ -214,7 +215,7 @@ class NetworkServiceBrowserTest : public ContentBrowserTest {
// Verifies that WebUI pages with WebUI bindings can't make network requests.
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest, WebUIBindingsNoHttp) {
- GURL test_url("chrome://webui/");
+ GURL test_url(GetWebUIURL("webui/"));
NavigateToURL(shell(), test_url);
RenderProcessKilledObserver killed_observer(shell()->web_contents());
ASSERT_FALSE(CheckCanLoadHttp());
@@ -224,7 +225,7 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest, WebUIBindingsNoHttp) {
// Verifies that WebUI pages without WebUI bindings can make network requests.
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest, NoWebUIBindingsHttp) {
- GURL test_url("chrome://webui/nobinding/");
+ GURL test_url(GetWebUIURL("webui/nobinding/"));
NavigateToURL(shell(), test_url);
ASSERT_TRUE(CheckCanLoadHttp());
}
@@ -233,7 +234,7 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest, NoWebUIBindingsHttp) {
// ChildProcessSecurityPolicyImpl::CanRequestURL is properly rejected.
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest,
FileSystemBindingsCorrectOrigin) {
- GURL test_url("chrome://webui/nobinding/");
+ GURL test_url(GetWebUIURL("webui/nobinding/"));
NavigateToURL(shell(), test_url);
// Note: must be filesystem scheme (obviously).
diff --git a/chromium/content/browser/network_service_client.cc b/chromium/content/browser/network_service_client.cc
index 8978b4628ff..90ffdf4a0ab 100644
--- a/chromium/content/browser/network_service_client.cc
+++ b/chromium/content/browser/network_service_client.cc
@@ -4,18 +4,23 @@
#include "content/browser/network_service_client.h"
+#include <utility>
+
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/optional.h"
#include "base/task/post_task.h"
+#include "base/threading/sequence_bound.h"
#include "base/unguessable_token.h"
#include "content/browser/browsing_data/clear_site_data_handler.h"
#include "content/browser/devtools/devtools_url_loader_interceptor.h"
+#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/ssl/ssl_client_auth_handler.h"
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/browser/ssl/ssl_manager.h"
#include "content/browser/ssl_private_key_impl.h"
-#include "content/browser/web_contents/web_contents_getter_registry.h"
+#include "content/browser/web_contents/frame_tree_node_id_registry.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
@@ -25,12 +30,15 @@
#include "content/public/browser/login_delegate.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/resource_request_info.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/network_service_util.h"
#include "content/public/common/resource_type.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "net/cookies/cookie_util.h"
#include "net/http/http_auth_preferences.h"
#include "net/ssl/client_cert_store.h"
#include "services/network/public/mojom/network_context.mojom.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
#if defined(OS_ANDROID)
#include "base/android/content_uri_utils.h"
@@ -64,107 +72,67 @@ class SSLErrorDelegate : public SSLErrorHandler::Delegate {
base::WeakPtrFactory<SSLErrorDelegate> weak_factory_;
};
-// This class is created on UI thread, and deleted by
-// BrowserThread::DeleteSoon() after the |callback_| runs. The |callback_|
-// needs to run on UI thread since it is called through the
-// NetworkServiceClient interface.
-//
-// The |ssl_client_auth_handler_| needs to be created on IO thread, and deleted
-// on the same thread by posting a BrowserThread::DeleteSoon() task to IO
-// thread.
-//
-// ContinueWithCertificate() and CancelCertificateSelection() run on IO thread.
+// This class lives on the IO thread. It is self-owned and will delete itself
+// after any of the SSLClientAuthHandler::Delegate methods are invoked (or when
+// a mojo connection error occurs).
class SSLClientAuthDelegate : public SSLClientAuthHandler::Delegate {
public:
SSLClientAuthDelegate(
- network::mojom::NetworkServiceClient::OnCertificateRequestedCallback
- callback,
+ network::mojom::ClientCertificateResponderPtrInfo
+ client_cert_responder_info,
+ content::ResourceContext* resource_context,
ResourceRequestInfo::WebContentsGetter web_contents_getter,
- scoped_refptr<net::SSLCertRequestInfo> cert_info)
- : callback_(std::move(callback)), cert_info_(std::move(cert_info)) {
- content::WebContents* web_contents = web_contents_getter.Run();
- content::BrowserContext* browser_context =
- web_contents->GetBrowserContext();
- content::ResourceContext* resource_context =
- browser_context->GetResourceContext();
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&SSLClientAuthDelegate::CreateSSLClientAuthHandler,
- base::Unretained(this), resource_context,
- web_contents_getter));
+ const scoped_refptr<net::SSLCertRequestInfo>& cert_info)
+ : client_cert_responder_(std::move(client_cert_responder_info)),
+ ssl_client_auth_handler_(std::make_unique<SSLClientAuthHandler>(
+ GetContentClient()->browser()->CreateClientCertStore(
+ resource_context),
+ std::move(web_contents_getter),
+ std::move(cert_info.get()),
+ this)) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(client_cert_responder_);
+ ssl_client_auth_handler_->SelectCertificate();
+ client_cert_responder_.set_connection_error_handler(base::BindOnce(
+ &SSLClientAuthDelegate::DeleteSelf, base::Unretained(this)));
+ }
+
+ ~SSLClientAuthDelegate() override { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
+
+ void DeleteSelf() { delete this; }
+
+ // SSLClientAuthHandler::Delegate:
+ void CancelCertificateSelection() override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ client_cert_responder_->CancelRequest();
+ DeleteSelf();
}
- ~SSLClientAuthDelegate() override {}
// SSLClientAuthHandler::Delegate:
void ContinueWithCertificate(
scoped_refptr<net::X509Certificate> cert,
scoped_refptr<net::SSLPrivateKey> private_key) override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
DCHECK((cert && private_key) || (!cert && !private_key));
- std::string provider_name;
- std::vector<uint16_t> algorithm_preferences;
- network::mojom::SSLPrivateKeyPtr ssl_private_key;
- auto ssl_private_key_request = mojo::MakeRequest(&ssl_private_key);
-
- if (private_key) {
- provider_name = private_key->GetProviderName();
- algorithm_preferences = private_key->GetAlgorithmPreferences();
- mojo::MakeStrongBinding(
- std::make_unique<SSLPrivateKeyImpl>(std::move(private_key)),
- std::move(ssl_private_key_request));
- }
+ if (cert && private_key) {
+ network::mojom::SSLPrivateKeyPtr ssl_private_key;
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&SSLClientAuthDelegate::RunCallback,
- base::Unretained(this), cert, std::move(provider_name),
- std::move(algorithm_preferences),
- std::move(ssl_private_key),
- false /* cancel_certificate_selection */));
- }
+ mojo::MakeStrongBinding(std::make_unique<SSLPrivateKeyImpl>(private_key),
+ mojo::MakeRequest(&ssl_private_key));
- // SSLClientAuthHandler::Delegate:
- void CancelCertificateSelection() override {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- network::mojom::SSLPrivateKeyPtr ssl_private_key;
- mojo::MakeRequest(&ssl_private_key);
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&SSLClientAuthDelegate::RunCallback,
- base::Unretained(this), nullptr, std::string(),
- std::vector<uint16_t>(), std::move(ssl_private_key),
- true /* cancel_certificate_selection */));
- }
+ client_cert_responder_->ContinueWithCertificate(
+ cert, private_key->GetProviderName(),
+ private_key->GetAlgorithmPreferences(), std::move(ssl_private_key));
+ } else {
+ client_cert_responder_->ContinueWithoutCertificate();
+ }
- void RunCallback(scoped_refptr<net::X509Certificate> cert,
- std::string provider_name,
- std::vector<uint16_t> algorithm_preferences,
- network::mojom::SSLPrivateKeyPtr ssl_private_key,
- bool cancel_certificate_selection) {
- std::move(callback_).Run(cert, provider_name, algorithm_preferences,
- std::move(ssl_private_key),
- cancel_certificate_selection);
- BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, this);
+ DeleteSelf();
}
private:
- void CreateSSLClientAuthHandler(
- content::ResourceContext* resource_context,
- ResourceRequestInfo::WebContentsGetter web_contents_getter) {
- std::unique_ptr<net::ClientCertStore> client_cert_store =
- GetContentClient()->browser()->CreateClientCertStore(resource_context);
- ssl_client_auth_handler_.reset(new SSLClientAuthHandler(
- std::move(client_cert_store), std::move(web_contents_getter),
- cert_info_.get(), this));
- ssl_client_auth_handler_->SelectCertificate();
- }
-
- network::mojom::NetworkServiceClient::OnCertificateRequestedCallback
- callback_;
- scoped_refptr<net::SSLCertRequestInfo> cert_info_;
+ network::mojom::ClientCertificateResponderPtr client_cert_responder_;
std::unique_ptr<SSLClientAuthHandler> ssl_client_auth_handler_;
};
@@ -324,7 +292,8 @@ void HandleFileUploadRequest(
base::RepeatingCallback<WebContents*(void)> GetWebContentsFromRegistry(
const base::UnguessableToken& window_id) {
- return WebContentsGetterRegistry::GetInstance()->Get(window_id);
+ return FrameTreeNodeIdRegistry::GetInstance()->GetWebContentsGetter(
+ window_id);
}
WebContents* GetWebContents(int process_id, int routing_id) {
@@ -334,18 +303,24 @@ WebContents* GetWebContents(int process_id, int routing_id) {
return WebContents::FromFrameTreeNodeId(routing_id);
}
-BrowserContext* GetBrowserContextFromIds(int process_id, int routing_id) {
- WebContents* web_contents = GetWebContents(process_id, routing_id);
- if (web_contents)
- return web_contents->GetBrowserContext();
- // Some requests such as service worker updates are not associated with
- // a WebContents so we can't use it to obtain the BrowserContext.
- // TODO(dullweber): Could we always use RenderProcessHost?
- RenderProcessHost* process_host = RenderProcessHostImpl::FromID(process_id);
- if (process_host)
- return process_host->GetBrowserContext();
-
- return nullptr;
+bool IsMainFrameRequest(int process_id, int routing_id) {
+ if (process_id != network::mojom::kBrowserProcessId)
+ return false;
+
+ auto* frame_tree_node = FrameTreeNode::GloballyFindByID(routing_id);
+ return frame_tree_node && frame_tree_node->IsMainFrame();
+}
+
+void CreateSSLClientAuthDelegateOnIO(
+ network::mojom::ClientCertificateResponderPtrInfo
+ client_cert_responder_info,
+ content::ResourceContext* resource_context,
+ ResourceRequestInfo::WebContentsGetter web_contents_getter,
+ scoped_refptr<net::SSLCertRequestInfo> cert_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ new SSLClientAuthDelegate(std::move(client_cert_responder_info),
+ resource_context, std::move(web_contents_getter),
+ cert_info); // deletes self
}
void OnCertificateRequestedContinuation(
@@ -353,23 +328,28 @@ void OnCertificateRequestedContinuation(
uint32_t routing_id,
uint32_t request_id,
const scoped_refptr<net::SSLCertRequestInfo>& cert_info,
- network::mojom::NetworkServiceClient::OnCertificateRequestedCallback
- callback,
+ network::mojom::ClientCertificateResponderPtrInfo
+ client_cert_responder_info,
base::RepeatingCallback<WebContents*(void)> web_contents_getter) {
if (!web_contents_getter) {
web_contents_getter =
base::BindRepeating(GetWebContents, process_id, routing_id);
}
- if (!web_contents_getter.Run()) {
- network::mojom::SSLPrivateKeyPtr ssl_private_key;
- mojo::MakeRequest(&ssl_private_key);
- std::move(callback).Run(nullptr, std::string(), std::vector<uint16_t>(),
- std::move(ssl_private_key),
- true /* cancel_certificate_selection */);
+ WebContents* web_contents = web_contents_getter.Run();
+ if (!web_contents) {
+ DCHECK(client_cert_responder_info);
+ network::mojom::ClientCertificateResponderPtr client_cert_responder(
+ std::move(client_cert_responder_info));
+ client_cert_responder->CancelRequest();
return;
}
- new SSLClientAuthDelegate(std::move(callback), std::move(web_contents_getter),
- cert_info); // deletes self
+
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&CreateSSLClientAuthDelegateOnIO,
+ std::move(client_cert_responder_info),
+ web_contents->GetBrowserContext()->GetResourceContext(),
+ std::move(web_contents_getter), cert_info));
}
#if defined(OS_ANDROID)
@@ -383,6 +363,82 @@ void FinishGenerateNegotiateAuthToken(
}
#endif
+// TODO(crbug.com/977040): Remove when no longer needed.
+void DeprecateSameSiteCookies(int process_id,
+ int routing_id,
+ const net::CookieStatusList& excluded_cookies) {
+ // Navigation requests start in the browser, before process_id is assigned, so
+ // the id is set to network::mojom::kBrowserProcessId. In these situations,
+ // the routing_id is the frame tree node id, and can be used directly.
+ RenderFrameHostImpl* frame = nullptr;
+ if (process_id == network::mojom::kBrowserProcessId) {
+ FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(routing_id);
+ if (ftn)
+ frame = ftn->current_frame_host();
+ } else {
+ frame = RenderFrameHostImpl::FromID(process_id, routing_id);
+ }
+
+ if (!frame)
+ return;
+
+ // Because of the nature of mojo and calling cross process, there's the
+ // possibility of calling this method after the page has already been
+ // navigated away from, which is DCHECKed against in
+ // LogWebFeatureForCurrentPage. We're replicating the DCHECK here and
+ // returning early should this be the case.
+ WebContents* web_contents = WebContents::FromRenderFrameHost(frame);
+
+ // |web_contents| will be null on interstitial pages, which means the frame
+ // has been navigated away from and the function should return early.
+ if (!web_contents)
+ return;
+
+ RenderFrameHostImpl* root_frame_host = frame;
+ while (root_frame_host->GetParent() != nullptr)
+ root_frame_host = root_frame_host->GetParent();
+
+ if (root_frame_host != web_contents->GetMainFrame())
+ return;
+
+ bool samesite_treated_as_lax_cookies = false;
+ bool samesite_none_insecure_cookies = false;
+
+ bool emit_messages =
+ base::FeatureList::IsEnabled(features::kCookieDeprecationMessages);
+
+ for (const net::CookieWithStatus& excluded_cookie : excluded_cookies) {
+ std::string cookie_url =
+ net::cookie_util::CookieOriginToURL(excluded_cookie.cookie.Domain(),
+ excluded_cookie.cookie.IsSecure())
+ .possibly_invalid_spec();
+
+ if (excluded_cookie.status ==
+ net::CanonicalCookie::CookieInclusionStatus::
+ EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX) {
+ samesite_treated_as_lax_cookies = true;
+ }
+ if (excluded_cookie.status == net::CanonicalCookie::CookieInclusionStatus::
+ EXCLUDE_SAMESITE_NONE_INSECURE) {
+ samesite_none_insecure_cookies = true;
+ }
+ if (emit_messages) {
+ root_frame_host->AddSameSiteCookieDeprecationMessage(
+ cookie_url, excluded_cookie.status);
+ }
+ }
+
+ if (samesite_treated_as_lax_cookies) {
+ GetContentClient()->browser()->LogWebFeatureForCurrentPage(
+ frame, blink::mojom::WebFeature::kCookieNoSameSite);
+ }
+
+ if (samesite_none_insecure_cookies) {
+ GetContentClient()->browser()->LogWebFeatureForCurrentPage(
+ frame, blink::mojom::WebFeature::kCookieInsecureAndSameSiteNone);
+ }
+}
+
} // namespace
NetworkServiceClient::NetworkServiceClient(
@@ -430,13 +486,11 @@ void NetworkServiceClient::OnAuthRequired(
uint32_t routing_id,
uint32_t request_id,
const GURL& url,
- const GURL& site_for_cookies,
bool first_auth_attempt,
const 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 =
+ base::RepeatingCallback<WebContents*(void)> web_contents_getter =
base::BindRepeating(GetWebContents, process_id, routing_id);
if (!web_contents_getter.Run()) {
@@ -444,14 +498,7 @@ void NetworkServiceClient::OnAuthRequired(
return;
}
- if (ResourceDispatcherHostImpl::Get()->DoNotPromptForLogin(
- static_cast<ResourceType>(resource_type), url, site_for_cookies)) {
- std::move(auth_challenge_responder)->OnAuthCredentials(base::nullopt);
- return;
- }
-
- bool is_request_for_main_frame =
- static_cast<ResourceType>(resource_type) == ResourceType::kMainFrame;
+ bool is_request_for_main_frame = IsMainFrameRequest(process_id, routing_id);
new LoginHandlerDelegate(std::move(auth_challenge_responder),
std::move(web_contents_getter), auth_info,
is_request_for_main_frame, process_id, routing_id,
@@ -465,38 +512,39 @@ void NetworkServiceClient::OnCertificateRequested(
uint32_t routing_id,
uint32_t request_id,
const scoped_refptr<net::SSLCertRequestInfo>& cert_info,
- network::mojom::NetworkServiceClient::OnCertificateRequestedCallback
- callback) {
+ network::mojom::ClientCertificateResponderPtr cert_responder) {
// Use |window_id| if it's provided.
if (window_id) {
base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&GetWebContentsFromRegistry, *window_id),
base::BindOnce(&OnCertificateRequestedContinuation, process_id,
- routing_id, request_id, cert_info, std::move(callback)));
+ routing_id, request_id, cert_info,
+ cert_responder.PassInterface()));
return;
}
OnCertificateRequestedContinuation(process_id, routing_id, request_id,
- cert_info, std::move(callback), {});
+ cert_info, cert_responder.PassInterface(),
+ {});
}
void NetworkServiceClient::OnSSLCertificateError(
uint32_t process_id,
uint32_t routing_id,
- uint32_t request_id,
- int32_t resource_type,
const GURL& url,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal,
OnSSLCertificateErrorCallback response) {
SSLErrorDelegate* delegate =
new SSLErrorDelegate(std::move(response)); // deletes self
- base::Callback<WebContents*(void)> web_contents_getter =
+ base::RepeatingCallback<WebContents*(void)> web_contents_getter =
base::BindRepeating(GetWebContents, process_id, routing_id);
+ bool is_main_frame_request = IsMainFrameRequest(process_id, routing_id);
SSLManager::OnSSLCertificateError(
- delegate->GetWeakPtr(), static_cast<ResourceType>(resource_type), url,
- std::move(web_contents_getter), ssl_info, fatal);
+ delegate->GetWeakPtr(), is_main_frame_request, url,
+ std::move(web_contents_getter), net_error, ssl_info, fatal);
}
#if defined(OS_CHROMEOS)
@@ -564,21 +612,6 @@ void NetworkServiceClient::OnLoadingStateUpdate(
std::move(callback).Run();
}
-void NetworkServiceClient::OnClearSiteData(int process_id,
- int routing_id,
- const GURL& url,
- const std::string& header_value,
- int load_flags,
- OnClearSiteDataCallback callback) {
- auto browser_context_getter =
- base::BindRepeating(GetBrowserContextFromIds, process_id, routing_id);
- auto web_contents_getter =
- base::BindRepeating(GetWebContents, process_id, routing_id);
- ClearSiteDataHandler::HandleHeader(browser_context_getter,
- web_contents_getter, url, header_value,
- load_flags, std::move(callback));
-}
-
void NetworkServiceClient::OnCertDBChanged() {
GetNetworkService()->OnCertDBChanged();
}
@@ -688,4 +721,28 @@ void NetworkServiceClient::OnGenerateHttpNegotiateAuthToken(
}
#endif
+void NetworkServiceClient::OnFlaggedRequestCookies(
+ int32_t process_id,
+ int32_t routing_id,
+ const net::CookieStatusList& excluded_cookies) {
+ DeprecateSameSiteCookies(process_id, routing_id, excluded_cookies);
+}
+
+void NetworkServiceClient::OnFlaggedResponseCookies(
+ int32_t process_id,
+ int32_t routing_id,
+ const net::CookieAndLineStatusList& excluded_cookies) {
+ net::CookieStatusList excluded_list;
+
+ for (const auto& excluded_cookie : excluded_cookies) {
+ // If there's no cookie, it was a parsing error and wouldn't be deprecated
+ if (excluded_cookie.cookie) {
+ excluded_list.push_back(
+ {excluded_cookie.cookie.value(), excluded_cookie.status});
+ }
+ }
+
+ DeprecateSameSiteCookies(process_id, routing_id, excluded_list);
+}
+
} // namespace content
diff --git a/chromium/content/browser/network_service_client.h b/chromium/content/browser/network_service_client.h
index 58d907f8e82..9cfacfac0ad 100644
--- a/chromium/content/browser/network_service_client.h
+++ b/chromium/content/browser/network_service_client.h
@@ -5,6 +5,10 @@
#ifndef CONTENT_BROWSER_NETWORK_SERVICE_IMPL_H_
#define CONTENT_BROWSER_NETWORK_SERVICE_IMPL_H_
+#include <memory>
+#include <string>
+#include <vector>
+
#include "base/macros.h"
#include "base/memory/memory_pressure_listener.h"
#include "build/build_config.h"
@@ -39,10 +43,8 @@ class CONTENT_EXPORT NetworkServiceClient
uint32_t routing_id,
uint32_t request_id,
const GURL& url,
- const GURL& site_for_cookies,
bool first_auth_attempt,
const net::AuthChallengeInfo& auth_info,
- int32_t resource_type,
const base::Optional<network::ResourceResponseHead>& head,
network::mojom::AuthChallengeResponderPtr
auth_challenge_responder) override;
@@ -52,13 +54,11 @@ class CONTENT_EXPORT NetworkServiceClient
uint32_t routing_id,
uint32_t request_id,
const scoped_refptr<net::SSLCertRequestInfo>& cert_info,
- network::mojom::NetworkServiceClient::OnCertificateRequestedCallback
- callback) override;
+ network::mojom::ClientCertificateResponderPtr cert_responder) override;
void OnSSLCertificateError(uint32_t process_id,
uint32_t routing_id,
- uint32_t request_id,
- int32_t resource_type,
const GURL& url,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal,
OnSSLCertificateErrorCallback response) override;
@@ -83,12 +83,6 @@ class CONTENT_EXPORT NetworkServiceClient
bool blocked_by_policy) override;
void OnLoadingStateUpdate(std::vector<network::mojom::LoadInfoPtr> infos,
OnLoadingStateUpdateCallback callback) override;
- void OnClearSiteData(int process_id,
- int routing_id,
- const GURL& url,
- const std::string& header_value,
- int load_flags,
- OnClearSiteDataCallback callback) override;
void OnDataUseUpdate(int32_t network_traffic_annotation_id_hash,
int64_t recv_bytes,
int64_t sent_bytes) override;
@@ -100,7 +94,14 @@ class CONTENT_EXPORT NetworkServiceClient
const std::string& spn,
OnGenerateHttpNegotiateAuthTokenCallback callback) override;
#endif
-
+ void OnFlaggedRequestCookies(
+ int32_t process_id,
+ int32_t routing_id,
+ const net::CookieStatusList& excluded_cookies) override;
+ void OnFlaggedResponseCookies(
+ int32_t process_id,
+ int32_t routing_id,
+ const net::CookieAndLineStatusList& excluded_cookies) override;
// net::CertDatabase::Observer implementation:
void OnCertDBChanged() override;
diff --git a/chromium/content/browser/network_service_instance.cc b/chromium/content/browser/network_service_instance_impl.cc
index 5f6b1392774..7c7cfc6932e 100644
--- a/chromium/content/browser/network_service_instance.cc
+++ b/chromium/content/browser/network_service_instance_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/public/browser/network_service_instance.h"
+#include "content/browser/network_service_instance_impl.h"
#include <map>
#include <memory>
@@ -17,12 +17,14 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/threading/sequence_local_storage_slot.h"
#include "build/build_config.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/network_service_client.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/network_service_instance.h"
#include "content/public/common/network_service_util.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
@@ -45,9 +47,16 @@ constexpr char kKrb5CCEnvName[] = "KRB5CCNAME";
constexpr char kKrb5ConfEnvName[] = "KRB5_CONFIG";
#endif
+bool g_force_create_network_service_directly = false;
network::mojom::NetworkServicePtr* g_network_service_ptr = nullptr;
network::NetworkConnectionTracker* g_network_connection_tracker;
-network::NetworkService* g_network_service;
+
+std::unique_ptr<network::NetworkService>& GetLocalNetworkService() {
+ static base::NoDestructor<
+ base::SequenceLocalStorageSlot<std::unique_ptr<network::NetworkService>>>
+ service;
+ return service->GetOrCreateValue();
+}
network::mojom::NetworkServiceParamsPtr CreateNetworkServiceParams() {
network::mojom::NetworkServiceParamsPtr network_service_params =
@@ -80,14 +89,14 @@ network::mojom::NetworkServiceParamsPtr CreateNetworkServiceParams() {
}
void CreateNetworkServiceOnIO(network::mojom::NetworkServiceRequest request) {
- if (g_network_service) {
+ if (GetLocalNetworkService()) {
// GetNetworkServiceImpl() was already called and created the object, so
// just bind it.
- g_network_service->Bind(std::move(request));
+ GetLocalNetworkService()->Bind(std::move(request));
return;
}
- g_network_service = new network::NetworkService(
+ GetLocalNetworkService() = std::make_unique<network::NetworkService>(
nullptr, std::move(request), GetContentClient()->browser()->GetNetLog());
}
@@ -112,10 +121,12 @@ void OnNetworkServiceCrash() {
} // namespace
network::mojom::NetworkService* GetNetworkService() {
- service_manager::Connector* connector =
- base::FeatureList::IsEnabled(network::features::kNetworkService)
- ? ServiceManagerConnection::GetForProcess()->GetConnector()
- : nullptr;
+ service_manager::Connector* connector = nullptr;
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
+ ServiceManagerConnection::GetForProcess() && // null in unit tests.
+ !g_force_create_network_service_directly) {
+ connector = ServiceManagerConnection::GetForProcess()->GetConnector();
+ }
return GetNetworkServiceFromConnector(connector);
}
@@ -145,13 +156,12 @@ CONTENT_EXPORT network::mojom::NetworkService* GetNetworkServiceFromConnector(
auto request = mojo::MakeRequest(g_network_service_ptr);
auto leaked_pipe = request.PassMessagePipe().release();
} else {
- if (is_network_service_enabled) {
+ if (is_network_service_enabled && connector) {
connector->BindInterface(mojom::kNetworkServiceName,
g_network_service_ptr);
g_network_service_ptr->set_connection_error_handler(
base::BindOnce(&OnNetworkServiceCrash));
} else {
- DCHECK(!g_network_service_ptr->is_bound());
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(CreateNetworkServiceOnIO,
@@ -183,10 +193,12 @@ CONTENT_EXPORT network::mojom::NetworkService* GetNetworkServiceFromConnector(
if (!file.IsValid()) {
LOG(ERROR) << "Failed opening: " << log_path.value();
} else {
- // TODO(mmenke): Get capture mode from the command line.
+ net::NetLogCaptureMode capture_mode =
+ net::GetNetCaptureModeFromCommandLine(
+ *command_line, network::switches::kNetLogCaptureMode);
+
(*g_network_service_ptr)
- ->StartNetLog(std::move(file),
- network::mojom::NetLogCaptureMode::DEFAULT,
+ ->StartNetLog(std::move(file), capture_mode,
std::move(client_constants));
}
}
@@ -235,17 +247,19 @@ RegisterNetworkServiceCrashHandler(base::RepeatingClosure handler) {
network::NetworkService* GetNetworkServiceImpl() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
- if (!g_network_service) {
- g_network_service = new network::NetworkService(
+ if (!GetLocalNetworkService()) {
+ GetLocalNetworkService() = std::make_unique<network::NetworkService>(
nullptr, nullptr, GetContentClient()->browser()->GetNetLog());
}
- return g_network_service;
+ return GetLocalNetworkService().get();
}
+#if defined(OS_CHROMEOS)
net::NetworkChangeNotifier* GetNetworkChangeNotifier() {
return BrowserMainLoop::GetInstance()->network_change_notifier();
}
+#endif
void FlushNetworkServiceInstanceForTesting() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -307,4 +321,13 @@ scoped_refptr<base::DeferredSequencedTaskRunner> GetNetworkTaskRunner() {
return instance->get();
}
+void ForceCreateNetworkServiceDirectlyForTesting() {
+ g_force_create_network_service_directly = true;
+}
+
+void ResetNetworkServiceForTesting() {
+ delete g_network_service_ptr;
+ g_network_service_ptr = nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/network_service_instance_impl.h b/chromium/content/browser/network_service_instance_impl.h
new file mode 100644
index 00000000000..641d0813fc4
--- /dev/null
+++ b/chromium/content/browser/network_service_instance_impl.h
@@ -0,0 +1,31 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_NETWORK_SERVICE_INSTANCE_IMPL_H_
+#define CONTENT_BROWSER_NETWORK_SERVICE_INSTANCE_IMPL_H_
+
+#include "base/callback.h"
+#include "base/callback_list.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Creates the network::NetworkService object on the IO thread directly instead
+// of trying to go through the ServiceManager.
+CONTENT_EXPORT void ForceCreateNetworkServiceDirectlyForTesting();
+
+// Resets the interface ptr to the network service.
+CONTENT_EXPORT void ResetNetworkServiceForTesting();
+
+// Registers |handler| to run (on UI thread) after NetworkServicePtr encounters
+// an error. Note that there are no ordering guarantees wrt error handlers for
+// other interfaces (e.g. NetworkContextPtr and/or URLLoaderFactoryPtr).
+//
+// Can only be called on the UI thread. No-op if NetworkService is disabled.
+CONTENT_EXPORT std::unique_ptr<base::CallbackList<void()>::Subscription>
+RegisterNetworkServiceCrashHandler(base::RepeatingClosure handler);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_NETWORK_SERVICE_INSTANCE_IMPL_H_
diff --git a/chromium/content/browser/network_service_restart_browsertest.cc b/chromium/content/browser/network_service_restart_browsertest.cc
index 1eb5cfc5a5d..2aca979fbb5 100644
--- a/chromium/content/browser/network_service_restart_browsertest.cc
+++ b/chromium/content/browser/network_service_restart_browsertest.cc
@@ -12,6 +12,7 @@
#include "build/build_config.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/render_frame_message_filter.h"
+#include "content/browser/network_service_instance_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_status.h"
diff --git a/chromium/content/browser/notifications/OWNERS b/chromium/content/browser/notifications/OWNERS
index 0d5ed95cb0a..fec618f3c34 100644
--- a/chromium/content/browser/notifications/OWNERS
+++ b/chromium/content/browser/notifications/OWNERS
@@ -4,6 +4,7 @@
# //content/renderer/notifications/
# //content/test/mock_platform_notification_service.*
+knollr@chromium.org
mkwst@chromium.org
peter@chromium.org
diff --git a/chromium/content/browser/notifications/blink_notification_service_impl.cc b/chromium/content/browser/notifications/blink_notification_service_impl.cc
index a30403295a8..63a1fe8ebd1 100644
--- a/chromium/content/browser/notifications/blink_notification_service_impl.cc
+++ b/chromium/content/browser/notifications/blink_notification_service_impl.cc
@@ -268,14 +268,9 @@ void BlinkNotificationServiceImpl::ClosePersistentNotification(
if (CheckPermissionStatus() != blink::mojom::PermissionStatus::GRANTED)
return;
- GetNotificationService(browser_context_)
- ->ClosePersistentNotification(notification_id);
-
- // Deleting the data associated with |notification_id| from the notification
- // database will be done in a task runner, but there's no reason to postpone
- // removing the notification from the user's display until that's done.
notification_context_->DeleteNotificationData(
- notification_id, origin_.GetURL(), base::DoNothing());
+ notification_id, origin_.GetURL(), /* close_notification= */ true,
+ base::DoNothing());
}
void BlinkNotificationServiceImpl::GetNotifications(
diff --git a/chromium/content/browser/notifications/devtools_event_logging.cc b/chromium/content/browser/notifications/devtools_event_logging.cc
new file mode 100644
index 00000000000..0dacfeb5974
--- /dev/null
+++ b/chromium/content/browser/notifications/devtools_event_logging.cc
@@ -0,0 +1,144 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/notifications/devtools_event_logging.h"
+
+#include "base/callback.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/devtools_background_services_context.h"
+#include "content/public/browser/notification_database_data.h"
+#include "content/public/browser/storage_partition.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
+#include "url/gurl.h"
+
+namespace content {
+namespace notifications {
+
+namespace {
+
+using EventMetadata = std::map<std::string, std::string>;
+using DevToolsBaseCallback =
+ base::OnceCallback<void(const std::string& event_name,
+ const std::string& instance_id,
+ const EventMetadata& event_metadata)>;
+using DevToolsCallback =
+ base::OnceCallback<void(const std::string& event_name,
+ const EventMetadata& event_metadata)>;
+
+DevToolsBackgroundServicesContext* GetDevToolsContext(
+ BrowserContext* browser_context,
+ const GURL& origin) {
+ auto* storage_partition =
+ BrowserContext::GetStoragePartitionForSite(browser_context, origin);
+ if (!storage_partition)
+ return nullptr;
+
+ auto* devtools_context =
+ storage_partition->GetDevToolsBackgroundServicesContext();
+ if (!devtools_context || !devtools_context->IsRecording(
+ DevToolsBackgroundService::kNotifications)) {
+ return nullptr;
+ }
+
+ return devtools_context;
+}
+
+DevToolsCallback GetDevToolsCallback(BrowserContext* browser_context,
+ const NotificationDatabaseData& data) {
+ if (data.service_worker_registration_id ==
+ blink::mojom::kInvalidServiceWorkerRegistrationId) {
+ return DevToolsCallback();
+ }
+
+ auto* devtools_context = GetDevToolsContext(browser_context, data.origin);
+ if (!devtools_context)
+ return DevToolsCallback();
+
+ // Passing the |devtools_context| as base::Unretained is safe as the callback
+ // is executed synchronously.
+ auto base_callback = base::BindOnce(
+ &DevToolsBackgroundServicesContext::LogBackgroundServiceEvent,
+ base::Unretained(devtools_context), data.service_worker_registration_id,
+ url::Origin::Create(data.origin),
+ DevToolsBackgroundService::kNotifications);
+
+ // TODO(knollr): Reorder parameters of LogBackgroundServiceEvent instead.
+ return base::BindOnce(
+ [](DevToolsBaseCallback callback, const std::string& notification_id,
+ const std::string& event_name, const EventMetadata& metadata) {
+ std::move(callback).Run(event_name, notification_id, metadata);
+ },
+ std::move(base_callback), data.notification_data.tag);
+}
+
+} // namespace
+
+bool ShouldLogNotificationEventToDevTools(BrowserContext* browser_context,
+ const GURL& origin) {
+ return GetDevToolsContext(browser_context, origin) != nullptr;
+}
+
+void LogNotificationDisplayedEventToDevTools(
+ BrowserContext* browser_context,
+ const NotificationDatabaseData& data) {
+ DevToolsCallback callback = GetDevToolsCallback(browser_context, data);
+ if (!callback)
+ return;
+
+ std::move(callback).Run(
+ /* event_name= */ "Notification displayed",
+ {{"Title", base::UTF16ToUTF8(data.notification_data.title)},
+ {"Body", base::UTF16ToUTF8(data.notification_data.body)}});
+}
+
+void LogNotificationClosedEventToDevTools(
+ BrowserContext* browser_context,
+ const NotificationDatabaseData& data) {
+ DevToolsCallback callback = GetDevToolsCallback(browser_context, data);
+ if (!callback)
+ return;
+
+ std::move(callback).Run(/* event_name= */ "Notification closed",
+ /* event_metadata= */ {});
+}
+
+void LogNotificationScheduledEventToDevTools(
+ BrowserContext* browser_context,
+ const NotificationDatabaseData& data,
+ base::Time show_trigger_timestamp) {
+ DevToolsCallback callback = GetDevToolsCallback(browser_context, data);
+ if (!callback)
+ return;
+
+ std::move(callback).Run(
+ /* event_name= */ "Notification scheduled",
+ {{"Show Trigger Timestamp",
+ base::NumberToString(show_trigger_timestamp.ToJsTime())},
+ {"Title", base::UTF16ToUTF8(data.notification_data.title)},
+ {"Body", base::UTF16ToUTF8(data.notification_data.body)}});
+}
+
+void LogNotificationClickedEventToDevTools(
+ BrowserContext* browser_context,
+ const NotificationDatabaseData& data,
+ const base::Optional<int>& action_index,
+ const base::Optional<base::string16>& reply) {
+ DevToolsCallback callback = GetDevToolsCallback(browser_context, data);
+ if (!callback)
+ return;
+
+ EventMetadata event_metadata;
+ if (action_index)
+ event_metadata["Action Index"] = base::NumberToString(*action_index);
+ if (reply)
+ event_metadata["Reply"] = base::UTF16ToUTF8(*reply);
+
+ std::move(callback).Run(/* event_name= */ "Notification clicked",
+ event_metadata);
+}
+
+} // namespace notifications
+} // namespace content
diff --git a/chromium/content/browser/notifications/devtools_event_logging.h b/chromium/content/browser/notifications/devtools_event_logging.h
new file mode 100644
index 00000000000..c46a2268b87
--- /dev/null
+++ b/chromium/content/browser/notifications/devtools_event_logging.h
@@ -0,0 +1,47 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_NOTIFICATIONS_DEVTOOLS_EVENT_LOGGING_H_
+#define CONTENT_BROWSER_NOTIFICATIONS_DEVTOOLS_EVENT_LOGGING_H_
+
+#include <string>
+
+#include "base/optional.h"
+#include "base/strings/string16.h"
+#include "base/time/time.h"
+
+class GURL;
+
+namespace content {
+
+class BrowserContext;
+struct NotificationDatabaseData;
+
+namespace notifications {
+
+bool ShouldLogNotificationEventToDevTools(BrowserContext* browser_context,
+ const GURL& origin);
+
+void LogNotificationDisplayedEventToDevTools(
+ BrowserContext* browser_context,
+ const NotificationDatabaseData& data);
+
+void LogNotificationClosedEventToDevTools(BrowserContext* browser_context,
+ const NotificationDatabaseData& data);
+
+void LogNotificationScheduledEventToDevTools(
+ BrowserContext* browser_context,
+ const NotificationDatabaseData& data,
+ base::Time show_trigger_timestamp);
+
+void LogNotificationClickedEventToDevTools(
+ BrowserContext* browser_context,
+ const NotificationDatabaseData& data,
+ const base::Optional<int>& action_index,
+ const base::Optional<base::string16>& reply);
+
+} // namespace notifications
+} // namespace content
+
+#endif // CONTENT_BROWSER_NOTIFICATIONS_DEVTOOLS_EVENT_LOGGING_H_
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
index f423da168ea..ba2bb9078f9 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -11,6 +11,7 @@
#include "base/optional.h"
#include "base/task/post_task.h"
#include "build/build_config.h"
+#include "content/browser/notifications/devtools_event_logging.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
@@ -27,14 +28,17 @@ namespace content {
namespace {
using NotificationDispatchCompleteCallback =
- base::Callback<void(PersistentNotificationStatus)>;
+ base::OnceCallback<void(PersistentNotificationStatus)>;
using NotificationOperationCallback =
- base::Callback<void(const ServiceWorkerRegistration*,
- const NotificationDatabaseData&)>;
+ base::OnceCallback<void(const ServiceWorkerRegistration*,
+ const NotificationDatabaseData&,
+ NotificationDispatchCompleteCallback)>;
using NotificationOperationCallbackWithContext =
- base::Callback<void(const scoped_refptr<PlatformNotificationContext>&,
- const ServiceWorkerRegistration*,
- const NotificationDatabaseData&)>;
+ base::OnceCallback<void(const scoped_refptr<PlatformNotificationContext>&,
+ BrowserContext* browser_context,
+ const ServiceWorkerRegistration*,
+ const NotificationDatabaseData&,
+ NotificationDispatchCompleteCallback)>;
// Derives a PersistentNotificationStatus from the ServiceWorkerStatusCode.
PersistentNotificationStatus ConvertServiceWorkerStatus(
@@ -80,12 +84,12 @@ PersistentNotificationStatus ConvertServiceWorkerStatus(
// |dispatch_complete_callback| on the UI thread with a
// PersistentNotificationStatus derived from the service worker status.
void ServiceWorkerNotificationEventFinished(
- const NotificationDispatchCompleteCallback& dispatch_complete_callback,
+ NotificationDispatchCompleteCallback dispatch_complete_callback,
blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
- base::BindOnce(dispatch_complete_callback,
+ base::BindOnce(std::move(dispatch_complete_callback),
ConvertServiceWorkerStatus(service_worker_status)));
}
@@ -94,9 +98,8 @@ void ServiceWorkerNotificationEventFinished(
// called on the IO thread.
void DispatchNotificationEventOnRegistration(
const NotificationDatabaseData& notification_database_data,
- const scoped_refptr<PlatformNotificationContext>& notification_context,
- const NotificationOperationCallback& dispatch_event_action,
- const NotificationDispatchCompleteCallback& dispatch_error_callback,
+ NotificationOperationCallback dispatch_event_action,
+ NotificationDispatchCompleteCallback dispatch_complete_callback,
blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -110,8 +113,9 @@ void DispatchNotificationEventOnRegistration(
if (service_worker_status == blink::ServiceWorkerStatusCode::kOk) {
DCHECK(service_worker_registration->active_version());
- dispatch_event_action.Run(service_worker_registration.get(),
- notification_database_data);
+ std::move(dispatch_event_action)
+ .Run(service_worker_registration.get(), notification_database_data,
+ std::move(dispatch_complete_callback));
return;
}
@@ -145,18 +149,18 @@ void DispatchNotificationEventOnRegistration(
break;
}
- base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(dispatch_error_callback, status));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(dispatch_complete_callback), status));
}
// Finds the ServiceWorkerRegistration associated with the |origin| and
-// |service_worker_registration_id|. Must be called on the IO thread.
+// |service_worker_registration_id|. Must be called on the UI thread.
void FindServiceWorkerRegistration(
const GURL& origin,
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
- const scoped_refptr<PlatformNotificationContext>& notification_context,
- const NotificationOperationCallback& notification_action_callback,
- const NotificationDispatchCompleteCallback& dispatch_error_callback,
+ NotificationOperationCallback notification_action_callback,
+ NotificationDispatchCompleteCallback dispatch_complete_callback,
bool success,
const NotificationDatabaseData& notification_database_data) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -167,20 +171,21 @@ void FindServiceWorkerRegistration(
LOG(INFO) << "Lookup for ServiceWoker Registration: success: " << success;
#endif
if (!success) {
- dispatch_error_callback.Run(PersistentNotificationStatus::kDatabaseError);
+ std::move(dispatch_complete_callback)
+ .Run(PersistentNotificationStatus::kDatabaseError);
return;
}
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
- base::BindOnce(
- &ServiceWorkerContextWrapper::FindReadyRegistrationForId,
- service_worker_context,
- notification_database_data.service_worker_registration_id, origin,
- base::BindOnce(&DispatchNotificationEventOnRegistration,
- notification_database_data, notification_context,
- notification_action_callback,
- dispatch_error_callback)));
+ base::BindOnce(&ServiceWorkerContextWrapper::FindReadyRegistrationForId,
+ service_worker_context,
+ notification_database_data.service_worker_registration_id,
+ origin,
+ base::BindOnce(&DispatchNotificationEventOnRegistration,
+ notification_database_data,
+ std::move(notification_action_callback),
+ std::move(dispatch_complete_callback))));
}
// Reads the data associated with the |notification_id| belonging to |origin|
@@ -191,14 +196,15 @@ void ReadNotificationDatabaseData(
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) {
+ NotificationOperationCallback notification_read_callback,
+ NotificationDispatchCompleteCallback dispatch_complete_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
notification_context->ReadNotificationDataAndRecordInteraction(
notification_id, origin, interaction,
- base::Bind(&FindServiceWorkerRegistration, origin, service_worker_context,
- notification_context, notification_read_callback,
- dispatch_error_callback));
+ base::BindOnce(&FindServiceWorkerRegistration, origin,
+ service_worker_context,
+ std::move(notification_read_callback),
+ std::move(dispatch_complete_callback)));
}
// -----------------------------------------------------------------------------
@@ -235,11 +241,19 @@ void DispatchNotificationClickEventOnWorker(
void DoDispatchNotificationClickEvent(
const base::Optional<int>& action_index,
const base::Optional<base::string16>& reply,
- const NotificationDispatchCompleteCallback& dispatch_complete_callback,
const scoped_refptr<PlatformNotificationContext>& notification_context,
+ BrowserContext* browser_context,
const ServiceWorkerRegistration* service_worker_registration,
- const NotificationDatabaseData& notification_database_data) {
+ const NotificationDatabaseData& notification_database_data,
+ NotificationDispatchCompleteCallback dispatch_complete_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&notifications::LogNotificationClickedEventToDevTools,
+ browser_context, notification_database_data, action_index,
+ reply));
+
service_worker_registration->active_version()->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::NOTIFICATION_CLICK,
base::BindOnce(
@@ -247,7 +261,7 @@ void DoDispatchNotificationClickEvent(
base::WrapRefCounted(service_worker_registration->active_version()),
notification_database_data, action_index, reply,
base::BindOnce(&ServiceWorkerNotificationEventFinished,
- dispatch_complete_callback)));
+ std::move(dispatch_complete_callback))));
}
// -----------------------------------------------------------------------------
@@ -256,7 +270,7 @@ void DoDispatchNotificationClickEvent(
// close event.
void OnPersistentNotificationDataDeleted(
blink::ServiceWorkerStatusCode service_worker_status,
- const NotificationDispatchCompleteCallback& dispatch_complete_callback,
+ NotificationDispatchCompleteCallback dispatch_complete_callback,
bool success) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PersistentNotificationStatus status =
@@ -264,7 +278,7 @@ void OnPersistentNotificationDataDeleted(
: PersistentNotificationStatus::kDatabaseError;
if (service_worker_status != blink::ServiceWorkerStatusCode::kOk)
status = ConvertServiceWorkerStatus(service_worker_status);
- dispatch_complete_callback.Run(status);
+ std::move(dispatch_complete_callback).Run(status);
}
// Called when the persistent notification close event has been handled
@@ -273,7 +287,7 @@ void DeleteNotificationDataFromDatabase(
const std::string& notification_id,
const GURL& origin,
const scoped_refptr<PlatformNotificationContext>& notification_context,
- const NotificationDispatchCompleteCallback& dispatch_complete_callback,
+ NotificationDispatchCompleteCallback dispatch_complete_callback,
blink::ServiceWorkerStatusCode status_code) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
base::PostTaskWithTraits(
@@ -281,8 +295,9 @@ void DeleteNotificationDataFromDatabase(
base::BindOnce(
&PlatformNotificationContext::DeleteNotificationData,
notification_context, notification_id, origin,
- base::BindRepeating(&OnPersistentNotificationDataDeleted, status_code,
- dispatch_complete_callback)));
+ /* close_notification= */ false,
+ base::BindOnce(&OnPersistentNotificationDataDeleted, status_code,
+ std::move(dispatch_complete_callback))));
}
// Dispatches the notificationclose event on |service_worker|.
@@ -311,10 +326,11 @@ void DispatchNotificationCloseEventOnWorker(
void DoDispatchNotificationCloseEvent(
const std::string& notification_id,
bool by_user,
- const NotificationDispatchCompleteCallback& dispatch_complete_callback,
const scoped_refptr<PlatformNotificationContext>& notification_context,
+ BrowserContext* browser_context,
const ServiceWorkerRegistration* service_worker_registration,
- const NotificationDatabaseData& notification_database_data) {
+ const NotificationDatabaseData& notification_database_data,
+ NotificationDispatchCompleteCallback dispatch_complete_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (by_user) {
service_worker_registration->active_version()->RunAfterStartWorker(
@@ -325,11 +341,12 @@ void DoDispatchNotificationCloseEvent(
notification_database_data,
base::BindOnce(&DeleteNotificationDataFromDatabase, notification_id,
notification_database_data.origin,
- notification_context, dispatch_complete_callback)));
+ notification_context,
+ std::move(dispatch_complete_callback))));
} else {
DeleteNotificationDataFromDatabase(
notification_id, notification_database_data.origin,
- notification_context, dispatch_complete_callback,
+ notification_context, std::move(dispatch_complete_callback),
blink::ServiceWorkerStatusCode::kOk);
}
}
@@ -341,9 +358,8 @@ void DispatchNotificationEvent(
const std::string& notification_id,
const GURL& origin,
const PlatformNotificationContext::Interaction interaction,
- const NotificationOperationCallbackWithContext&
- notification_action_callback,
- const NotificationDispatchCompleteCallback& notification_error_callback) {
+ NotificationOperationCallbackWithContext notification_action_callback,
+ NotificationDispatchCompleteCallback dispatch_complete_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!notification_id.empty());
DCHECK(origin.is_valid());
@@ -360,8 +376,9 @@ void DispatchNotificationEvent(
ReadNotificationDatabaseData(
notification_id, origin, interaction, service_worker_context,
notification_context,
- base::BindRepeating(notification_action_callback, notification_context),
- notification_error_callback);
+ base::BindOnce(std::move(notification_action_callback),
+ notification_context, browser_context),
+ std::move(dispatch_complete_callback));
}
} // namespace
@@ -388,10 +405,6 @@ void NotificationEventDispatcherImpl::DispatchNotificationClickEvent(
const base::Optional<base::string16>& reply,
NotificationDispatchCompleteCallback dispatch_complete_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // TODO(peter): Remove AdaptCallbackForRepeating() when the dependencies of
- // the NotificationEventDispatcherImpl have updated to using OnceCallbacks.
- auto repeating_callback =
- base::AdaptCallbackForRepeating(std::move(dispatch_complete_callback));
PlatformNotificationContext::Interaction interaction =
action_index.has_value()
@@ -400,9 +413,8 @@ void NotificationEventDispatcherImpl::DispatchNotificationClickEvent(
DispatchNotificationEvent(
browser_context, notification_id, origin, interaction,
- base::Bind(&DoDispatchNotificationClickEvent, action_index, reply,
- repeating_callback),
- repeating_callback /* notification_error_callback */);
+ base::BindOnce(&DoDispatchNotificationClickEvent, action_index, reply),
+ std::move(dispatch_complete_callback));
}
void NotificationEventDispatcherImpl::DispatchNotificationCloseEvent(
@@ -412,17 +424,12 @@ void NotificationEventDispatcherImpl::DispatchNotificationCloseEvent(
bool by_user,
NotificationDispatchCompleteCallback dispatch_complete_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // TODO(peter): Remove AdaptCallbackForRepeating() when the dependencies of
- // the NotificationEventDispatcherImpl have updated to using OnceCallbacks.
- auto repeating_callback =
- base::AdaptCallbackForRepeating(std::move(dispatch_complete_callback));
- DispatchNotificationEvent(
- browser_context, notification_id, origin,
- PlatformNotificationContext::Interaction::CLOSED,
- base::Bind(&DoDispatchNotificationCloseEvent, notification_id, by_user,
- repeating_callback),
- repeating_callback /* notification_error_callback */);
+ DispatchNotificationEvent(browser_context, notification_id, origin,
+ PlatformNotificationContext::Interaction::CLOSED,
+ base::BindOnce(&DoDispatchNotificationCloseEvent,
+ notification_id, by_user),
+ std::move(dispatch_complete_callback));
}
void NotificationEventDispatcherImpl::RegisterNonPersistentNotificationListener(
diff --git a/chromium/content/browser/notifications/platform_notification_context_impl.cc b/chromium/content/browser/notifications/platform_notification_context_impl.cc
index d0b32520a30..9402a2b5156 100644
--- a/chromium/content/browser/notifications/platform_notification_context_impl.cc
+++ b/chromium/content/browser/notifications/platform_notification_context_impl.cc
@@ -67,7 +67,8 @@ PlatformNotificationContextImpl::PlatformNotificationContextImpl(
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
: path_(path),
browser_context_(browser_context),
- service_worker_context_(service_worker_context) {
+ service_worker_context_(service_worker_context),
+ has_shutdown_(false) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
@@ -109,6 +110,10 @@ void PlatformNotificationContextImpl::DidGetNotifications(
std::set<std::string> displayed_notifications,
bool supports_synchronization) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Abort if the profile has been shut down already. This mainly happens in
+ // tests and very short lived sessions.
+ if (has_shutdown_)
+ return;
// Check if there are pending notifications to display.
base::Time next_trigger = base::Time::Max();
@@ -189,8 +194,11 @@ void PlatformNotificationContextImpl::DoHandleSyncNotification(
void PlatformNotificationContextImpl::Shutdown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ has_shutdown_ = true;
+
+ if (service_proxy_)
+ service_proxy_->Shutdown();
- service_proxy_.reset();
services_.clear();
// |service_worker_context_| may be NULL in tests.
@@ -235,7 +243,7 @@ void PlatformNotificationContextImpl::DoReadAllNotificationOrigins(
std::set<GURL> origins;
if (!initialized) {
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ false,
std::move(origins)));
return;
@@ -257,7 +265,7 @@ void PlatformNotificationContextImpl::DoReadAllNotificationOrigins(
DestroyDatabase();
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), success, std::move(origins)));
}
@@ -267,7 +275,7 @@ void PlatformNotificationContextImpl::CheckPermissionsAndDeleteBlocked(
std::set<GURL> origins) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Make sure |browser_context_| is still valid before getting the controller.
- if (!success || !service_proxy_) {
+ if (!success || !service_proxy_ || has_shutdown_) {
std::move(callback).Run(/* success= */ false, /* deleted_count= */ 0);
return;
}
@@ -303,7 +311,7 @@ void PlatformNotificationContextImpl::DoDeleteAllNotificationDataForOrigins(
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (!initialized) {
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ false,
/* deleted_count= */ 0));
return;
@@ -336,10 +344,9 @@ void PlatformNotificationContextImpl::DoDeleteAllNotificationDataForOrigins(
service_proxy_->CloseNotification(notification_id);
}
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
- base::BindOnce(std::move(callback), success,
- deleted_notification_ids.size()));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), success,
+ deleted_notification_ids.size()));
}
void PlatformNotificationContextImpl::ReadNotificationDataAndRecordInteraction(
@@ -362,7 +369,7 @@ void PlatformNotificationContextImpl::DoReadNotificationData(
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (!initialized) {
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ false,
NotificationDatabaseData()));
return;
@@ -378,7 +385,7 @@ void PlatformNotificationContextImpl::DoReadNotificationData(
if (status == NotificationDatabase::STATUS_OK) {
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ true,
database_data));
return;
@@ -389,7 +396,7 @@ void PlatformNotificationContextImpl::DoReadNotificationData(
DestroyDatabase();
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ false,
NotificationDatabaseData()));
}
@@ -459,7 +466,7 @@ void PlatformNotificationContextImpl::DoReadNotificationResources(
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (!initialized) {
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ false,
blink::NotificationResources()));
return;
@@ -474,7 +481,7 @@ void PlatformNotificationContextImpl::DoReadNotificationResources(
if (status == NotificationDatabase::STATUS_OK) {
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ true,
notification_resources));
return;
@@ -485,7 +492,7 @@ void PlatformNotificationContextImpl::DoReadNotificationResources(
DestroyDatabase();
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ false,
blink::NotificationResources()));
}
@@ -543,7 +550,7 @@ void PlatformNotificationContextImpl::
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (!initialized) {
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ false,
std::vector<NotificationDatabaseData>()));
return;
@@ -578,7 +585,7 @@ void PlatformNotificationContextImpl::
}
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ true,
notification_datas));
@@ -593,7 +600,7 @@ void PlatformNotificationContextImpl::
DestroyDatabase();
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ false,
std::vector<NotificationDatabaseData>()));
}
@@ -644,7 +651,7 @@ void PlatformNotificationContextImpl::DoWriteNotificationData(
DCHECK(database_data.notification_id.empty());
if (!initialized || !service_proxy_) {
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ false,
/* notification_id= */ ""));
return;
@@ -680,7 +687,7 @@ void PlatformNotificationContextImpl::DoWriteNotificationData(
DestroyDatabase();
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ false,
/* notification_id= */ ""));
return;
@@ -696,7 +703,7 @@ void PlatformNotificationContextImpl::DoWriteNotificationData(
!DoCheckNotificationTriggerQuota(origin)) {
// TODO(knollr): Reply with a custom error so developers can handle this.
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ false,
/* notification_id= */ ""));
return;
@@ -718,14 +725,13 @@ void PlatformNotificationContextImpl::DoWriteNotificationData(
service_proxy_->CloseNotification(notification_id);
// Schedule notification to be shown.
- service_proxy_->ScheduleTrigger(
- write_database_data.notification_data.show_trigger_timestamp.value());
+ service_proxy_->ScheduleNotification(std::move(write_database_data));
// Respond with success as this notification got scheduled successfully.
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ true,
- write_database_data.notification_id));
+ notification_id));
return;
}
@@ -742,7 +748,7 @@ void PlatformNotificationContextImpl::DoWriteNotificationData(
DestroyDatabase();
base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), /* success= */ false,
/* notification_id= */ ""));
}
@@ -750,27 +756,44 @@ void PlatformNotificationContextImpl::DoWriteNotificationData(
void PlatformNotificationContextImpl::DeleteNotificationData(
const std::string& notification_id,
const GURL& origin,
+ bool close_notification,
DeleteResultCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!service_proxy_)
+ return;
- LazyInitialize(
- base::BindOnce(&PlatformNotificationContextImpl::DoDeleteNotificationData,
- this, notification_id, origin, std::move(callback)));
+ // Close notification as we're about to delete its data.
+ if (close_notification)
+ service_proxy_->CloseNotification(notification_id);
+
+ bool should_log_close = service_proxy_->ShouldLogClose(origin);
+ LazyInitialize(base::BindOnce(
+ &PlatformNotificationContextImpl::DoDeleteNotificationData, this,
+ notification_id, origin, std::move(callback), should_log_close));
}
void PlatformNotificationContextImpl::DoDeleteNotificationData(
const std::string& notification_id,
const GURL& origin,
DeleteResultCallback callback,
+ bool should_log_close,
bool initialized) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (!initialized) {
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
- base::BindOnce(std::move(callback), false));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), false));
return;
}
+ // Read additional data if we need to log the close event.
+ if (should_log_close) {
+ NotificationDatabaseData data;
+ if (database_->ReadNotificationData(notification_id, origin, &data) ==
+ NotificationDatabase::STATUS_OK) {
+ service_proxy_->LogClose(std::move(data));
+ }
+ }
+
NotificationDatabase::Status status =
database_->DeleteNotificationData(notification_id, origin);
@@ -787,9 +810,8 @@ void PlatformNotificationContextImpl::DoDeleteNotificationData(
success = true;
}
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
- base::BindOnce(std::move(callback), success));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), success));
}
void PlatformNotificationContextImpl::OnRegistrationDeleted(
@@ -850,7 +872,7 @@ void PlatformNotificationContextImpl::LazyInitialize(
if (!task_runner_) {
task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
}
task_runner_->PostTask(
diff --git a/chromium/content/browser/notifications/platform_notification_context_impl.h b/chromium/content/browser/notifications/platform_notification_context_impl.h
index 11eed749075..3373171efb6 100644
--- a/chromium/content/browser/notifications/platform_notification_context_impl.h
+++ b/chromium/content/browser/notifications/platform_notification_context_impl.h
@@ -93,6 +93,7 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
WriteResultCallback callback) override;
void DeleteNotificationData(const std::string& notification_id,
const GURL& origin,
+ bool close_notification,
DeleteResultCallback callback) override;
void DeleteAllNotificationDataForBlockedOrigins(
DeleteAllResultCallback callback) override;
@@ -206,6 +207,7 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
void DoDeleteNotificationData(const std::string& notification_id,
const GURL& origin,
DeleteResultCallback callback,
+ bool should_log_close,
bool initialized);
// Actually reads all notification origins from the database. Must only be
@@ -272,6 +274,9 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
NotificationDatabase::UkmCallback ukm_callback_;
+ // Flag if the |browser_context_| has been shutdown already.
+ bool has_shutdown_;
+
DISALLOW_COPY_AND_ASSIGN(PlatformNotificationContextImpl);
};
diff --git a/chromium/content/browser/notifications/platform_notification_context_trigger_unittest.cc b/chromium/content/browser/notifications/platform_notification_context_trigger_unittest.cc
index 4750c58cad1..de2d611301b 100644
--- a/chromium/content/browser/notifications/platform_notification_context_trigger_unittest.cc
+++ b/chromium/content/browser/notifications/platform_notification_context_trigger_unittest.cc
@@ -62,6 +62,8 @@ class PlatformNotificationContextTriggerTest : public ::testing::Test {
}
void SetUp() override {
+ // Advance time a little bit so TimeTicks::Now().is_null() becomes false.
+ thread_bundle_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
scoped_feature_list_.InitAndEnableFeature(features::kNotificationTriggers);
platform_notification_context_ =
base::MakeRefCounted<PlatformNotificationContextImpl>(
diff --git a/chromium/content/browser/notifications/platform_notification_context_unittest.cc b/chromium/content/browser/notifications/platform_notification_context_unittest.cc
index fb60eb3871b..2e62f6859ee 100644
--- a/chromium/content/browser/notifications/platform_notification_context_unittest.cc
+++ b/chromium/content/browser/notifications/platform_notification_context_unittest.cc
@@ -206,8 +206,8 @@ TEST_F(PlatformNotificationContextTest, ReadNonExistentNotification) {
context->ReadNotificationDataAndRecordInteraction(
"invalid-notification-id", GURL("https://example.com"),
PlatformNotificationContext::Interaction::NONE,
- base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidReadNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -226,8 +226,8 @@ TEST_F(PlatformNotificationContextTest, WriteReadNotification) {
context->WriteNotificationData(
next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
origin, notification_database_data,
- base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidWriteNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -237,8 +237,8 @@ TEST_F(PlatformNotificationContextTest, WriteReadNotification) {
context->ReadNotificationDataAndRecordInteraction(
notification_id(), origin, PlatformNotificationContext::Interaction::NONE,
- base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidReadNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -268,8 +268,8 @@ TEST_F(PlatformNotificationContextTest, WriteReadReplacedNotification) {
context->WriteNotificationData(
next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
origin, notification_database_data,
- base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidWriteNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
std::string read_notification_id = notification_id();
@@ -285,8 +285,8 @@ TEST_F(PlatformNotificationContextTest, WriteReadReplacedNotification) {
context->WriteNotificationData(
next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
origin, notification_database_data,
- base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidWriteNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -311,8 +311,10 @@ TEST_F(PlatformNotificationContextTest, DeleteInvalidNotification) {
context->DeleteNotificationData(
"invalid-notification-id", GURL("https://example.com"),
- base::Bind(&PlatformNotificationContextTest::DidDeleteNotificationData,
- base::Unretained(this)));
+ /* close_notification= */ false,
+ base::BindOnce(
+ &PlatformNotificationContextTest::DidDeleteNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -332,8 +334,8 @@ TEST_F(PlatformNotificationContextTest, DeleteNotification) {
context->WriteNotificationData(
next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
origin, notification_database_data,
- base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidWriteNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -343,8 +345,10 @@ TEST_F(PlatformNotificationContextTest, DeleteNotification) {
context->DeleteNotificationData(
notification_id(), origin,
- base::Bind(&PlatformNotificationContextTest::DidDeleteNotificationData,
- base::Unretained(this)));
+ /* close_notification= */ false,
+ base::BindOnce(
+ &PlatformNotificationContextTest::DidDeleteNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -353,8 +357,8 @@ TEST_F(PlatformNotificationContextTest, DeleteNotification) {
context->ReadNotificationDataAndRecordInteraction(
notification_id(), origin, PlatformNotificationContext::Interaction::NONE,
- base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidReadNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -363,6 +367,45 @@ TEST_F(PlatformNotificationContextTest, DeleteNotification) {
EXPECT_FALSE(success());
}
+TEST_F(PlatformNotificationContextTest, DeleteClosesNotification) {
+ NotificationBrowserClient notification_browser_client(browser_context());
+ SetBrowserClientForTesting(&notification_browser_client);
+ PlatformNotificationService* service =
+ notification_browser_client.GetPlatformNotificationService(
+ browser_context());
+
+ scoped_refptr<PlatformNotificationContextImpl> context =
+ CreatePlatformNotificationContext();
+
+ GURL origin("https://example.com");
+ NotificationDatabaseData notification_database_data;
+
+ context->WriteNotificationData(
+ next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
+ origin, notification_database_data,
+ base::BindOnce(&PlatformNotificationContextTest::DidWriteNotificationData,
+ base::Unretained(this)));
+
+ base::RunLoop().RunUntilIdle();
+
+ // The write operation should have displayed a notification.
+ ASSERT_TRUE(success());
+ EXPECT_EQ(1u, GetDisplayedNotificationsSync(service).size());
+
+ context->DeleteNotificationData(
+ notification_id(), origin,
+ /* close_notification= */ true,
+ base::BindOnce(
+ &PlatformNotificationContextTest::DidDeleteNotificationData,
+ base::Unretained(this)));
+
+ base::RunLoop().RunUntilIdle();
+
+ // Deleting the notification data should have closed the notification.
+ ASSERT_TRUE(success());
+ EXPECT_EQ(0u, GetDisplayedNotificationsSync(service).size());
+}
+
TEST_F(PlatformNotificationContextTest,
DeleteAllNotificationDataForBlockedOrigins) {
NotificationBrowserClient notification_browser_client(browser_context());
@@ -470,8 +513,8 @@ TEST_F(PlatformNotificationContextTest, ServiceWorkerUnregistered) {
notification_context->WriteNotificationData(
next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
origin, notification_database_data,
- base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidWriteNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -493,8 +536,8 @@ TEST_F(PlatformNotificationContextTest, ServiceWorkerUnregistered) {
// And verify that the associated notification has indeed been dropped.
notification_context->ReadNotificationDataAndRecordInteraction(
notification_id(), origin, PlatformNotificationContext::Interaction::NONE,
- base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidReadNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -514,8 +557,8 @@ TEST_F(PlatformNotificationContextTest, DestroyDatabaseOnStorageWiped) {
context->WriteNotificationData(
next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
origin, notification_database_data,
- base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidWriteNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -532,8 +575,8 @@ TEST_F(PlatformNotificationContextTest, DestroyDatabaseOnStorageWiped) {
// be the case when OnStorageWiped gets called in production.
context->ReadNotificationDataAndRecordInteraction(
notification_id(), origin, PlatformNotificationContext::Interaction::NONE,
- base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidReadNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -556,8 +599,8 @@ TEST_F(PlatformNotificationContextTest, DestroyOnDiskDatabase) {
context->ReadNotificationDataAndRecordInteraction(
"invalid-notification-id", GURL("https://example.com"),
PlatformNotificationContext::Interaction::NONE,
- base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidReadNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -599,8 +642,9 @@ TEST_F(PlatformNotificationContextTest, ReadAllServiceWorkerDataFilled) {
context->WriteNotificationData(
next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
origin, notification_database_data,
- base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
- base::Unretained(this)));
+ base::BindOnce(
+ &PlatformNotificationContextTest::DidWriteNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -640,8 +684,8 @@ TEST_F(PlatformNotificationContextTest, SynchronizeNotifications) {
context->WriteNotificationData(
next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
origin, notification_database_data,
- base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidWriteNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(success());
@@ -661,8 +705,8 @@ TEST_F(PlatformNotificationContextTest, SynchronizeNotifications) {
context->ReadNotificationDataAndRecordInteraction(
notification_id(), origin,
PlatformNotificationContext::Interaction::CLOSED,
- base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
- base::Unretained(this)));
+ base::BindOnce(&PlatformNotificationContextTest::DidReadNotificationData,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/notifications/platform_notification_service_proxy.cc b/chromium/content/browser/notifications/platform_notification_service_proxy.cc
index 1e65ea4bc03..41c4ac8270c 100644
--- a/chromium/content/browser/notifications/platform_notification_service_proxy.cc
+++ b/chromium/content/browser/notifications/platform_notification_service_proxy.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/task/post_task.h"
+#include "content/browser/notifications/devtools_event_logging.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/content_browser_client.h"
@@ -21,13 +22,25 @@ PlatformNotificationServiceProxy::PlatformNotificationServiceProxy(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
BrowserContext* browser_context)
: service_worker_context_(service_worker_context),
+ browser_context_(browser_context),
notification_service_(
GetContentClient()->browser()->GetPlatformNotificationService(
browser_context)),
+ weak_ptr_factory_ui_(this),
weak_ptr_factory_io_(this) {}
PlatformNotificationServiceProxy::~PlatformNotificationServiceProxy() = default;
+void PlatformNotificationServiceProxy::Shutdown() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ weak_ptr_factory_ui_.InvalidateWeakPtrs();
+}
+
+base::WeakPtr<PlatformNotificationServiceProxy>
+PlatformNotificationServiceProxy::AsWeakPtr() {
+ return weak_ptr_factory_ui_.GetWeakPtr();
+}
+
void PlatformNotificationServiceProxy::DoDisplayNotification(
const NotificationDatabaseData& data,
const GURL& service_worker_scope,
@@ -38,6 +51,8 @@ void PlatformNotificationServiceProxy::DoDisplayNotification(
data.notification_id, service_worker_scope, data.origin,
data.notification_data,
data.notification_resources.value_or(blink::NotificationResources()));
+ notifications::LogNotificationDisplayedEventToDevTools(browser_context_,
+ data);
}
std::move(callback).Run(/* success= */ true, data.notification_id);
}
@@ -115,6 +130,27 @@ void PlatformNotificationServiceProxy::DoScheduleTrigger(base::Time timestamp) {
notification_service_->ScheduleTrigger(timestamp);
}
+void PlatformNotificationServiceProxy::ScheduleNotification(
+ const NotificationDatabaseData& data) {
+ DCHECK(data.notification_data.show_trigger_timestamp.has_value());
+ if (!notification_service_)
+ return;
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
+ base::BindOnce(&PlatformNotificationServiceProxy::DoScheduleNotification,
+ AsWeakPtr(), data));
+}
+
+void PlatformNotificationServiceProxy::DoScheduleNotification(
+ const NotificationDatabaseData& data) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ base::Time show_trigger_timestamp =
+ data.notification_data.show_trigger_timestamp.value();
+ notifications::LogNotificationScheduledEventToDevTools(
+ browser_context_, data, show_trigger_timestamp);
+ notification_service_->ScheduleTrigger(show_trigger_timestamp);
+}
+
base::Time PlatformNotificationServiceProxy::GetNextTrigger() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!notification_service_)
@@ -130,4 +166,24 @@ void PlatformNotificationServiceProxy::RecordNotificationUkmEvent(
notification_service_->RecordNotificationUkmEvent(data);
}
+bool PlatformNotificationServiceProxy::ShouldLogClose(const GURL& origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return notifications::ShouldLogNotificationEventToDevTools(browser_context_,
+ origin);
+}
+
+void PlatformNotificationServiceProxy::LogClose(
+ const NotificationDatabaseData& data) {
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI, base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&PlatformNotificationServiceProxy::DoLogClose, AsWeakPtr(),
+ data));
+}
+
+void PlatformNotificationServiceProxy::DoLogClose(
+ const NotificationDatabaseData& data) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ notifications::LogNotificationClosedEventToDevTools(browser_context_, data);
+}
+
} // namespace content
diff --git a/chromium/content/browser/notifications/platform_notification_service_proxy.h b/chromium/content/browser/notifications/platform_notification_service_proxy.h
index 2989f332532..1d0693c4c2d 100644
--- a/chromium/content/browser/notifications/platform_notification_service_proxy.h
+++ b/chromium/content/browser/notifications/platform_notification_service_proxy.h
@@ -28,8 +28,7 @@ class PlatformNotificationService;
class ServiceWorkerContextWrapper;
class ServiceWorkerRegistration;
-class CONTENT_EXPORT PlatformNotificationServiceProxy
- : public base::SupportsWeakPtr<PlatformNotificationServiceProxy> {
+class CONTENT_EXPORT PlatformNotificationServiceProxy {
public:
using DisplayResultCallback =
base::OnceCallback<void(bool /* success */,
@@ -41,6 +40,13 @@ class CONTENT_EXPORT PlatformNotificationServiceProxy
~PlatformNotificationServiceProxy();
+ // To be called when the |browser_context_| has been shutdown. This
+ // invalidates all weak pointers. Must be called on the UI thread.
+ void Shutdown();
+
+ // Gets a weak pointer to be used on the UI thread.
+ base::WeakPtr<PlatformNotificationServiceProxy> AsWeakPtr();
+
// Displays a notification with |data| and calls |callback| with the result.
// This will verify against the given |service_worker_context_| if available.
void DisplayNotification(const NotificationDatabaseData& data,
@@ -52,6 +58,9 @@ class CONTENT_EXPORT PlatformNotificationServiceProxy
// Schedules a notification trigger for |timestamp|.
void ScheduleTrigger(base::Time timestamp);
+ // Schedules a notification with |data|.
+ void ScheduleNotification(const NotificationDatabaseData& data);
+
// Gets the next notification trigger or base::Time::Max if none set. Must be
// called on the UI thread.
base::Time GetNextTrigger();
@@ -59,6 +68,13 @@ class CONTENT_EXPORT PlatformNotificationServiceProxy
// Records a given notification to UKM. Must be called on the UI thread.
void RecordNotificationUkmEvent(const NotificationDatabaseData& data);
+ // Returns if we should log a notification close event by calling LogClose.
+ // Must be called on the UI thread.
+ bool ShouldLogClose(const GURL& origin);
+
+ // Logs the event of closing a notification.
+ void LogClose(const NotificationDatabaseData& data);
+
private:
// Actually calls |notification_service_| to display the notification after
// verifying the |service_worker_scope|. Must be called on the UI thread.
@@ -74,6 +90,14 @@ class CONTENT_EXPORT PlatformNotificationServiceProxy
// called on the UI thread.
void DoScheduleTrigger(base::Time timestamp);
+ // Actually calls |notification_service_| to schedule a notification. Must be
+ // called on the UI thread.
+ void DoScheduleNotification(const NotificationDatabaseData& data);
+
+ // Actually logs the event of closing a notification. Must be called on the UI
+ // thread.
+ void DoLogClose(const NotificationDatabaseData& data);
+
// Verifies that the service worker exists and is valid for the given
// notification origin.
void VerifyServiceWorkerScope(
@@ -83,7 +107,9 @@ class CONTENT_EXPORT PlatformNotificationServiceProxy
scoped_refptr<ServiceWorkerRegistration> registration);
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+ BrowserContext* browser_context_;
PlatformNotificationService* notification_service_;
+ base::WeakPtrFactory<PlatformNotificationServiceProxy> weak_ptr_factory_ui_;
base::WeakPtrFactory<PlatformNotificationServiceProxy> weak_ptr_factory_io_;
DISALLOW_COPY_AND_ASSIGN(PlatformNotificationServiceProxy);
diff --git a/chromium/content/browser/ns_view_bridge_factory_host.mm b/chromium/content/browser/ns_view_bridge_factory_host.mm
deleted file mode 100644
index c1c59669e36..00000000000
--- a/chromium/content/browser/ns_view_bridge_factory_host.mm
+++ /dev/null
@@ -1,51 +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/public/browser/ns_view_bridge_factory_host.h"
-
-#include "base/no_destructor.h"
-
-namespace content {
-
-namespace {
-
-using HostIdToFactoryMap = std::map<uint64_t, NSViewBridgeFactoryHost*>;
-
-HostIdToFactoryMap* GetHostIdToFactoryMap() {
- static base::NoDestructor<HostIdToFactoryMap> instance;
- return instance.get();
-}
-
-} // namespace
-
-// static
-const uint64_t NSViewBridgeFactoryHost::kLocalDirectHostId = -1;
-
-// static
-NSViewBridgeFactoryHost* NSViewBridgeFactoryHost::GetFromHostId(
- uint64_t host_id) {
- auto found = GetHostIdToFactoryMap()->find(host_id);
- if (found == GetHostIdToFactoryMap()->end())
- return nullptr;
- return found->second;
-}
-
-NSViewBridgeFactoryHost::NSViewBridgeFactoryHost(
- mojom::NSViewBridgeFactoryAssociatedRequest* request,
- uint64_t host_id)
- : host_id_(host_id) {
- *request = mojo::MakeRequest(&factory_);
- DCHECK(!GetHostIdToFactoryMap()->count(host_id_));
- GetHostIdToFactoryMap()->insert(std::make_pair(host_id_, this));
-}
-
-NSViewBridgeFactoryHost::~NSViewBridgeFactoryHost() {
- GetHostIdToFactoryMap()->erase(host_id_);
-}
-
-mojom::NSViewBridgeFactory* NSViewBridgeFactoryHost::GetFactory() {
- return factory_.get();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/oop_browsertest.cc b/chromium/content/browser/oop_browsertest.cc
index 83c72238d52..0b7c5bf444c 100644
--- a/chromium/content/browser/oop_browsertest.cc
+++ b/chromium/content/browser/oop_browsertest.cc
@@ -22,7 +22,6 @@
#include "gpu/config/gpu_switches.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/gl/gl_switches.h"
@@ -37,10 +36,7 @@ class OOPBrowserTest : public ContentBrowserTest {
command_line->AppendSwitch(switches::kEnableGpuRasterization);
command_line->AppendSwitch(switches::kEnablePixelOutputInTests);
command_line->AppendSwitch(switches::kEnableOopRasterization);
-
- const bool use_gpu_in_tests = !features::IsMultiProcessMash();
- if (use_gpu_in_tests)
- command_line->AppendSwitch(switches::kUseGpuInTests);
+ command_line->AppendSwitch(switches::kUseGpuInTests);
}
void VerifyVisualStateUpdated(const base::Closure& done_cb,
diff --git a/chromium/content/browser/origin_trials/OWNERS b/chromium/content/browser/origin_trials/OWNERS
new file mode 100644
index 00000000000..73686a788f2
--- /dev/null
+++ b/chromium/content/browser/origin_trials/OWNERS
@@ -0,0 +1 @@
+file://third_party/blink/common/origin_trials/OWNERS
diff --git a/chromium/content/browser/origin_trials/origin_trials_browsertest.cc b/chromium/content/browser/origin_trials/origin_trials_browsertest.cc
new file mode 100644
index 00000000000..df382c0d463
--- /dev/null
+++ b/chromium/content/browser/origin_trials/origin_trials_browsertest.cc
@@ -0,0 +1,129 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/strings/strcat.h"
+#include "base/test/bind_test_util.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/url_loader_interceptor.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/common/shell_switches.h"
+
+using content::URLLoaderInterceptor;
+
+namespace {
+constexpr char kBaseDataDir[] = "content/test/data/origin_trials/";
+
+void NavigateViaRenderer(content::WebContents* web_contents, const GURL& url) {
+ EXPECT_TRUE(
+ content::ExecJs(web_contents->GetMainFrame(),
+ base::StrCat({"location.href='", url.spec(), "';"})));
+ // Enqueue a no-op script execution, which will block until the navigation
+ // initiated above completes.
+ EXPECT_TRUE(content::ExecJs(web_contents->GetMainFrame(), "true"));
+ EXPECT_TRUE(content::WaitForLoadStop(web_contents));
+ EXPECT_EQ(web_contents->GetLastCommittedURL(), url);
+}
+
+} // namespace
+
+namespace content {
+
+class OriginTrialsBrowserTest : public content::ContentBrowserTest {
+ public:
+ OriginTrialsBrowserTest() : ContentBrowserTest() {}
+ ~OriginTrialsBrowserTest() override {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ ContentBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitch(switches::kExposeInternalsForTesting);
+ }
+
+ void SetUpOnMainThread() override {
+ ContentBrowserTest::SetUpOnMainThread();
+
+ // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, since
+ // the origin trial token in the response is associated with a fixed
+ // origin, whereas EmbeddedTestServer serves content on a random port.
+ url_loader_interceptor_ =
+ std::make_unique<URLLoaderInterceptor>(base::BindLambdaForTesting(
+ [&](URLLoaderInterceptor::RequestParams* params) -> bool {
+ URLLoaderInterceptor::WriteResponse(
+ base::StrCat(
+ {kBaseDataDir, params->url_request.url.path_piece()}),
+ params->client.get());
+ return true;
+ }));
+ }
+
+ void TearDownOnMainThread() override {
+ url_loader_interceptor_.reset();
+ ContentBrowserTest::TearDownOnMainThread();
+ }
+
+ private:
+ std::unique_ptr<URLLoaderInterceptor> url_loader_interceptor_;
+
+ DISALLOW_COPY_AND_ASSIGN(OriginTrialsBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(OriginTrialsBrowserTest, Basic) {
+ NavigateToURL(shell(), GURL("https://example.test/basic.html"));
+ // Ensure we can invoke normalMethod(), which is only available when the
+ // Frobulate OT is enabled.
+ EXPECT_TRUE(content::ExecJs(shell()->web_contents()->GetMainFrame(),
+ "internals.originTrialsTest().normalMethod();"));
+}
+
+IN_PROC_BROWSER_TEST_F(OriginTrialsBrowserTest,
+ NonNavigationTrialNotActivatedAcrossNavigations) {
+ NavigateToURL(shell(), GURL("https://example.test/basic.html"));
+ EXPECT_TRUE(content::ExecJs(shell()->web_contents()->GetMainFrame(),
+ "internals.originTrialsTest().normalMethod();"));
+ NavigateViaRenderer(shell()->web_contents(),
+ GURL("https://other.test/notrial.html"));
+ EXPECT_TRUE(content::ExecJs(shell()->web_contents()->GetMainFrame(),
+ "internals.originTrialsTest();"));
+ EXPECT_FALSE(content::ExecJs(shell()->web_contents()->GetMainFrame(),
+ "internals.originTrialsTest().normalMethod();"));
+}
+
+IN_PROC_BROWSER_TEST_F(OriginTrialsBrowserTest, Navigation) {
+ NavigateToURL(shell(), GURL("https://example.test/navigation.html"));
+ // Ensure we can invoke navigationMethod(), which is only available when the
+ // FrobulateNavigation OT is enabled.
+ EXPECT_TRUE(
+ content::ExecJs(shell()->web_contents()->GetMainFrame(),
+ "internals.originTrialsTest().navigationMethod();"));
+}
+
+IN_PROC_BROWSER_TEST_F(OriginTrialsBrowserTest,
+ NavigationTrialActivatedAcrossNavigations) {
+ NavigateToURL(shell(), GURL("https://example.test/navigation.html"));
+ EXPECT_TRUE(
+ content::ExecJs(shell()->web_contents()->GetMainFrame(),
+ "internals.originTrialsTest().navigationMethod();"));
+
+ NavigateViaRenderer(shell()->web_contents(),
+ GURL("https://other.test/notrial.html"));
+ // Ensure we can invoke navigationMethod() after having navigated from
+ // navigation.html, since navigationMethod() is exposed via a cross-navigation
+ // OT.
+ EXPECT_TRUE(
+ content::ExecJs(shell()->web_contents()->GetMainFrame(),
+ "internals.originTrialsTest().navigationMethod();"));
+
+ NavigateViaRenderer(shell()->web_contents(),
+ GURL("https://other.test/basic.html"));
+ // Ensure we can't invoke navigationMethod() after a second navigation, as
+ // cross-navigation OTs should only be forwarded to immediate navigations from
+ // where the trial was activated.
+ EXPECT_FALSE(
+ content::ExecJs(shell()->web_contents()->GetMainFrame(),
+ "internals.originTrialsTest().navigationMethod();"));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/payments/payment_app_info_fetcher.cc b/chromium/content/browser/payments/payment_app_info_fetcher.cc
index 0a10a013a5e..2ccd84c68ae 100644
--- a/chromium/content/browser/payments/payment_app_info_fetcher.cc
+++ b/chromium/content/browser/payments/payment_app_info_fetcher.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/task/post_task.h"
+#include "components/payments/content/icon/icon_size.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -238,13 +239,6 @@ void PaymentAppInfoFetcher::SelfDeleteFetcher::FetchPaymentAppManifestCallback(
&(fetched_payment_app_info_->name));
}
- // TODO(gogerald): Choose appropriate icon size dynamically on different
- // platforms.
- // Here we choose a large ideal icon size to be big enough for all platforms.
- // Note that we only scale down for this icon size but not scale up.
- const int kPaymentAppIdealIconSize = 0xFFFF;
- const int kPaymentAppMinimumIconSize = 0;
-
if (manifest.icons.empty()) {
WarnIfPossible(
"Unable to download the payment handler's icon, because the web app "
@@ -256,8 +250,22 @@ void PaymentAppInfoFetcher::SelfDeleteFetcher::FetchPaymentAppManifestCallback(
return;
}
+ WebContents* web_contents = web_contents_helper_->web_contents();
+ if (!web_contents) {
+ LOG(WARNING) << "Unable to download the payment handler's icon because no "
+ "renderer was found, possibly because the page was closed "
+ "or navigated away during installation. User may not "
+ "recognize this payment handler in UI, because it will be "
+ "labeled only by its name and origin.";
+ RunCallbackAndDestroy();
+ return;
+ }
+ gfx::NativeView native_view = web_contents->GetNativeView();
+
icon_url_ = blink::ManifestIconSelector::FindBestMatchingIcon(
- manifest.icons, kPaymentAppIdealIconSize, kPaymentAppMinimumIconSize,
+ manifest.icons,
+ payments::IconSizeCalculator::IdealIconHeight(native_view),
+ payments::IconSizeCalculator::MinimumIconHeight(),
ManifestIconDownloader::kMaxWidthToHeightRatio,
blink::Manifest::ImageResource::Purpose::ANY);
if (!icon_url_.is_valid()) {
@@ -271,19 +279,10 @@ void PaymentAppInfoFetcher::SelfDeleteFetcher::FetchPaymentAppManifestCallback(
return;
}
- if (!web_contents_helper_->web_contents()) {
- LOG(WARNING) << "Unable to download the payment handler's icon because no "
- "renderer was found, possibly because the page was closed "
- "or navigated away during installation. User may not "
- "recognize this payment handler in UI, because it will be "
- "labeled only by its name and origin.";
- RunCallbackAndDestroy();
- return;
- }
-
bool can_download = ManifestIconDownloader::Download(
- web_contents_helper_->web_contents(), icon_url_, kPaymentAppIdealIconSize,
- kPaymentAppMinimumIconSize,
+ web_contents, icon_url_,
+ payments::IconSizeCalculator::IdealIconHeight(native_view),
+ payments::IconSizeCalculator::MinimumIconHeight(),
base::BindOnce(&PaymentAppInfoFetcher::SelfDeleteFetcher::OnIconFetched,
base::Unretained(this)),
false /* square_only */);
diff --git a/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc b/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
index c1e109b774f..d0d47d2d944 100644
--- a/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
+++ b/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/task/post_task.h"
+#include "components/payments/content/icon/icon_size.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -23,13 +24,6 @@
namespace content {
namespace {
-// TODO(zino): Choose appropriate icon size dynamically on different platforms.
-// Here we choose a large ideal icon size to be big enough for all platforms.
-// Note that we only scale down for this icon size but not scale up.
-// Please see: https://crbug.com/763886
-const int kPaymentAppIdealIconSize = 0xFFFF;
-const int kPaymentAppMinimumIconSize = 0;
-
void DownloadBestMatchingIcon(
WebContents* web_contents,
const std::vector<blink::Manifest::ImageResource>& icons,
@@ -75,11 +69,20 @@ void DownloadBestMatchingIcon(
callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (web_contents == nullptr) {
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(callback), std::string()));
+ return;
+ }
+
+ gfx::NativeView native_view = web_contents->GetNativeView();
GURL icon_url = blink::ManifestIconSelector::FindBestMatchingIcon(
- icons, kPaymentAppIdealIconSize, kPaymentAppMinimumIconSize,
+ icons, payments::IconSizeCalculator::IdealIconHeight(native_view),
+ payments::IconSizeCalculator::MinimumIconHeight(),
ManifestIconDownloader::kMaxWidthToHeightRatio,
blink::Manifest::ImageResource::Purpose::ANY);
- if (web_contents == nullptr || !icon_url.is_valid()) {
+ if (!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
// checked whether they are valid in renderer side. So, if the icon url is
@@ -98,8 +101,9 @@ void DownloadBestMatchingIcon(
}
bool can_download_icon = ManifestIconDownloader::Download(
- web_contents, icon_url, kPaymentAppIdealIconSize,
- kPaymentAppMinimumIconSize,
+ web_contents, icon_url,
+ payments::IconSizeCalculator::IdealIconHeight(native_view),
+ payments::IconSizeCalculator::MinimumIconHeight(),
base::BindOnce(&OnIconFetched, web_contents, copy_icons,
std::move(callback)),
false /* square_only */);
diff --git a/chromium/content/browser/permissions/permission_controller_impl.cc b/chromium/content/browser/permissions/permission_controller_impl.cc
index 9025fcf33e1..6ab49b2d857 100644
--- a/chromium/content/browser/permissions/permission_controller_impl.cc
+++ b/chromium/content/browser/permissions/permission_controller_impl.cc
@@ -7,6 +7,7 @@
#include "content/browser/permissions/permission_controller_impl.h"
#include "base/bind.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/permission_controller_delegate.h"
@@ -29,6 +30,60 @@ blink::mojom::PermissionStatus GetPermissionOverrideStatus(
return blink::mojom::PermissionStatus::GRANTED;
}
+base::Optional<blink::scheduler::WebSchedulerTrackedFeature>
+PermissionToSchedulingFeature(PermissionType permission_name) {
+ switch (permission_name) {
+ case PermissionType::GEOLOCATION:
+ return blink::scheduler::WebSchedulerTrackedFeature::
+ kRequestedGeolocationPermission;
+ case PermissionType::NOTIFICATIONS:
+ return blink::scheduler::WebSchedulerTrackedFeature::
+ kRequestedNotificationsPermission;
+ case PermissionType::MIDI:
+ case PermissionType::MIDI_SYSEX:
+ return blink::scheduler::WebSchedulerTrackedFeature::
+ kRequestedMIDIPermission;
+ case PermissionType::AUDIO_CAPTURE:
+ return blink::scheduler::WebSchedulerTrackedFeature::
+ kRequestedAudioCapturePermission;
+ case PermissionType::VIDEO_CAPTURE:
+ return blink::scheduler::WebSchedulerTrackedFeature::
+ kRequestedVideoCapturePermission;
+ case PermissionType::SENSORS:
+ return blink::scheduler::WebSchedulerTrackedFeature::
+ kRequestedSensorsPermission;
+ case PermissionType::BACKGROUND_SYNC:
+ case PermissionType::BACKGROUND_FETCH:
+ case PermissionType::PERIODIC_BACKGROUND_SYNC:
+ return blink::scheduler::WebSchedulerTrackedFeature::
+ kRequestedBackgroundWorkPermission;
+ case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
+ case PermissionType::DURABLE_STORAGE:
+ case PermissionType::FLASH:
+ case PermissionType::ACCESSIBILITY_EVENTS:
+ case PermissionType::CLIPBOARD_READ:
+ case PermissionType::CLIPBOARD_WRITE:
+ case PermissionType::PAYMENT_HANDLER:
+ case PermissionType::IDLE_DETECTION:
+ case PermissionType::NUM:
+ return base::nullopt;
+ }
+}
+
+void NotifySchedulerAboutPermissionRequest(RenderFrameHost* render_frame_host,
+ PermissionType permission_name) {
+ DCHECK(render_frame_host);
+
+ base::Optional<blink::scheduler::WebSchedulerTrackedFeature> feature =
+ PermissionToSchedulingFeature(permission_name);
+
+ if (!feature)
+ return;
+
+ static_cast<RenderFrameHostImpl*>(render_frame_host)
+ ->OnSchedulerTrackedFeatureUsed(feature.value());
+}
+
} // namespace
PermissionControllerImpl::PermissionControllerImpl(
@@ -121,6 +176,8 @@ int PermissionControllerImpl::RequestPermission(
const GURL& requesting_origin,
bool user_gesture,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback) {
+ NotifySchedulerAboutPermissionRequest(render_frame_host, permission);
+
auto it = devtools_permission_overrides_.find(requesting_origin.GetOrigin());
if (it != devtools_permission_overrides_.end()) {
callback.Run(GetPermissionOverrideStatus(it->second, permission));
@@ -144,6 +201,9 @@ int PermissionControllerImpl::RequestPermissions(
bool user_gesture,
const base::Callback<
void(const std::vector<blink::mojom::PermissionStatus>&)>& callback) {
+ for (PermissionType permission : permissions)
+ NotifySchedulerAboutPermissionRequest(render_frame_host, permission);
+
auto it = devtools_permission_overrides_.find(requesting_origin.GetOrigin());
if (it != devtools_permission_overrides_.end()) {
std::vector<blink::mojom::PermissionStatus> result;
diff --git a/chromium/content/browser/permissions/permission_service_impl.cc b/chromium/content/browser/permissions/permission_service_impl.cc
index 6d5525503ad..d698c592c82 100644
--- a/chromium/content/browser/permissions/permission_service_impl.cc
+++ b/chromium/content/browser/permissions/permission_service_impl.cc
@@ -88,6 +88,9 @@ bool PermissionDescriptorToPermissionType(
case PermissionName::IDLE_DETECTION:
*permission_type = PermissionType::IDLE_DETECTION;
return true;
+ case PermissionName::PERIODIC_BACKGROUND_SYNC:
+ *permission_type = PermissionType::PERIODIC_BACKGROUND_SYNC;
+ return true;
}
NOTREACHED();
diff --git a/chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc b/chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc
deleted file mode 100644
index 43bd0924785..00000000000
--- a/chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc
+++ /dev/null
@@ -1,63 +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/picture_in_picture/overlay_surface_embedder.h"
-
-#include "ui/compositor/layer.h"
-
-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);
-
- // The frame provided by the parent window's layer needs to show through
- // |video_layer_|.
- video_layer_->SetFillsBoundsOpaquely(false);
- // |video_layer_| bounds are set with the (0, 0) origin point. The
- // positioning of |window_| is dictated by itself.
- video_layer_->SetBounds(
- gfx::Rect(gfx::Point(0, 0), window_->GetBounds().size()));
-
- // 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::SetSurfaceId(const viz::SurfaceId& surface_id) {
- video_layer_ = window_->GetVideoLayer();
- // SurfaceInfo has information about the embedded surface.
- video_layer_->SetShowSurface(surface_id, window_->GetBounds().size(),
- SK_ColorBLACK,
- cc::DeadlinePolicy::UseDefaultDeadline(),
- true /* stretch_content_to_fill_bounds */);
-}
-
-void OverlaySurfaceEmbedder::UpdateLayerBounds() {
- // Update the size of window background.
- window_background_layer_ = window_->GetWindowBackgroundLayer();
- window_background_layer_->SetBounds(
- gfx::Rect(gfx::Point(0, 0), window_->GetBounds().size()));
-
- // 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
deleted file mode 100644
index 9307f38e8d8..00000000000
--- a/chromium/content/browser/picture_in_picture/overlay_surface_embedder.h
+++ /dev/null
@@ -1,47 +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_PICTURE_IN_PICTURE_OVERLAY_SURFACE_EMBEDDER_H_
-#define CONTENT_BROWSER_PICTURE_IN_PICTURE_OVERLAY_SURFACE_EMBEDDER_H_
-
-#include <memory>
-
-#include "content/public/browser/overlay_window.h"
-
-namespace viz {
-class SurfaceId;
-}
-
-namespace content {
-
-// Embed a surface into the OverlayWindow to show content. Responsible for
-// setting up the surface layers that contain content to show on the
-// OverlayWindow.
-class OverlaySurfaceEmbedder {
- public:
- explicit OverlaySurfaceEmbedder(OverlayWindow* window);
- ~OverlaySurfaceEmbedder();
-
- void SetSurfaceId(const viz::SurfaceId&);
- void UpdateLayerBounds();
-
- private:
- // The window which embeds the client. Weak pointer since the
- // PictureInPictureWindowController owns the window.
- OverlayWindow* window_;
-
- // Contains the client's content.
- std::unique_ptr<ui::Layer> surface_layer_;
-
- // Owned by the OverlayWindow implementation.
- // These are set in the constructor.
- ui::Layer* window_background_layer_ = nullptr;
- ui::Layer* video_layer_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(OverlaySurfaceEmbedder);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_PICTURE_IN_PICTURE_OVERLAY_SURFACE_EMBEDDER_H_
diff --git a/chromium/content/browser/picture_in_picture/picture_in_picture_service_impl.cc b/chromium/content/browser/picture_in_picture/picture_in_picture_service_impl.cc
index fe51da36595..2d826434f34 100644
--- a/chromium/content/browser/picture_in_picture/picture_in_picture_service_impl.cc
+++ b/chromium/content/browser/picture_in_picture/picture_in_picture_service_impl.cc
@@ -6,8 +6,7 @@
#include <utility>
-#include "content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h"
-#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/browser/picture_in_picture/picture_in_picture_session.h"
namespace content {
@@ -32,66 +31,17 @@ void PictureInPictureServiceImpl::StartSession(
const gfx::Size& natural_size,
bool show_play_pause_button,
bool show_mute_button,
+ blink::mojom::PictureInPictureSessionObserverPtr observer,
StartSessionCallback callback) {
- player_id_ = MediaPlayerId(render_frame_host_, player_id);
+ blink::mojom::PictureInPictureSessionPtr session_ptr;
- auto* pip_controller = GetController();
- if (pip_controller)
- pip_controller->set_service(this);
+ gfx::Size window_size;
+ active_session_.reset(new PictureInPictureSession(
+ this, MediaPlayerId(render_frame_host_, player_id), surface_id,
+ natural_size, show_play_pause_button, show_mute_button,
+ mojo::MakeRequest(&session_ptr), std::move(observer), &window_size));
- gfx::Size window_size = web_contents_impl()->EnterPictureInPicture(
- surface_id.value(), natural_size);
-
- if (pip_controller) {
- pip_controller->SetAlwaysHidePlayPauseButton(show_play_pause_button);
- pip_controller->SetAlwaysHideMuteButton(show_mute_button);
- }
-
- std::move(callback).Run(window_size);
-}
-
-void PictureInPictureServiceImpl::EndSession(EndSessionCallback callback) {
- DCHECK(player_id_);
-
- ExitPictureInPictureInternal();
-
- std::move(callback).Run();
-}
-
-void PictureInPictureServiceImpl::UpdateSession(
- uint32_t player_id,
- const base::Optional<viz::SurfaceId>& surface_id,
- const gfx::Size& natural_size,
- bool show_play_pause_button,
- bool show_mute_button) {
- player_id_ = MediaPlayerId(render_frame_host_, player_id);
-
- // The PictureInPictureWindowController instance may not have been created by
- // the embedder.
- if (auto* pip_controller = GetController()) {
- pip_controller->EmbedSurface(surface_id.value(), natural_size);
- pip_controller->SetAlwaysHidePlayPauseButton(show_play_pause_button);
- pip_controller->SetAlwaysHideMuteButton(show_mute_button);
- pip_controller->set_service(this);
- }
-}
-
-void PictureInPictureServiceImpl::SetDelegate(
- blink::mojom::PictureInPictureDelegatePtr delegate) {
- delegate.set_connection_error_handler(
- base::BindOnce(&PictureInPictureServiceImpl::OnDelegateDisconnected,
- // delegate is held by |this|.
- base::Unretained(this)));
-
- if (delegate_)
- mojo::ReportBadMessage("SetDelegate() should only be called once.");
-
- delegate_ = std::move(delegate);
-}
-
-void PictureInPictureServiceImpl::NotifyWindowResized(const gfx::Size& size) {
- if (delegate_)
- delegate_->PictureInPictureWindowSizeChanged(size);
+ std::move(callback).Run(std::move(session_ptr), window_size);
}
PictureInPictureServiceImpl::PictureInPictureServiceImpl(
@@ -101,35 +51,10 @@ PictureInPictureServiceImpl::PictureInPictureServiceImpl(
render_frame_host_(render_frame_host) {}
PictureInPictureServiceImpl::~PictureInPictureServiceImpl() {
- if (player_id_)
- ExitPictureInPictureInternal();
- if (GetController())
- GetController()->set_service(nullptr);
-}
-
-PictureInPictureWindowControllerImpl*
-PictureInPictureServiceImpl::GetController() {
- return PictureInPictureWindowControllerImpl::GetOrCreateForWebContents(
- web_contents_impl());
-}
-
-void PictureInPictureServiceImpl::OnDelegateDisconnected() {
- delegate_ = nullptr;
-}
-
-void PictureInPictureServiceImpl::ExitPictureInPictureInternal() {
- web_contents_impl()->ExitPictureInPicture();
-
- // Reset must happen after notifying the WebContents because it may interact
- // with it.
- player_id_.reset();
-
- if (auto* controller = GetController())
- controller->set_service(nullptr);
-}
-
-WebContentsImpl* PictureInPictureServiceImpl::web_contents_impl() {
- return static_cast<WebContentsImpl*>(web_contents());
+ // If the service is destroyed because the frame was destroyed, the session
+ // may still be active and it has to be shutdown before its dtor runs.
+ if (active_session_)
+ active_session_->Shutdown();
}
} // namespace content
diff --git a/chromium/content/browser/picture_in_picture/picture_in_picture_service_impl.h b/chromium/content/browser/picture_in_picture/picture_in_picture_service_impl.h
index d9cab4af5ec..2d326331244 100644
--- a/chromium/content/browser/picture_in_picture/picture_in_picture_service_impl.h
+++ b/chromium/content/browser/picture_in_picture/picture_in_picture_service_impl.h
@@ -8,17 +8,17 @@
#include "base/containers/unique_ptr_adapters.h"
#include "content/common/content_export.h"
#include "content/public/browser/frame_service_base.h"
-#include "content/public/browser/media_player_id.h"
#include "third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom.h"
namespace content {
-class PictureInPictureWindowControllerImpl;
+class PictureInPictureSession;
// Receives Picture-in-Picture messages from a given RenderFrame. There is one
-// PictureInPictureServiceImpl per RenderFrameHost. It talks directly to the
-// PictureInPictureWindowControllerImpl. Only one service interacts with the
-// window at a given time.
+// PictureInPictureServiceImpl per RenderFrameHost. The service gets a hold of
+// a PictureInPictureSession to which it delegates most of the interactions with
+// the rest of the Picture-in-Picture classes such as
+// PictureInPictureWindowController.
class CONTENT_EXPORT PictureInPictureServiceImpl final
: public content::FrameServiceBase<blink::mojom::PictureInPictureService> {
public:
@@ -34,44 +34,23 @@ class CONTENT_EXPORT PictureInPictureServiceImpl final
const gfx::Size& natural_size,
bool show_play_pause_button,
bool show_mute_button,
+ blink::mojom::PictureInPictureSessionObserverPtr,
StartSessionCallback) final;
- void EndSession(EndSessionCallback) final;
- void UpdateSession(uint32_t player_id,
- const base::Optional<viz::SurfaceId>& surface_id,
- const gfx::Size& natural_size,
- bool show_play_pause_button,
- bool show_mute_button) final;
- void SetDelegate(blink::mojom::PictureInPictureDelegatePtr) final;
- void NotifyWindowResized(const gfx::Size&);
-
- // Returns the player that is currently in Picture-in-Picture in the context
- // of the frame associated with the service. Returns nullopt if there are
- // none.
- const base::Optional<MediaPlayerId>& player_id() const { return player_id_; }
- void ResetPlayerId() { player_id_.reset(); }
+ PictureInPictureSession* active_session_for_testing() const {
+ return active_session_.get();
+ }
private:
+ friend class PictureInPictureSession;
+
PictureInPictureServiceImpl(RenderFrameHost*,
blink::mojom::PictureInPictureServiceRequest);
~PictureInPictureServiceImpl() override;
- // Returns the PictureInPictureWindowControllerImpl associated with the
- // WebContents. Can be null.
- PictureInPictureWindowControllerImpl* GetController();
-
- // Callack run when the delegate is disconnected. Only one delegate should be
- // set at any given time.
- void OnDelegateDisconnected();
-
- // Implementation of ExitPictureInPicture without callback handling.
- void ExitPictureInPictureInternal();
-
- WebContentsImpl* web_contents_impl();
-
- blink::mojom::PictureInPictureDelegatePtr delegate_ = nullptr;
RenderFrameHost* render_frame_host_ = nullptr;
- base::Optional<MediaPlayerId> player_id_;
+
+ std::unique_ptr<PictureInPictureSession> active_session_;
DISALLOW_COPY_AND_ASSIGN(PictureInPictureServiceImpl);
};
diff --git a/chromium/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc b/chromium/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
index 09decd2f742..b2603154373 100644
--- a/chromium/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
+++ b/chromium/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
@@ -19,6 +19,20 @@
namespace content {
+class DummyPictureInPictureSessionObserver
+ : public blink::mojom::PictureInPictureSessionObserver {
+ public:
+ DummyPictureInPictureSessionObserver() = default;
+ ~DummyPictureInPictureSessionObserver() final = default;
+
+ // Implementation of PictureInPictureSessionObserver.
+ void OnWindowSizeChanged(const gfx::Size&) final {}
+ void OnStopped() final {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DummyPictureInPictureSessionObserver);
+};
+
class PictureInPictureDelegate : public WebContentsDelegate {
public:
PictureInPictureDelegate() = default;
@@ -48,18 +62,16 @@ class TestOverlayWindow : public OverlayWindow {
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 {}
void SetAlwaysHidePlayPauseButton(bool is_visible) override {}
- ui::Layer* GetWindowBackgroundLayer() override { return nullptr; }
- ui::Layer* GetVideoLayer() override { return nullptr; }
- gfx::Rect GetVideoBounds() override { return gfx::Rect(); }
void SetMutedState(MutedState muted_state) override {}
void SetSkipAdButtonVisibility(bool is_visible) override {}
void SetNextTrackButtonVisibility(bool is_visible) override {}
void SetPreviousTrackButtonVisibility(bool is_visible) override {}
+ void SetSurfaceId(const viz::SurfaceId& surface_id) override {}
+ cc::Layer* GetLayerForTesting() override { return nullptr; }
private:
DISALLOW_COPY_AND_ASSIGN(TestOverlayWindow);
@@ -115,9 +127,14 @@ class PictureInPictureServiceImplTest : public RenderViewHostImplTestHarness {
TEST_F(PictureInPictureServiceImplTest, EnterPictureInPicture) {
const int kPlayerVideoOnlyId = 30;
- // If Picture-in-Picture was never triggered, the media player id would not be
- // set.
- EXPECT_FALSE(service().player_id().has_value());
+ DummyPictureInPictureSessionObserver observer;
+ mojo::Binding<blink::mojom::PictureInPictureSessionObserver>
+ observer_bindings(&observer);
+ blink::mojom::PictureInPictureSessionObserverPtr observer_ptr;
+ observer_bindings.Bind(mojo::MakeRequest(&observer_ptr));
+
+ // If Picture-in-Picture there shouldn't be an active session.
+ EXPECT_FALSE(service().active_session_for_testing());
viz::SurfaceId surface_id =
viz::SurfaceId(viz::FrameSinkId(1, 1),
@@ -129,9 +146,9 @@ TEST_F(PictureInPictureServiceImplTest, EnterPictureInPicture) {
service().StartSession(kPlayerVideoOnlyId, surface_id, gfx::Size(42, 42),
true /* show_play_pause_button */,
- true /* show_mute_button */, base::DoNothing());
- EXPECT_TRUE(service().player_id().has_value());
- EXPECT_EQ(kPlayerVideoOnlyId, service().player_id()->delegate_id);
+ true /* show_mute_button */, std::move(observer_ptr),
+ base::DoNothing());
+ EXPECT_TRUE(service().active_session_for_testing());
// 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
@@ -139,7 +156,7 @@ TEST_F(PictureInPictureServiceImplTest, EnterPictureInPicture) {
contents()->GetMainFrame()->OnMessageReceived(
MediaPlayerDelegateHostMsg_OnMediaDestroyed(
contents()->GetMainFrame()->GetRoutingID(), kPlayerVideoOnlyId));
- EXPECT_TRUE(service().player_id().has_value());
+ EXPECT_TRUE(service().active_session_for_testing());
}
} // namespace content
diff --git a/chromium/content/browser/picture_in_picture/picture_in_picture_session.cc b/chromium/content/browser/picture_in_picture/picture_in_picture_session.cc
new file mode 100644
index 00000000000..0e6c05f506e
--- /dev/null
+++ b/chromium/content/browser/picture_in_picture/picture_in_picture_session.cc
@@ -0,0 +1,117 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/picture_in_picture/picture_in_picture_session.h"
+
+#include "content/browser/picture_in_picture/picture_in_picture_service_impl.h"
+#include "content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+
+namespace content {
+
+PictureInPictureSession::PictureInPictureSession(
+ PictureInPictureServiceImpl* service,
+ const MediaPlayerId& player_id,
+ const base::Optional<viz::SurfaceId>& surface_id,
+ const gfx::Size& natural_size,
+ bool show_play_pause_button,
+ bool show_mute_button,
+ mojo::InterfaceRequest<blink::mojom::PictureInPictureSession> request,
+ blink::mojom::PictureInPictureSessionObserverPtr observer,
+ gfx::Size* window_size)
+ : service_(service),
+ binding_(this, std::move(request)),
+ player_id_(player_id),
+ observer_(std::move(observer)) {
+ binding_.set_connection_error_handler(base::BindOnce(
+ &PictureInPictureSession::OnConnectionError, base::Unretained(this)));
+
+ // TODO(mlamouri): figure out why this can be null and have the method return
+ // a const ref.
+ auto* controller = GetController();
+ if (controller)
+ controller->SetActiveSession(this);
+
+ *window_size = GetWebContentsImpl()->EnterPictureInPicture(surface_id.value(),
+ natural_size);
+
+ if (controller) {
+ controller->SetAlwaysHidePlayPauseButton(show_play_pause_button);
+ controller->SetAlwaysHideMuteButton(show_mute_button);
+ }
+}
+
+PictureInPictureSession::~PictureInPictureSession() {
+ DCHECK(is_stopping_);
+}
+
+void PictureInPictureSession::Stop(StopCallback callback) {
+ StopInternal(std::move(callback));
+}
+
+void PictureInPictureSession::Update(
+ uint32_t player_id,
+ const base::Optional<viz::SurfaceId>& surface_id,
+ const gfx::Size& natural_size,
+ bool show_play_pause_button,
+ bool show_mute_button) {
+ player_id_ = MediaPlayerId(service_->render_frame_host_, player_id);
+
+ // The PictureInPictureWindowController instance may not have been created by
+ // the embedder.
+ if (auto* pip_controller = GetController()) {
+ pip_controller->EmbedSurface(surface_id.value(), natural_size);
+ pip_controller->SetAlwaysHidePlayPauseButton(show_play_pause_button);
+ pip_controller->SetAlwaysHideMuteButton(show_mute_button);
+ pip_controller->SetActiveSession(this);
+ }
+}
+
+void PictureInPictureSession::NotifyWindowResized(const gfx::Size& size) {
+ observer_->OnWindowSizeChanged(size);
+}
+
+void PictureInPictureSession::Shutdown() {
+ if (is_stopping_)
+ return;
+
+ StopInternal(base::NullCallback());
+}
+
+void PictureInPictureSession::StopInternal(StopCallback callback) {
+ DCHECK(!is_stopping_);
+
+ is_stopping_ = true;
+
+ GetWebContentsImpl()->ExitPictureInPicture();
+
+ // `OnStopped()` should only be called if there is no callback to run, as a
+ // contract in the API.
+ if (callback)
+ std::move(callback).Run();
+ else
+ observer_->OnStopped();
+
+ if (auto* controller = GetController())
+ controller->SetActiveSession(nullptr);
+
+ // Reset must happen after everything is done as it will destroy |this|.
+ service_->active_session_.reset();
+}
+
+void PictureInPictureSession::OnConnectionError() {
+ // StopInternal() will self destruct which will close the bindings.
+ StopInternal(base::NullCallback());
+}
+
+WebContentsImpl* PictureInPictureSession::GetWebContentsImpl() {
+ return static_cast<WebContentsImpl*>(service_->web_contents());
+}
+
+PictureInPictureWindowControllerImpl* PictureInPictureSession::GetController() {
+ return PictureInPictureWindowControllerImpl::GetOrCreateForWebContents(
+ GetWebContentsImpl());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/picture_in_picture/picture_in_picture_session.h b/chromium/content/browser/picture_in_picture/picture_in_picture_session.h
new file mode 100644
index 00000000000..7d34db75a23
--- /dev/null
+++ b/chromium/content/browser/picture_in_picture/picture_in_picture_session.h
@@ -0,0 +1,92 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_PICTURE_IN_PICTURE_PICTURE_IN_PICTURE_SESSION_H_
+#define CONTENT_BROWSER_PICTURE_IN_PICTURE_PICTURE_IN_PICTURE_SESSION_H_
+
+#include "content/public/browser/media_player_id.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom.h"
+
+namespace content {
+
+class PictureInPictureServiceImpl;
+class PictureInPictureWindowControllerImpl;
+class WebContentsImpl;
+
+// The PicutreInPictureSession communicates with the
+// PictureInPictureWindowController and the WebContents. It is created by the
+// PictureInPictureService but deletes itself. When created, the session will
+// enter Picture-in-Picture and when deleted, it will automatically exit
+// Picture-in-Picture unless another session became active.
+// The session MUST be stopped before its dtor runs to avoid unexpected
+// deletion.
+class PictureInPictureSession : public blink::mojom::PictureInPictureSession {
+ public:
+ PictureInPictureSession(
+ PictureInPictureServiceImpl* service,
+ const MediaPlayerId& player_id,
+ const base::Optional<viz::SurfaceId>& surface_id,
+ const gfx::Size& natural_size,
+ bool show_play_pause_button,
+ bool show_mute_button,
+ mojo::InterfaceRequest<blink::mojom::PictureInPictureSession> request,
+ blink::mojom::PictureInPictureSessionObserverPtr observer,
+ gfx::Size* window_size);
+ ~PictureInPictureSession() override;
+
+ // blink::mojom::PictureInPictureSession interface.
+ void Stop(StopCallback callback) final;
+ void Update(uint32_t player_id,
+ const base::Optional<viz::SurfaceId>& surface_id,
+ const gfx::Size& natural_size,
+ bool show_play_pause_button,
+ bool show_mute_button) final;
+
+ void NotifyWindowResized(const gfx::Size& size);
+
+ // Returns the player that is currently in Picture-in-Picture. Returns nullopt
+ // if there are none.
+ const base::Optional<MediaPlayerId>& player_id() const { return player_id_; }
+
+ // Shuts down the session. Called by the window controller when the window is
+ // closed.
+ void Shutdown();
+
+ private:
+ PictureInPictureSession() = delete;
+
+ // Exits Picture-in-Picture, notifies the PictureInPictureWindowController of
+ // change of active session and deletes self.
+ void StopInternal(StopCallback callback);
+
+ // Called when the |binding_| hits a connection error.
+ void OnConnectionError();
+
+ // Returns the WebContentsImpl associated with this Picture-in-Picture
+ // session. It relies on the WebContents associated with the |service_|.
+ WebContentsImpl* GetWebContentsImpl();
+
+ // Returns the PictureInPictureWindowControllerImpl associated with the
+ // WebContents. Can be null.
+ PictureInPictureWindowControllerImpl* GetController();
+
+ // Owns |this|.
+ PictureInPictureServiceImpl* service_;
+
+ mojo::Binding<blink::mojom::PictureInPictureSession> binding_;
+
+ base::Optional<MediaPlayerId> player_id_;
+
+ // Whether the session is currently stopping. The final stop of stopping is to
+ // be destroyed so once its set to true it will never be set back to false and
+ // the dtor will check that it's stopping.
+ bool is_stopping_ = false;
+
+ blink::mojom::PictureInPictureSessionObserverPtr observer_ = nullptr;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_PICTURE_IN_PICTURE_PICTURE_IN_PICTURE_SESSION_H_
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 0db14f57298..3a86ab1f5d0 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
@@ -9,8 +9,7 @@
#include "components/viz/common/surfaces/surface_id.h"
#include "content/browser/media/media_web_contents_observer.h"
#include "content/browser/media/session/media_session_impl.h"
-#include "content/browser/picture_in_picture/overlay_surface_embedder.h"
-#include "content/browser/picture_in_picture/picture_in_picture_service_impl.h"
+#include "content/browser/picture_in_picture/picture_in_picture_session.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/media/media_player_delegate_messages.h"
#include "content/public/browser/content_browser_client.h"
@@ -18,7 +17,6 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_client.h"
-#include "ui/compositor/layer.h"
namespace content {
@@ -52,8 +50,7 @@ PictureInPictureWindowControllerImpl::~PictureInPictureWindowControllerImpl() {
return;
initiator_->SetHasPictureInPictureVideo(false);
- OnLeavingPictureInPicture(true /* should_pause_video */,
- true /* should_reset_pip_player */);
+ OnLeavingPictureInPicture(true /* should_pause_video */);
}
PictureInPictureWindowControllerImpl::PictureInPictureWindowControllerImpl(
@@ -97,25 +94,22 @@ gfx::Size PictureInPictureWindowControllerImpl::Show() {
return window_->GetBounds().size();
}
-void PictureInPictureWindowControllerImpl::Close(bool should_pause_video,
- bool should_reset_pip_player) {
+void PictureInPictureWindowControllerImpl::Close(bool should_pause_video) {
if (!window_ || !window_->IsVisible())
return;
window_->Hide();
- CloseInternal(should_pause_video, should_reset_pip_player);
+ CloseInternal(should_pause_video);
}
void PictureInPictureWindowControllerImpl::CloseAndFocusInitiator() {
- Close(false /* should_pause_video */, true /* should_reset_pip_player */);
+ Close(false /* should_pause_video */);
initiator_->Activate();
}
void PictureInPictureWindowControllerImpl::OnWindowDestroyed() {
window_ = nullptr;
- embedder_ = nullptr;
- CloseInternal(true /* should_pause_video */,
- true /* should_reset_pip_player */);
+ CloseInternal(true /* should_pause_video */);
}
void PictureInPictureWindowControllerImpl::EmbedSurface(
@@ -126,16 +120,6 @@ void PictureInPictureWindowControllerImpl::EmbedSurface(
DCHECK(surface_id.is_valid());
- // TODO(https://crbug.com/925346): We also want to unregister the page that
- // used to embed the video as its parent.
- ui::Compositor* compositor = window_->GetLayer()->GetCompositor();
- if (!surface_id_.is_valid()) {
- compositor->AddChildFrameSink(surface_id.frame_sink_id());
- } else if (surface_id_.frame_sink_id() != surface_id.frame_sink_id()) {
- compositor->RemoveChildFrameSink(surface_id_.frame_sink_id());
- compositor->AddChildFrameSink(surface_id.frame_sink_id());
- }
-
surface_id_ = surface_id;
// Update the media player id in step with the video surface id. If the
@@ -145,10 +129,7 @@ void PictureInPictureWindowControllerImpl::EmbedSurface(
UpdateMediaPlayerId();
window_->UpdateVideoSize(natural_size);
-
- if (!embedder_)
- embedder_.reset(new OverlaySurfaceEmbedder(window_.get()));
- embedder_->SetSurfaceId(surface_id_);
+ window_->SetSurfaceId(surface_id_);
}
OverlayWindow* PictureInPictureWindowControllerImpl::GetWindowForTesting() {
@@ -156,18 +137,16 @@ OverlayWindow* PictureInPictureWindowControllerImpl::GetWindowForTesting() {
}
void PictureInPictureWindowControllerImpl::UpdateLayerBounds() {
- if (media_player_id_.has_value() && service_ && window_ &&
+ if (media_player_id_.has_value() && active_session_ && window_ &&
window_->IsVisible()) {
- service_->NotifyWindowResized(window_->GetBounds().size());
+ active_session_->NotifyWindowResized(window_->GetBounds().size());
}
-
- if (embedder_)
- embedder_->UpdateLayerBounds();
}
bool PictureInPictureWindowControllerImpl::IsPlayerActive() {
if (!media_player_id_.has_value())
- media_player_id_ = service_ ? service_->player_id() : base::nullopt;
+ media_player_id_ =
+ active_session_ ? active_session_->player_id() : base::nullopt;
// At creation time, the player id may not be set.
if (!media_player_id_.has_value())
@@ -248,11 +227,23 @@ bool PictureInPictureWindowControllerImpl::ToggleMute() {
}
void PictureInPictureWindowControllerImpl::UpdateMediaPlayerId() {
- media_player_id_ = service_ ? service_->player_id() : base::nullopt;
+ media_player_id_ =
+ active_session_ ? active_session_->player_id() : base::nullopt;
UpdatePlaybackState(IsPlayerActive(), !media_player_id_.has_value());
UpdateMutedState();
}
+void PictureInPictureWindowControllerImpl::SetActiveSession(
+ PictureInPictureSession* session) {
+ if (active_session_ == session)
+ return;
+
+ if (active_session_)
+ active_session_->Shutdown();
+
+ active_session_ = session;
+}
+
void PictureInPictureWindowControllerImpl::SetAlwaysHidePlayPauseButton(
bool is_visible) {
always_hide_play_pause_button_ = is_visible;
@@ -395,13 +386,7 @@ bool PictureInPictureWindowControllerImpl::IsPlayerMuted() {
}
void PictureInPictureWindowControllerImpl::OnLeavingPictureInPicture(
- bool should_pause_video,
- bool should_reset_pip_player) {
- if (window_ && surface_id_.is_valid()) {
- window_->GetLayer()->GetCompositor()->RemoveChildFrameSink(
- surface_id_.frame_sink_id());
- }
-
+ 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_->render_frame_host->Send(new MediaPlayerDelegateMsg_Pause(
@@ -410,27 +395,19 @@ void PictureInPictureWindowControllerImpl::OnLeavingPictureInPicture(
}
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));
-
- if (should_reset_pip_player) {
- DCHECK(service_);
- service_->ResetPlayerId();
- media_player_id_.reset();
- }
+ active_session_->Shutdown();
+ active_session_ = nullptr;
+ media_player_id_.reset();
}
}
void PictureInPictureWindowControllerImpl::CloseInternal(
- bool should_pause_video,
- bool should_reset_pip_player) {
+ bool should_pause_video) {
if (initiator_->IsBeingDestroyed())
return;
initiator_->SetHasPictureInPictureVideo(false);
- OnLeavingPictureInPicture(should_pause_video, should_reset_pip_player);
+ OnLeavingPictureInPicture(should_pause_video);
surface_id_ = viz::SurfaceId();
}
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 3631ec6ef53..166dfd742dc 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
@@ -19,8 +19,7 @@
namespace content {
class MediaWebContentsObserver;
-class OverlaySurfaceEmbedder;
-class PictureInPictureServiceImpl;
+class PictureInPictureSession;
class WebContents;
class WebContentsImpl;
@@ -48,8 +47,7 @@ class PictureInPictureWindowControllerImpl
// PictureInPictureWindowController:
CONTENT_EXPORT gfx::Size Show() override;
- CONTENT_EXPORT void Close(bool should_pause_video,
- bool should_reset_pip_player) override;
+ CONTENT_EXPORT void Close(bool should_pause_video) override;
CONTENT_EXPORT void CloseAndFocusInitiator() override;
CONTENT_EXPORT void OnWindowDestroyed() override;
CONTENT_EXPORT void EmbedSurface(const viz::SurfaceId& surface_id,
@@ -86,7 +84,11 @@ class PictureInPictureWindowControllerImpl
// state of this object.
void UpdateMediaPlayerId();
- void set_service(PictureInPictureServiceImpl* service) { service_ = service; }
+ // Sets the active Picture-in-Picture session associated with the controller.
+ // This is different from the service's active session as there is one
+ // controller per WebContents and one service per RenderFrameHost.
+ // The current session may be shut down as a side effect of this.
+ void SetActiveSession(PictureInPictureSession* session);
private:
friend class WebContentsUserData<PictureInPictureWindowControllerImpl>;
@@ -97,12 +99,11 @@ class PictureInPictureWindowControllerImpl
WebContents* initiator);
// Signal to the media player that |this| is leaving Picture-in-Picture mode.
- void OnLeavingPictureInPicture(bool should_pause_video,
- bool should_reset_pip_player);
+ 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, bool should_reset_pip_player);
+ 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.
@@ -118,7 +119,7 @@ class PictureInPictureWindowControllerImpl
bool RemoveMutedPlayerEntry(const MediaPlayerId& id);
std::unique_ptr<OverlayWindow> window_;
- std::unique_ptr<OverlaySurfaceEmbedder> embedder_;
+
// TODO(929156): remove this as it should be accessible via `web_contents()`.
WebContentsImpl* const initiator_;
@@ -149,10 +150,11 @@ class PictureInPictureWindowControllerImpl
// origin trial is disabled.
bool always_hide_mute_button_ = false;
- // Service currently associated with the Picture-in-Picture window. The
- // service makes the bridge with the renderer process by sending enter/exit
- // requests. It is also holding the Picture-in-Picture MediaPlayerId.
- PictureInPictureServiceImpl* service_ = nullptr;
+ // Session currently associated with the Picture-in-Picture window. The
+ // session object makes the bridge with the renderer process by handling
+ // requests and holding states such as the active player id.
+ // The session will be nullptr when there is no active session.
+ PictureInPictureSession* active_session_ = nullptr;
WEB_CONTENTS_USER_DATA_KEY_DECL();
diff --git a/chromium/content/browser/pointer_lock_browsertest.cc b/chromium/content/browser/pointer_lock_browsertest.cc
index 468eedc5109..0afb41fea01 100644
--- a/chromium/content/browser/pointer_lock_browsertest.cc
+++ b/chromium/content/browser/pointer_lock_browsertest.cc
@@ -45,9 +45,7 @@ class MockPointerLockRenderWidgetHostView : public RenderWidgetHostViewAura {
public:
MockPointerLockRenderWidgetHostView(RenderWidgetHost* host,
bool is_guest_view_hack)
- : RenderWidgetHostViewAura(host,
- is_guest_view_hack,
- false /* is_mus_browser_plugin_guest */),
+ : RenderWidgetHostViewAura(host, is_guest_view_hack),
host_(RenderWidgetHostImpl::From(host)) {}
~MockPointerLockRenderWidgetHostView() override {
if (IsMouseLocked())
diff --git a/chromium/content/browser/portal/portal.cc b/chromium/content/browser/portal/portal.cc
index d7faeb9a4d1..b45333fb353 100644
--- a/chromium/content/browser/portal/portal.cc
+++ b/chromium/content/browser/portal/portal.cc
@@ -10,6 +10,7 @@
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/render_frame_host_manager.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
@@ -34,12 +35,17 @@ Portal::Portal(RenderFrameHostImpl* owner_render_frame_host)
: WebContentsObserver(
WebContents::FromRenderFrameHost(owner_render_frame_host)),
owner_render_frame_host_(owner_render_frame_host),
- portal_token_(base::UnguessableToken::Create()) {
+ portal_token_(base::UnguessableToken::Create()),
+ portal_host_binding_(this) {
auto pair = g_portal_token_map.Get().emplace(portal_token_, this);
DCHECK(pair.second);
}
Portal::~Portal() {
+ WebContentsImpl* outer_contents_impl = static_cast<WebContentsImpl*>(
+ WebContents::FromRenderFrameHost(owner_render_frame_host_));
+ devtools_instrumentation::PortalDetached(outer_contents_impl->GetMainFrame());
+
g_portal_token_map.Get().erase(portal_token_);
}
@@ -59,11 +65,13 @@ Portal* Portal::FromToken(const base::UnguessableToken& portal_token) {
// static
Portal* Portal::Create(RenderFrameHostImpl* owner_render_frame_host,
- blink::mojom::PortalAssociatedRequest request) {
+ blink::mojom::PortalAssociatedRequest request,
+ blink::mojom::PortalClientAssociatedPtrInfo client) {
auto portal_ptr = base::WrapUnique(new Portal(owner_render_frame_host));
Portal* portal = portal_ptr.get();
portal->binding_ = mojo::MakeStrongAssociatedBinding(std::move(portal_ptr),
std::move(request));
+ portal->client_ = blink::mojom::PortalClientAssociatedPtr(std::move(client));
return portal;
}
@@ -73,6 +81,33 @@ std::unique_ptr<Portal> Portal::CreateForTesting(
return base::WrapUnique(new Portal(owner_render_frame_host));
}
+// static
+void Portal::BindPortalHostRequest(
+ RenderFrameHostImpl* frame,
+ blink::mojom::PortalHostAssociatedRequest request) {
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(frame));
+
+ // This guards against the blink::mojom::PortalHost interface being used
+ // outside the main frame of a Portal's guest.
+ if (!web_contents || !web_contents->IsPortal() ||
+ !frame->frame_tree_node()->IsMainFrame()) {
+ mojo::ReportBadMessage(
+ "blink.mojom.PortalHost can only be used by the the main frame of a "
+ "Portal's guest.");
+ return;
+ }
+
+ // This binding may already be bound to another request, and in such cases,
+ // we rebind with the new request. An example scenario is a new document after
+ // a portal navigation trying to create a connection, but the old document
+ // hasn't been destroyed yet (and the pipe hasn't been closed).
+ auto& binding = web_contents->portal()->portal_host_binding_;
+ if (binding.is_bound())
+ binding.Close();
+ binding.Bind(std::move(request));
+}
+
RenderFrameProxyHost* Portal::CreateProxyAndAttachPortal() {
WebContentsImpl* outer_contents_impl = static_cast<WebContentsImpl*>(
WebContents::FromRenderFrameHost(owner_render_frame_host_));
@@ -122,10 +157,21 @@ RenderFrameProxyHost* Portal::CreateProxyAndAttachPortal() {
if (web_contents_created)
PortalWebContentsCreated(portal_contents_impl_);
+ devtools_instrumentation::PortalAttached(outer_contents_impl->GetMainFrame());
+
return proxy_host;
}
void Portal::Navigate(const GURL& url) {
+ if (!url.SchemeIsHTTPOrHTTPS()) {
+ mojo::ReportBadMessage("Portal::Navigate tried to use non-HTTP protocol.");
+ binding_->Close(); // Also deletes |this|.
+ return;
+ }
+
+ // TODO(lfg): Investigate which other restrictions we might need when
+ // navigating portals. See http://crbug.com/964395.
+
NavigationController::LoadURLParams load_url_params(url);
portal_contents_impl_->GetController().LoadURLWithParams(load_url_params);
}
@@ -148,8 +194,19 @@ void Portal::Activate(blink::TransferableMessage data,
auto* outer_contents_main_frame_view = static_cast<RenderWidgetHostViewBase*>(
outer_contents->GetMainFrame()->GetView());
- if (outer_contents_main_frame_view)
+
+ if (outer_contents_main_frame_view) {
+ // Take fallback contents from previous WebContents so that the activation
+ // is smooth without flashes.
+ auto* portal_contents_main_frame_view =
+ static_cast<RenderWidgetHostViewBase*>(
+ portal_contents_impl_->GetMainFrame()->GetView());
+ portal_contents_main_frame_view->TakeFallbackContentFrom(
+ outer_contents_main_frame_view);
+
outer_contents_main_frame_view->Destroy();
+ }
+
std::unique_ptr<WebContents> predecessor_web_contents =
delegate->SwapWebContents(outer_contents, std::move(portal_contents),
true, is_loading);
@@ -158,22 +215,42 @@ void Portal::Activate(blink::TransferableMessage data,
portal_contents_impl_->set_portal(nullptr);
blink::mojom::PortalAssociatedPtr portal_ptr;
- Portal* portal = Create(portal_contents_impl_->GetMainFrame(),
- mojo::MakeRequest(&portal_ptr));
+ blink::mojom::PortalClientAssociatedPtr portal_client_ptr;
+ auto portal_client_request = mojo::MakeRequest(&portal_client_ptr);
+ Portal* portal =
+ Create(portal_contents_impl_->GetMainFrame(),
+ mojo::MakeRequest(&portal_ptr), portal_client_ptr.PassInterface());
portal->SetPortalContents(std::move(predecessor_web_contents));
portal_contents_impl_->GetMainFrame()->OnPortalActivated(
- portal->portal_token_, portal_ptr.PassInterface(), std::move(data),
- std::move(callback));
+ portal->portal_token_, portal_ptr.PassInterface(),
+ std::move(portal_client_request), std::move(data), std::move(callback));
+
+ devtools_instrumentation::PortalActivated(outer_contents->GetMainFrame());
}
-void Portal::PostMessage(blink::TransferableMessage message,
- const base::Optional<url::Origin>& target_origin) {
- portal_contents_impl_->GetMainFrame()->ForwardMessageToPortalHost(
+void Portal::PostMessageToGuest(
+ blink::TransferableMessage message,
+ const base::Optional<url::Origin>& target_origin) {
+ portal_contents_impl_->GetMainFrame()->ForwardMessageFromHost(
std::move(message), owner_render_frame_host_->GetLastCommittedOrigin(),
target_origin);
}
+void Portal::PostMessageToHost(
+ blink::TransferableMessage message,
+ const base::Optional<url::Origin>& target_origin) {
+ DCHECK(GetPortalContents());
+ if (target_origin) {
+ if (target_origin != owner_render_frame_host_->GetLastCommittedOrigin())
+ return;
+ }
+ client().ForwardMessageFromGuest(
+ std::move(message),
+ GetPortalContents()->GetMainFrame()->GetLastCommittedOrigin(),
+ target_origin);
+}
+
void Portal::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
if (render_frame_host == owner_render_frame_host_)
binding_->Close(); // Also deletes |this|.
@@ -183,6 +260,13 @@ void Portal::WebContentsDestroyed() {
binding_->Close(); // Also deletes |this|.
}
+void Portal::LoadingStateChanged(WebContents* source,
+ bool to_different_document) {
+ DCHECK_EQ(source, portal_contents_impl_);
+ if (!source->IsLoading())
+ client_->DispatchLoadEvent();
+}
+
void Portal::PortalWebContentsCreated(WebContents* portal_web_contents) {
WebContentsImpl* outer_contents = static_cast<WebContentsImpl*>(
WebContents::FromRenderFrameHost(owner_render_frame_host_));
@@ -190,6 +274,10 @@ void Portal::PortalWebContentsCreated(WebContents* portal_web_contents) {
outer_contents->GetDelegate()->PortalWebContentsCreated(portal_web_contents);
}
+base::UnguessableToken Portal::GetDevToolsFrameToken() const {
+ return portal_contents_impl_->GetMainFrame()->GetDevToolsFrameToken();
+}
+
WebContentsImpl* Portal::GetPortalContents() {
return portal_contents_impl_;
}
@@ -199,6 +287,11 @@ void Portal::SetBindingForTesting(
binding_ = binding;
}
+void Portal::SetClientForTesting(
+ blink::mojom::PortalClientAssociatedPtr client) {
+ client_ = std::move(client);
+}
+
void Portal::SetPortalContents(std::unique_ptr<WebContents> web_contents) {
portal_contents_ = std::move(web_contents);
portal_contents_impl_ = static_cast<WebContentsImpl*>(portal_contents_.get());
diff --git a/chromium/content/browser/portal/portal.h b/chromium/content/browser/portal/portal.h
index 98b941826fd..07e4b4331db 100644
--- a/chromium/content/browser/portal/portal.h
+++ b/chromium/content/browser/portal/portal.h
@@ -30,6 +30,7 @@ class WebContentsImpl;
// The Portal is owned by its mojo binding, so it is kept alive as long as the
// other end of the pipe (typically in the renderer) exists.
class CONTENT_EXPORT Portal : public blink::mojom::Portal,
+ public blink::mojom::PortalHost,
public WebContentsObserver,
public WebContentsDelegate {
public:
@@ -43,12 +44,17 @@ class CONTENT_EXPORT Portal : public blink::mojom::Portal,
// function creates a strong binding, so the ownership of the Portal is
// delegated to the binding.
static Portal* Create(RenderFrameHostImpl* owner_render_frame_host,
- blink::mojom::PortalAssociatedRequest request);
+ blink::mojom::PortalAssociatedRequest request,
+ blink::mojom::PortalClientAssociatedPtrInfo client);
// Creates a portal without binding it to any pipe. Only used in tests.
static std::unique_ptr<Portal> CreateForTesting(
RenderFrameHostImpl* owner_render_frame_host);
+ static void BindPortalHostRequest(
+ RenderFrameHostImpl* frame,
+ blink::mojom::PortalHostAssociatedRequest request);
+
// Called from a synchronous IPC from the renderer process in order to create
// the proxy.
RenderFrameProxyHost* CreateProxyAndAttachPortal();
@@ -57,19 +63,30 @@ class CONTENT_EXPORT Portal : public blink::mojom::Portal,
void Navigate(const GURL& url) override;
void Activate(blink::TransferableMessage data,
ActivateCallback callback) override;
- void PostMessage(const blink::TransferableMessage message,
- const base::Optional<url::Origin>& target_origin) override;
+ void PostMessageToGuest(
+ const blink::TransferableMessage message,
+ const base::Optional<url::Origin>& target_origin) override;
+
+ // blink::mojom::PortalHost implementation
+ void PostMessageToHost(
+ blink::TransferableMessage message,
+ const base::Optional<url::Origin>& target_origin) override;
// WebContentsObserver overrides.
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
void WebContentsDestroyed() override;
// WebContentsDelegate overrides.
+ void LoadingStateChanged(WebContents* source,
+ bool to_different_document) override;
void PortalWebContentsCreated(WebContents* portal_web_contents) override;
// Returns the token which uniquely identifies this Portal.
const base::UnguessableToken& portal_token() const { return portal_token_; }
+ // Returns the devtools frame token for the portal's main frame.
+ base::UnguessableToken GetDevToolsFrameToken() const;
+
// Returns the Portal's WebContents.
WebContentsImpl* GetPortalContents();
@@ -84,6 +101,9 @@ class CONTENT_EXPORT Portal : public blink::mojom::Portal,
}
void SetBindingForTesting(
mojo::StrongAssociatedBindingPtr<blink::mojom::Portal> binding);
+ void SetClientForTesting(blink::mojom::PortalClientAssociatedPtr client);
+
+ blink::mojom::PortalClient& client() { return *client_; }
private:
explicit Portal(RenderFrameHostImpl* owner_render_frame_host);
@@ -99,10 +119,17 @@ class CONTENT_EXPORT Portal : public blink::mojom::Portal,
// WeakPtr to StrongBinding.
mojo::StrongAssociatedBindingPtr<blink::mojom::Portal> binding_;
+ // Receives messages from the inner render process.
+ mojo::AssociatedBinding<blink::mojom::PortalHost> portal_host_binding_;
+
+ // Used to communicate with the HTMLPortalElement in the renderer that
+ // hosts this Portal.
+ blink::mojom::PortalClientAssociatedPtr client_;
+
// When the portal is not attached, the Portal owns its WebContents.
std::unique_ptr<WebContents> portal_contents_;
- WebContentsImpl* portal_contents_impl_;
+ WebContentsImpl* portal_contents_impl_ = nullptr;
};
} // namespace content
diff --git a/chromium/content/browser/portal/portal_browsertest.cc b/chromium/content/browser/portal/portal_browsertest.cc
index 52f05325c59..11ae0aac31b 100644
--- a/chromium/content/browser/portal/portal_browsertest.cc
+++ b/chromium/content/browser/portal/portal_browsertest.cc
@@ -22,6 +22,7 @@
#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -42,7 +43,8 @@ class PortalInterceptorForTesting final
public:
static PortalInterceptorForTesting* Create(
RenderFrameHostImpl* render_frame_host_impl,
- blink::mojom::PortalAssociatedRequest request);
+ blink::mojom::PortalAssociatedRequest request,
+ blink::mojom::PortalClientAssociatedPtr client);
static PortalInterceptorForTesting* From(content::Portal* portal);
void Activate(blink::TransferableMessage data,
@@ -58,6 +60,15 @@ class PortalInterceptorForTesting final
portal_->Activate(std::move(data), std::move(callback));
}
+ void Navigate(const GURL& url) override {
+ if (navigate_callback_) {
+ navigate_callback_.Run(url);
+ return;
+ }
+
+ portal_->Navigate(url);
+ }
+
void WaitForActivate() {
if (portal_activated_)
return;
@@ -71,6 +82,9 @@ class PortalInterceptorForTesting final
content::Portal* GetPortal() { return portal_.get(); }
WebContents* GetPortalContents() { return portal_->GetPortalContents(); }
+ // IPC callbacks
+ base::RepeatingCallback<void(const GURL&)> navigate_callback_;
+
private:
PortalInterceptorForTesting(RenderFrameHostImpl* render_frame_host_impl)
: portal_(content::Portal::CreateForTesting(render_frame_host_impl)) {}
@@ -87,13 +101,15 @@ class PortalInterceptorForTesting final
// static
PortalInterceptorForTesting* PortalInterceptorForTesting::Create(
RenderFrameHostImpl* render_frame_host_impl,
- blink::mojom::PortalAssociatedRequest request) {
+ blink::mojom::PortalAssociatedRequest request,
+ blink::mojom::PortalClientAssociatedPtr client) {
auto test_portal_ptr =
base::WrapUnique(new PortalInterceptorForTesting(render_frame_host_impl));
PortalInterceptorForTesting* test_portal = test_portal_ptr.get();
test_portal->GetPortal()->SetBindingForTesting(
mojo::MakeStrongAssociatedBinding(std::move(test_portal_ptr),
std::move(request)));
+ test_portal->GetPortal()->SetClientForTesting(std::move(client));
return test_portal;
}
@@ -126,14 +142,16 @@ class PortalCreatedObserver : public mojom::FrameHostInterceptorForTesting {
}
void CreatePortal(blink::mojom::PortalAssociatedRequest request,
+ blink::mojom::PortalClientAssociatedPtrInfo client,
CreatePortalCallback callback) override {
PortalInterceptorForTesting* portal_interceptor =
- PortalInterceptorForTesting::Create(render_frame_host_impl_,
- std::move(request));
+ PortalInterceptorForTesting::Create(
+ render_frame_host_impl_, std::move(request),
+ blink::mojom::PortalClientAssociatedPtr(std::move(client)));
portal_ = portal_interceptor->GetPortal();
RenderFrameProxyHost* proxy_host = portal_->CreateProxyAndAttachPortal();
- std::move(callback).Run(proxy_host->GetRoutingID(),
- portal_->portal_token());
+ std::move(callback).Run(proxy_host->GetRoutingID(), portal_->portal_token(),
+ portal_->GetDevToolsFrameToken());
if (run_loop_)
run_loop_->Quit();
@@ -482,4 +500,91 @@ IN_PROC_BROWSER_TEST_F(PortalBrowserTest, AsyncEventTargetingIgnoresPortals) {
<< "Note: The portal's FrameSinkId is " << portal_view->GetFrameSinkId();
}
+// Tests that trying to navigate to a chrome:// URL kills the renderer.
+IN_PROC_BROWSER_TEST_F(PortalBrowserTest, NavigateToChrome) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("portal.test", "/title1.html")));
+ WebContentsImpl* web_contents_impl =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderFrameHostImpl* main_frame = web_contents_impl->GetMainFrame();
+
+ // Create portal.
+ PortalCreatedObserver portal_created_observer(main_frame);
+ EXPECT_TRUE(ExecJs(main_frame,
+ "var portal = document.createElement('portal');"
+ "document.body.appendChild(portal);"));
+ Portal* portal = portal_created_observer.WaitUntilPortalCreated();
+ PortalInterceptorForTesting* portal_interceptor =
+ PortalInterceptorForTesting::From(portal);
+ WebContentsImpl* portal_contents = portal->GetPortalContents();
+
+ // Try to navigate to chrome://settings and wait for the process to die.
+ portal_interceptor->navigate_callback_ = base::BindRepeating(
+ [](Portal* portal, const GURL& url) {
+ GURL chrome_url("chrome://settings");
+ portal->Navigate(chrome_url);
+ },
+ portal);
+ RenderProcessHostKillWaiter kill_waiter(
+ portal_contents->GetMainFrame()->GetProcess());
+ GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ ignore_result(ExecJs(main_frame, JsReplace("portal.src = $1;", a_url)));
+
+ EXPECT_EQ(base::nullopt, kill_waiter.Wait());
+}
+
+class PortalOOPIFBrowserTest : public PortalBrowserTest {
+ protected:
+ PortalOOPIFBrowserTest() {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ IsolateAllSitesForTesting(command_line);
+ }
+};
+
+// Tests that creating and destroying OOPIFs inside the portal works as
+// intended.
+IN_PROC_BROWSER_TEST_F(PortalOOPIFBrowserTest, OOPIFInsidePortal) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("portal.test", "/title1.html")));
+ WebContentsImpl* web_contents_impl =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderFrameHostImpl* main_frame = web_contents_impl->GetMainFrame();
+
+ // Create portal and wait for navigation.
+ PortalCreatedObserver portal_created_observer(main_frame);
+ GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(ExecJs(main_frame,
+ JsReplace("var portal = document.createElement('portal');"
+ "portal.src = $1;"
+ "document.body.appendChild(portal);",
+ a_url)));
+ Portal* portal = portal_created_observer.WaitUntilPortalCreated();
+ WebContentsImpl* portal_contents = portal->GetPortalContents();
+ RenderFrameHostImpl* portal_main_frame = portal_contents->GetMainFrame();
+ TestNavigationObserver portal_navigation_observer(portal_contents);
+ portal_navigation_observer.Wait();
+
+ // Add an out-of-process iframe to the portal.
+ GURL b_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
+ TestNavigationObserver iframe_navigation_observer(portal_contents);
+ EXPECT_TRUE(ExecJs(portal_main_frame,
+ JsReplace("var iframe = document.createElement('iframe');"
+ "iframe.src = $1;"
+ "document.body.appendChild(iframe);",
+ b_url)));
+ iframe_navigation_observer.Wait();
+ EXPECT_EQ(b_url, iframe_navigation_observer.last_navigation_url());
+ RenderFrameHostImpl* portal_iframe =
+ portal_main_frame->child_at(0)->current_frame_host();
+ EXPECT_NE(portal_main_frame->GetSiteInstance(),
+ portal_iframe->GetSiteInstance());
+
+ // Remove the OOPIF from the portal.
+ RenderFrameDeletedObserver deleted_observer(portal_iframe);
+ EXPECT_TRUE(
+ ExecJs(portal_main_frame, "document.querySelector('iframe').remove();"));
+ deleted_observer.WaitUntilDeleted();
+}
+
} // namespace content
diff --git a/chromium/content/browser/ppapi_plugin_process_host.cc b/chromium/content/browser/ppapi_plugin_process_host.cc
index 2d57937dfff..56a1b68a0d0 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.cc
+++ b/chromium/content/browser/ppapi_plugin_process_host.cc
@@ -32,6 +32,7 @@
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "content/public/common/service_names.mojom.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppapi_permissions.h"
#include "services/network/public/cpp/network_connection_tracker.h"
#include "services/service_manager/sandbox/sandbox_type.h"
#include "services/service_manager/sandbox/switches.h"
@@ -57,10 +58,16 @@ namespace content {
class PpapiPluginSandboxedProcessLauncherDelegate
: public content::SandboxedProcessLauncherDelegate {
public:
- explicit PpapiPluginSandboxedProcessLauncherDelegate(bool is_broker)
+ PpapiPluginSandboxedProcessLauncherDelegate(
+ bool is_broker,
+ const ppapi::PpapiPermissions& permissions)
#if BUILDFLAG(USE_ZYGOTE_HANDLE) || defined(OS_WIN)
: is_broker_(is_broker)
#endif
+#if defined(OS_WIN)
+ ,
+ permissions_(permissions)
+#endif
{
}
@@ -85,7 +92,7 @@ class PpapiPluginSandboxedProcessLauncherDelegate
#if !defined(NACL_WIN64)
// We don't support PPAPI win32k lockdown prior to Windows 10.
- if (base::win::GetVersion() >= base::win::VERSION_WIN10 &&
+ if (base::win::GetVersion() >= base::win::Version::WIN10 &&
service_manager::IsWin32kLockdownEnabled()) {
result =
service_manager::SandboxWin::AddWin32kLockdownPolicy(policy, true);
@@ -98,6 +105,14 @@ class PpapiPluginSandboxedProcessLauncherDelegate
if (!sid.empty())
service_manager::SandboxWin::AddAppContainerPolicy(policy, sid.c_str());
+ // Only Flash needs to be able to execute dynamic code.
+ if (!permissions_.HasPermission(ppapi::PERMISSION_FLASH)) {
+ sandbox::MitigationFlags flags = policy->GetDelayedProcessMitigations();
+ flags |= sandbox::MITIGATION_DYNAMIC_CODE_DISABLE;
+ if (sandbox::SBOX_ALL_OK != policy->SetDelayedProcessMitigations(flags))
+ return false;
+ }
+
return true;
}
#endif // OS_WIN
@@ -124,7 +139,10 @@ class PpapiPluginSandboxedProcessLauncherDelegate
private:
#if BUILDFLAG(USE_ZYGOTE_HANDLE) || defined(OS_WIN)
- bool is_broker_;
+ const bool is_broker_;
+#endif
+#if defined(OS_WIN)
+ const ppapi::PpapiPermissions permissions_;
#endif
DISALLOW_COPY_AND_ASSIGN(PpapiPluginSandboxedProcessLauncherDelegate);
@@ -346,6 +364,8 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
#if defined(OS_LINUX)
int flags = plugin_launcher.empty() ? ChildProcessHost::CHILD_ALLOW_SELF :
ChildProcessHost::CHILD_NORMAL;
+#elif defined(OS_MACOSX)
+ int flags = ChildProcessHost::CHILD_PLUGIN;
#else
int flags = ChildProcessHost::CHILD_NORMAL;
#endif
@@ -421,7 +441,8 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
// we are not using a plugin launcher - having a plugin launcher means we need
// to use another process instead of just forking the zygote.
process_->Launch(
- std::make_unique<PpapiPluginSandboxedProcessLauncherDelegate>(is_broker_),
+ std::make_unique<PpapiPluginSandboxedProcessLauncherDelegate>(
+ is_broker_, permissions_),
std::move(cmd_line), true);
return true;
}
diff --git a/chromium/content/browser/presentation/presentation_browsertest.cc b/chromium/content/browser/presentation/presentation_browsertest.cc
deleted file mode 100644
index 12954429aff..00000000000
--- a/chromium/content/browser/presentation/presentation_browsertest.cc
+++ /dev/null
@@ -1,53 +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/public/browser/web_contents.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/public/test/test_navigation_observer.h"
-#include "content/shell/browser/shell.h"
-
-namespace content {
-
-using PresentationBrowserTest = ContentBrowserTest;
-
-// Regression test that verifies that calling getAvailability() twice on the
-// same PresentationRequest does not return an undefined object.
-// TODO(mlamouri,mfoltz), update the test after [SameObject] is used,
-// see https://crbug.com/653131
-// Broken; see https://crbug.com/940503 .
-IN_PROC_BROWSER_TEST_F(PresentationBrowserTest,
- DISABLED_AvailabilityNotUndefined) {
- GURL test_url = GetTestUrl("", "hello.html");
-
- TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
- shell()->LoadURL(test_url);
-
- navigation_observer.Wait();
-
- ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
- "const r = new PresentationRequest('foo.html')");
-
- ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
- "const p1 = r.getAvailability();");
-
- ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
- "const p2 = r.getAvailability()");
-
- bool is_p1_undefined =
- ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
- "p1 === undefined")
- .GetBool();
-
- bool is_p2_undefined =
- ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
- "p2 === undefined")
- .GetBool();
-
- EXPECT_FALSE(is_p1_undefined);
- EXPECT_FALSE(is_p2_undefined);
-}
-
-} // namespace content
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 cf430dd5cec..0e38a96e45a 100644
--- a/chromium/content/browser/process_internals/process_internals_handler_impl.cc
+++ b/chromium/content/browser/process_internals/process_internals_handler_impl.cc
@@ -66,6 +66,8 @@ void ProcessInternalsHandlerImpl::GetIsolationMode(
modes.push_back("Site Per Process");
if (SiteIsolationPolicy::AreIsolatedOriginsEnabled())
modes.push_back("Isolate Origins");
+ if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled())
+ modes.push_back("Strict Origin Isolation");
// Retrieve any additional site isolation modes controlled by the embedder.
std::vector<std::string> additional_modes =
diff --git a/chromium/content/browser/process_internals/process_internals_ui.cc b/chromium/content/browser/process_internals/process_internals_ui.cc
index 762b9f1dcd1..e72756365b2 100644
--- a/chromium/content/browser/process_internals/process_internals_ui.cc
+++ b/chromium/content/browser/process_internals/process_internals_ui.cc
@@ -35,13 +35,11 @@ ProcessInternalsUI::ProcessInternalsUI(WebUI* web_ui)
WebUIDataSource* source =
WebUIDataSource::Create(kChromeUIProcessInternalsHost);
- source->AddResourcePath("url.mojom-lite.js", IDR_URL_MOJO_JS);
source->AddResourcePath("process_internals.js", IDR_PROCESS_INTERNALS_JS);
source->AddResourcePath("process_internals.css", IDR_PROCESS_INTERNALS_CSS);
source->AddResourcePath("process_internals.mojom-lite.js",
IDR_PROCESS_INTERNALS_MOJO_JS);
source->SetDefaultResource(IDR_PROCESS_INTERNALS_HTML);
- source->UseGzip();
WebUIDataSource::Add(web_contents()->GetBrowserContext(), source);
diff --git a/chromium/content/browser/push_messaging/push_messaging_manager.cc b/chromium/content/browser/push_messaging/push_messaging_manager.cc
index 6513a5f34a3..ea0d8eb7b32 100644
--- a/chromium/content/browser/push_messaging/push_messaging_manager.cc
+++ b/chromium/content/browser/push_messaging/push_messaging_manager.cc
@@ -21,7 +21,6 @@
#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/browser_task_traits.h"
#include "content/public/browser/permission_type.h"
@@ -30,9 +29,11 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/push_messaging_status.mojom.h"
+#include "third_party/blink/public/common/push_messaging/web_push_subscription_options.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom.h"
namespace content {
@@ -54,73 +55,76 @@ const char kIncognitoPushUnsupportedMessage[] =
// These UMA methods are called from the IO and/or UI threads. Racey but ok, see
// https://groups.google.com/a/chromium.org/d/msg/chromium-dev/FNzZRJtN2aw/Aw0CWAXJJ1kJ
-void RecordRegistrationStatus(mojom::PushRegistrationStatus status) {
+void RecordRegistrationStatus(blink::mojom::PushRegistrationStatus status) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
UMA_HISTOGRAM_ENUMERATION("PushMessaging.RegistrationStatus", status);
}
-void RecordUnregistrationStatus(mojom::PushUnregistrationStatus status) {
+void RecordUnregistrationStatus(blink::mojom::PushUnregistrationStatus status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationStatus", status);
}
-void RecordGetRegistrationStatus(mojom::PushGetRegistrationStatus status) {
+void RecordGetRegistrationStatus(
+ blink::mojom::PushGetRegistrationStatus status) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
UMA_HISTOGRAM_ENUMERATION("PushMessaging.GetRegistrationStatus", status);
}
const char* PushUnregistrationStatusToString(
- mojom::PushUnregistrationStatus status) {
+ blink::mojom::PushUnregistrationStatus status) {
switch (status) {
- case mojom::PushUnregistrationStatus::SUCCESS_UNREGISTERED:
+ case blink::mojom::PushUnregistrationStatus::SUCCESS_UNREGISTERED:
return "Unregistration successful - from push service";
- case mojom::PushUnregistrationStatus::SUCCESS_WAS_NOT_REGISTERED:
+ case blink::mojom::PushUnregistrationStatus::SUCCESS_WAS_NOT_REGISTERED:
return "Unregistration successful - was not registered";
- case mojom::PushUnregistrationStatus::PENDING_NETWORK_ERROR:
+ case blink::mojom::PushUnregistrationStatus::PENDING_NETWORK_ERROR:
return "Unregistration pending - a network error occurred, but it will "
"be retried until it succeeds";
- case mojom::PushUnregistrationStatus::NO_SERVICE_WORKER:
+ case blink::mojom::PushUnregistrationStatus::NO_SERVICE_WORKER:
return "Unregistration failed - no Service Worker";
- case mojom::PushUnregistrationStatus::SERVICE_NOT_AVAILABLE:
+ case blink::mojom::PushUnregistrationStatus::SERVICE_NOT_AVAILABLE:
return "Unregistration failed - push service not available";
- case mojom::PushUnregistrationStatus::PENDING_SERVICE_ERROR:
+ case blink::mojom::PushUnregistrationStatus::PENDING_SERVICE_ERROR:
return "Unregistration pending - a push service error occurred, but it "
"will be retried until it succeeds";
- case mojom::PushUnregistrationStatus::STORAGE_ERROR:
+ case blink::mojom::PushUnregistrationStatus::STORAGE_ERROR:
return "Unregistration failed - storage error";
- case mojom::PushUnregistrationStatus::NETWORK_ERROR:
+ case blink::mojom::PushUnregistrationStatus::NETWORK_ERROR:
return "Unregistration failed - could not connect to push server";
}
NOTREACHED();
return "";
}
-// Returns whether |sender_info| contains a valid application server key, that
-// is, a NIST P-256 public key in uncompressed format.
-bool IsApplicationServerKey(const std::string& sender_info) {
- return sender_info.size() == 65 && sender_info[0] == 0x04;
+// Returns whether |application_server_key| contains a valid application server
+// key, that is, a NIST P-256 public key in uncompressed format.
+bool IsApplicationServerKey(const std::string& application_server_key) {
+ return application_server_key.size() == 65 &&
+ application_server_key[0] == 0x04;
}
-// Returns sender_info if non-empty, otherwise checks if stored_sender_id
-// may be used as a fallback and if so, returns stored_sender_id instead.
+// Returns application_server_key if non-empty, otherwise checks if
+// stored_sender_id may be used as a fallback and if so, returns
+// stored_sender_id instead.
//
// This is in order to support the legacy way of subscribing from a service
// worker (first subscribe from the document using a gcm_sender_id set in the
// manifest, and then subscribe from the service worker with no key).
//
-// An empty string will be returned if sender_info is empty and the fallback
-// is not a numeric gcm sender id.
-std::string FixSenderInfo(const std::string& sender_info,
+// An empty string will be returned if application_server_key is empty and the
+// fallback is not a numeric gcm sender id.
+std::string FixSenderInfo(const std::string& application_server_key,
const std::string& stored_sender_id) {
- if (!sender_info.empty())
- return sender_info;
+ if (!application_server_key.empty())
+ return application_server_key;
if (base::ContainsOnlyChars(stored_sender_id, "0123456789"))
return stored_sender_id;
return std::string();
@@ -137,7 +141,7 @@ struct PushMessagingManager::RegisterData {
GURL requesting_origin;
int64_t service_worker_registration_id;
base::Optional<std::string> existing_subscription_id;
- PushSubscriptionOptions options;
+ blink::WebPushSubscriptionOptions options;
SubscribeCallback callback;
// The following member should only be read if FromDocument() is true.
@@ -173,7 +177,7 @@ class PushMessagingManager::Core {
const GURL& origin,
int64_t service_worker_registration_id,
const GURL& endpoint,
- const std::string& sender_info,
+ const std::string& application_server_key,
bool is_valid,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth);
@@ -181,8 +185,8 @@ class PushMessagingManager::Core {
// Callback called on UI thread.
void GetSubscriptionDidUnsubscribe(
GetSubscriptionCallback callback,
- mojom::PushGetRegistrationStatus get_status,
- mojom::PushUnregistrationStatus unsubscribe_status);
+ blink::mojom::PushGetRegistrationStatus get_status,
+ blink::mojom::PushUnregistrationStatus unsubscribe_status);
// Public helper methods on UI thread ----------------------------------------
@@ -219,14 +223,14 @@ class PushMessagingManager::Core {
const std::string& push_subscription_id,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth,
- mojom::PushRegistrationStatus status);
+ blink::mojom::PushRegistrationStatus status);
// Private Unregister methods on UI thread -----------------------------------
void DidUnregisterFromService(
UnsubscribeCallback callback,
int64_t service_worker_registration_id,
- mojom::PushUnregistrationStatus unregistration_status);
+ blink::mojom::PushUnregistrationStatus unregistration_status);
// Outer part of the PushMessagingManager which lives on the IO thread.
base::WeakPtr<PushMessagingManager> io_parent_;
@@ -289,7 +293,7 @@ PushMessagingManager::PushMessagingManager(
PushMessagingManager::~PushMessagingManager() {}
void PushMessagingManager::BindRequest(
- mojom::PushMessagingRequest request) {
+ blink::mojom::PushMessagingRequest request) {
bindings_.AddBinding(this, std::move(request));
}
@@ -297,11 +301,12 @@ void PushMessagingManager::BindRequest(
// PushMessagingManager and Core.
// -----------------------------------------------------------------------------
-void PushMessagingManager::Subscribe(int32_t render_frame_id,
- int64_t service_worker_registration_id,
- const PushSubscriptionOptions& options,
- bool user_gesture,
- SubscribeCallback callback) {
+void PushMessagingManager::Subscribe(
+ int32_t render_frame_id,
+ int64_t service_worker_registration_id,
+ const blink::WebPushSubscriptionOptions& options,
+ bool user_gesture,
+ SubscribeCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// TODO(mvanouwerkerk): Validate arguments?
RegisterData data;
@@ -319,13 +324,14 @@ void PushMessagingManager::Subscribe(int32_t render_frame_id,
data.service_worker_registration_id);
if (!service_worker_registration ||
!service_worker_registration->active_version()) {
- SendSubscriptionError(std::move(data),
- mojom::PushRegistrationStatus::NO_SERVICE_WORKER);
+ SendSubscriptionError(
+ std::move(data),
+ blink::mojom::PushRegistrationStatus::NO_SERVICE_WORKER);
return;
}
data.requesting_origin = service_worker_registration->scope().GetOrigin();
- DCHECK(!(data.options.sender_info.empty() && data.FromDocument()));
+ DCHECK(!(data.options.application_server_key.empty() && data.FromDocument()));
int64_t registration_id = data.service_worker_registration_id;
service_worker_context_->GetRegistrationUserData(
@@ -350,16 +356,17 @@ void PushMessagingManager::DidCheckForExistingRegistration(
const std::string& stored_sender_id = subscription_id_and_sender_id[1];
std::string fixed_sender_id =
- FixSenderInfo(data.options.sender_info, stored_sender_id);
+ FixSenderInfo(data.options.application_server_key, stored_sender_id);
if (fixed_sender_id.empty()) {
SendSubscriptionError(std::move(data),
- mojom::PushRegistrationStatus::NO_SENDER_ID);
+ blink::mojom::PushRegistrationStatus::NO_SENDER_ID);
return;
}
if (fixed_sender_id != stored_sender_id) {
- SendSubscriptionError(std::move(data),
- mojom::PushRegistrationStatus::SENDER_ID_MISMATCH);
+ SendSubscriptionError(
+ std::move(data),
+ blink::mojom::PushRegistrationStatus::SENDER_ID_MISMATCH);
return;
}
@@ -370,14 +377,14 @@ void PushMessagingManager::DidCheckForExistingRegistration(
// blink::ServiceWorkerStatusCode::kErrorNotFound by rejecting
// the subscription algorithm instead of trying to subscribe.
- if (!data.options.sender_info.empty()) {
+ if (!data.options.application_server_key.empty()) {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Core::RegisterOnUI, base::Unretained(ui_core_.get()),
std::move(data)));
} else {
- // No |sender_info| was provided by the developer. Fall back to checking
- // whether a previous subscription did identify a sender.
+ // No |application_server_key| was provided by the developer. Fall back to
+ // checking whether a previous subscription did identify a sender.
int64_t registration_id = data.service_worker_registration_id;
service_worker_context_->GetRegistrationUserData(
registration_id, {kPushSenderIdServiceWorkerKey},
@@ -393,20 +400,20 @@ void PushMessagingManager::DidGetSenderIdFromStorage(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
SendSubscriptionError(std::move(data),
- mojom::PushRegistrationStatus::NO_SENDER_ID);
+ blink::mojom::PushRegistrationStatus::NO_SENDER_ID);
return;
}
DCHECK_EQ(1u, stored_sender_id.size());
// We should only be here because no sender info was supplied to subscribe().
- DCHECK(data.options.sender_info.empty());
+ DCHECK(data.options.application_server_key.empty());
std::string fixed_sender_id =
- FixSenderInfo(data.options.sender_info, stored_sender_id[0]);
+ FixSenderInfo(data.options.application_server_key, stored_sender_id[0]);
if (fixed_sender_id.empty()) {
SendSubscriptionError(std::move(data),
- mojom::PushRegistrationStatus::NO_SENDER_ID);
+ blink::mojom::PushRegistrationStatus::NO_SENDER_ID);
return;
}
- data.options.sender_info = fixed_sender_id;
+ data.options.application_server_key = fixed_sender_id;
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Core::RegisterOnUI, base::Unretained(ui_core_.get()),
@@ -423,9 +430,10 @@ void PushMessagingManager::Core::RegisterOnUI(
// returns false because the Instance ID kill switch was enabled.
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&PushMessagingManager::SendSubscriptionError,
- io_parent_, std::move(data),
- mojom::PushRegistrationStatus::SERVICE_NOT_AVAILABLE));
+ base::BindOnce(
+ &PushMessagingManager::SendSubscriptionError, io_parent_,
+ std::move(data),
+ blink::mojom::PushRegistrationStatus::SERVICE_NOT_AVAILABLE));
} else {
// Prevent websites from detecting incognito mode, by emulating what would
// have happened if we had a PushMessagingService available.
@@ -433,10 +441,10 @@ void PushMessagingManager::Core::RegisterOnUI(
// Throw a permission denied error under the same circumstances.
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
- base::BindOnce(
- &PushMessagingManager::SendSubscriptionError, io_parent_,
- std::move(data),
- mojom::PushRegistrationStatus::INCOGNITO_PERMISSION_DENIED));
+ base::BindOnce(&PushMessagingManager::SendSubscriptionError,
+ io_parent_, std::move(data),
+ blink::mojom::PushRegistrationStatus::
+ INCOGNITO_PERMISSION_DENIED));
} else {
RenderFrameHost* render_frame_host =
RenderFrameHost::FromID(render_process_id_, data.render_frame_id);
@@ -468,7 +476,7 @@ void PushMessagingManager::Core::RegisterOnUI(
int64_t registration_id = data.service_worker_registration_id;
GURL requesting_origin = data.requesting_origin;
- PushSubscriptionOptions options = data.options;
+ blink::WebPushSubscriptionOptions options = data.options;
int render_frame_id = data.render_frame_id;
if (data.FromDocument()) {
push_service->SubscribeFromDocument(
@@ -495,7 +503,7 @@ void PushMessagingManager::Core::DidRequestPermissionInIncognito(
base::BindOnce(
&PushMessagingManager::SendSubscriptionError, io_parent_,
std::move(data),
- mojom::PushRegistrationStatus::INCOGNITO_PERMISSION_DENIED));
+ blink::mojom::PushRegistrationStatus::INCOGNITO_PERMISSION_DENIED));
}
void PushMessagingManager::Core::DidRegister(
@@ -503,7 +511,7 @@ void PushMessagingManager::Core::DidRegister(
const std::string& push_subscription_id,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth,
- mojom::PushRegistrationStatus status) {
+ blink::mojom::PushRegistrationStatus status) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// TODO(crbug.com/646721): Handle the case where |push_subscription_id| and
@@ -513,16 +521,18 @@ void PushMessagingManager::Core::DidRegister(
data.existing_subscription_id.has_value() &&
data.existing_subscription_id.value() != push_subscription_id;
- if (status == mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE) {
+ if (status ==
+ blink::mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE) {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
- base::BindOnce(
- &PushMessagingManager::PersistRegistrationOnIO, io_parent_,
- std::move(data), push_subscription_id, p256dh, auth,
- subscription_changed
- ? mojom::PushRegistrationStatus::
- SUCCESS_NEW_SUBSCRIPTION_FROM_PUSH_SERVICE
- : mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE));
+ base::BindOnce(&PushMessagingManager::PersistRegistrationOnIO,
+ io_parent_, std::move(data), push_subscription_id,
+ p256dh, auth,
+ subscription_changed
+ ? blink::mojom::PushRegistrationStatus::
+ SUCCESS_NEW_SUBSCRIPTION_FROM_PUSH_SERVICE
+ : blink::mojom::PushRegistrationStatus::
+ SUCCESS_FROM_PUSH_SERVICE));
} else {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
@@ -536,16 +546,16 @@ void PushMessagingManager::PersistRegistrationOnIO(
const std::string& push_subscription_id,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth,
- mojom::PushRegistrationStatus status) {
+ blink::mojom::PushRegistrationStatus status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
GURL requesting_origin = data.requesting_origin;
int64_t registration_id = data.service_worker_registration_id;
- std::string sender_info = data.options.sender_info;
+ std::string application_server_key = data.options.application_server_key;
service_worker_context_->StoreRegistrationUserData(
registration_id, requesting_origin,
{{kPushRegistrationIdServiceWorkerKey, push_subscription_id},
- {kPushSenderIdServiceWorkerKey, sender_info}},
+ {kPushSenderIdServiceWorkerKey, application_server_key}},
base::BindOnce(&PushMessagingManager::DidPersistRegistrationOnIO,
weak_factory_io_to_io_.GetWeakPtr(), std::move(data),
push_subscription_id, p256dh, auth, status));
@@ -556,7 +566,7 @@ void PushMessagingManager::DidPersistRegistrationOnIO(
const std::string& push_subscription_id,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth,
- mojom::PushRegistrationStatus push_registration_status,
+ blink::mojom::PushRegistrationStatus push_registration_status,
blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (service_worker_status == blink::ServiceWorkerStatusCode::kOk) {
@@ -565,13 +575,13 @@ void PushMessagingManager::DidPersistRegistrationOnIO(
} else {
// TODO(johnme): Unregister, so PushMessagingServiceImpl can decrease count.
SendSubscriptionError(std::move(data),
- mojom::PushRegistrationStatus::STORAGE_ERROR);
+ blink::mojom::PushRegistrationStatus::STORAGE_ERROR);
}
}
void PushMessagingManager::SendSubscriptionError(
RegisterData data,
- mojom::PushRegistrationStatus status) {
+ blink::mojom::PushRegistrationStatus status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::move(data.callback)
.Run(status, base::nullopt /* endpoint */, base::nullopt /* options */,
@@ -581,7 +591,7 @@ void PushMessagingManager::SendSubscriptionError(
void PushMessagingManager::SendSubscriptionSuccess(
RegisterData data,
- mojom::PushRegistrationStatus status,
+ blink::mojom::PushRegistrationStatus status,
const std::string& push_subscription_id,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth) {
@@ -590,13 +600,15 @@ void PushMessagingManager::SendSubscriptionSuccess(
// This shouldn't be possible in incognito mode, since we've already checked
// that we have an existing registration. Hence it's ok to throw an error.
DCHECK(!ui_core_->is_incognito());
- SendSubscriptionError(std::move(data),
- mojom::PushRegistrationStatus::SERVICE_NOT_AVAILABLE);
+ SendSubscriptionError(
+ std::move(data),
+ blink::mojom::PushRegistrationStatus::SERVICE_NOT_AVAILABLE);
return;
}
const GURL endpoint = CreateEndpoint(
- IsApplicationServerKey(data.options.sender_info), push_subscription_id);
+ IsApplicationServerKey(data.options.application_server_key),
+ push_subscription_id);
std::move(data.callback).Run(status, endpoint, data.options, p256dh, auth);
@@ -615,7 +627,7 @@ void PushMessagingManager::Unsubscribe(int64_t service_worker_registration_id,
service_worker_registration_id);
if (!service_worker_registration) {
DidUnregister(std::move(callback),
- mojom::PushUnregistrationStatus::NO_SERVICE_WORKER);
+ blink::mojom::PushUnregistrationStatus::NO_SERVICE_WORKER);
return;
}
@@ -661,14 +673,15 @@ void PushMessagingManager::Core::UnregisterFromService(
DCHECK(!is_incognito());
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&PushMessagingManager::DidUnregister, io_parent_,
- std::move(callback),
- mojom::PushUnregistrationStatus::SERVICE_NOT_AVAILABLE));
+ base::BindOnce(
+ &PushMessagingManager::DidUnregister, io_parent_,
+ std::move(callback),
+ blink::mojom::PushUnregistrationStatus::SERVICE_NOT_AVAILABLE));
return;
}
push_service->Unsubscribe(
- mojom::PushUnregistrationReason::JAVASCRIPT_API, requesting_origin,
+ blink::mojom::PushUnregistrationReason::JAVASCRIPT_API, requesting_origin,
service_worker_registration_id, sender_id,
base::Bind(&Core::DidUnregisterFromService,
weak_factory_ui_to_ui_.GetWeakPtr(), base::Passed(&callback),
@@ -678,7 +691,7 @@ void PushMessagingManager::Core::UnregisterFromService(
void PushMessagingManager::Core::DidUnregisterFromService(
UnsubscribeCallback callback,
int64_t service_worker_registration_id,
- mojom::PushUnregistrationStatus unregistration_status) {
+ blink::mojom::PushUnregistrationStatus unregistration_status) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::PostTaskWithTraits(
@@ -689,30 +702,30 @@ void PushMessagingManager::Core::DidUnregisterFromService(
void PushMessagingManager::DidUnregister(
UnsubscribeCallback callback,
- mojom::PushUnregistrationStatus unregistration_status) {
+ blink::mojom::PushUnregistrationStatus unregistration_status) {
// Only called from IO thread, but would be safe to call from UI thread.
DCHECK_CURRENTLY_ON(BrowserThread::IO);
switch (unregistration_status) {
- case mojom::PushUnregistrationStatus::SUCCESS_UNREGISTERED:
- case mojom::PushUnregistrationStatus::PENDING_NETWORK_ERROR:
- case mojom::PushUnregistrationStatus::PENDING_SERVICE_ERROR:
+ case blink::mojom::PushUnregistrationStatus::SUCCESS_UNREGISTERED:
+ case blink::mojom::PushUnregistrationStatus::PENDING_NETWORK_ERROR:
+ case blink::mojom::PushUnregistrationStatus::PENDING_SERVICE_ERROR:
std::move(callback).Run(blink::WebPushError::kErrorTypeNone,
true /* did_unsubscribe */,
base::nullopt /* error_message */);
break;
- case mojom::PushUnregistrationStatus::SUCCESS_WAS_NOT_REGISTERED:
+ case blink::mojom::PushUnregistrationStatus::SUCCESS_WAS_NOT_REGISTERED:
std::move(callback).Run(blink::WebPushError::kErrorTypeNone,
false /* did_unsubscribe */,
base::nullopt /* error_message */);
break;
- case mojom::PushUnregistrationStatus::NO_SERVICE_WORKER:
- case mojom::PushUnregistrationStatus::SERVICE_NOT_AVAILABLE:
- case mojom::PushUnregistrationStatus::STORAGE_ERROR:
+ case blink::mojom::PushUnregistrationStatus::NO_SERVICE_WORKER:
+ case blink::mojom::PushUnregistrationStatus::SERVICE_NOT_AVAILABLE:
+ case blink::mojom::PushUnregistrationStatus::STORAGE_ERROR:
std::move(callback).Run(blink::WebPushError::kErrorTypeAbort, false,
std::string(PushUnregistrationStatusToString(
unregistration_status)) /* error_message */);
break;
- case mojom::PushUnregistrationStatus::NETWORK_ERROR:
+ case blink::mojom::PushUnregistrationStatus::NETWORK_ERROR:
NOTREACHED();
break;
}
@@ -739,25 +752,27 @@ void PushMessagingManager::GetSubscription(
void PushMessagingManager::DidGetSubscription(
GetSubscriptionCallback callback,
int64_t service_worker_registration_id,
- const std::vector<std::string>& push_subscription_id_and_sender_info,
+ const std::vector<std::string>&
+ push_subscription_id_and_application_server_key,
blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- mojom::PushGetRegistrationStatus get_status =
- mojom::PushGetRegistrationStatus::STORAGE_ERROR;
+ blink::mojom::PushGetRegistrationStatus get_status =
+ blink::mojom::PushGetRegistrationStatus::STORAGE_ERROR;
switch (service_worker_status) {
case blink::ServiceWorkerStatusCode::kOk: {
- DCHECK_EQ(2u, push_subscription_id_and_sender_info.size());
+ DCHECK_EQ(2u, push_subscription_id_and_application_server_key.size());
const std::string& push_subscription_id =
- push_subscription_id_and_sender_info[0];
- const std::string& sender_info = push_subscription_id_and_sender_info[1];
+ push_subscription_id_and_application_server_key[0];
+ const std::string& application_server_key =
+ push_subscription_id_and_application_server_key[1];
if (!service_available_) {
// Return not found in incognito mode, so websites can't detect it.
- get_status =
- ui_core_->is_incognito()
- ? mojom::PushGetRegistrationStatus::
- INCOGNITO_REGISTRATION_NOT_FOUND
- : mojom::PushGetRegistrationStatus::SERVICE_NOT_AVAILABLE;
+ get_status = ui_core_->is_incognito()
+ ? blink::mojom::PushGetRegistrationStatus::
+ INCOGNITO_REGISTRATION_NOT_FOUND
+ : blink::mojom::PushGetRegistrationStatus::
+ SERVICE_NOT_AVAILABLE;
break;
}
@@ -765,13 +780,15 @@ void PushMessagingManager::DidGetSubscription(
service_worker_context_->GetLiveRegistration(
service_worker_registration_id);
if (!registration) {
- get_status = mojom::PushGetRegistrationStatus::NO_LIVE_SERVICE_WORKER;
+ get_status =
+ blink::mojom::PushGetRegistrationStatus::NO_LIVE_SERVICE_WORKER;
break;
}
const GURL origin = registration->scope().GetOrigin();
- const bool uses_standard_protocol = IsApplicationServerKey(sender_info);
+ const bool uses_standard_protocol =
+ IsApplicationServerKey(application_server_key);
const GURL endpoint =
CreateEndpoint(uses_standard_protocol, push_subscription_id);
@@ -779,21 +796,22 @@ void PushMessagingManager::DidGetSubscription(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Core::GetSubscriptionInfoOnUI,
base::Unretained(ui_core_.get()), origin,
- service_worker_registration_id, sender_info,
+ service_worker_registration_id, application_server_key,
push_subscription_id,
base::Bind(&Core::GetSubscriptionDidGetInfoOnUI,
ui_core_weak_ptr_, base::Passed(&callback),
origin, service_worker_registration_id,
- endpoint, sender_info)));
+ endpoint, application_server_key)));
return;
}
case blink::ServiceWorkerStatusCode::kErrorNotFound: {
- get_status = mojom::PushGetRegistrationStatus::REGISTRATION_NOT_FOUND;
+ get_status =
+ blink::mojom::PushGetRegistrationStatus::REGISTRATION_NOT_FOUND;
break;
}
case blink::ServiceWorkerStatusCode::kErrorFailed: {
- get_status = mojom::PushGetRegistrationStatus::STORAGE_ERROR;
+ get_status = blink::mojom::PushGetRegistrationStatus::STORAGE_ERROR;
break;
}
case blink::ServiceWorkerStatusCode::kErrorAbort:
@@ -816,7 +834,7 @@ void PushMessagingManager::DidGetSubscription(
NOTREACHED() << "Got unexpected error code: "
<< static_cast<uint32_t>(service_worker_status) << " "
<< blink::ServiceWorkerStatusToString(service_worker_status);
- get_status = mojom::PushGetRegistrationStatus::STORAGE_ERROR;
+ get_status = blink::mojom::PushGetRegistrationStatus::STORAGE_ERROR;
break;
}
}
@@ -831,22 +849,22 @@ void PushMessagingManager::Core::GetSubscriptionDidGetInfoOnUI(
const GURL& origin,
int64_t service_worker_registration_id,
const GURL& endpoint,
- const std::string& sender_info,
+ const std::string& application_server_key,
bool is_valid,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (is_valid) {
- PushSubscriptionOptions options;
+ blink::WebPushSubscriptionOptions options;
// Chrome rejects subscription requests with userVisibleOnly false, so it
// must have been true. TODO(harkness): If Chrome starts accepting silent
// push subscriptions with userVisibleOnly false, the bool will need to be
// stored.
options.user_visible_only = true;
- options.sender_info = sender_info;
+ options.application_server_key = application_server_key;
- mojom::PushGetRegistrationStatus status =
- mojom::PushGetRegistrationStatus::SUCCESS;
+ blink::mojom::PushGetRegistrationStatus status =
+ blink::mojom::PushGetRegistrationStatus::SUCCESS;
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), status,
@@ -861,11 +879,11 @@ void PushMessagingManager::Core::GetSubscriptionDidGetInfoOnUI(
// shutting down.
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
- base::BindOnce(std::move(callback),
- mojom::PushGetRegistrationStatus::RENDERER_SHUTDOWN,
- base::nullopt /* endpoint */,
- base::nullopt /* options */,
- base::nullopt /* p256dh */, base::nullopt /* auth */));
+ base::BindOnce(
+ std::move(callback),
+ blink::mojom::PushGetRegistrationStatus::RENDERER_SHUTDOWN,
+ base::nullopt /* endpoint */, base::nullopt /* options */,
+ base::nullopt /* p256dh */, base::nullopt /* auth */));
return;
}
@@ -873,15 +891,16 @@ void PushMessagingManager::Core::GetSubscriptionDidGetInfoOnUI(
// database, it did not have matching counterparts in the
// PushMessagingAppIdentifier map and/or GCM Store. Unsubscribe to fix this
// inconsistency.
- mojom::PushGetRegistrationStatus status =
- mojom::PushGetRegistrationStatus::STORAGE_CORRUPT;
+ blink::mojom::PushGetRegistrationStatus status =
+ blink::mojom::PushGetRegistrationStatus::STORAGE_CORRUPT;
- push_service->Unsubscribe(
- mojom::PushUnregistrationReason::GET_SUBSCRIPTION_STORAGE_CORRUPT,
- origin, service_worker_registration_id, sender_info,
- base::Bind(&Core::GetSubscriptionDidUnsubscribe,
- weak_factory_ui_to_ui_.GetWeakPtr(), base::Passed(&callback),
- status));
+ push_service->Unsubscribe(blink::mojom::PushUnregistrationReason::
+ GET_SUBSCRIPTION_STORAGE_CORRUPT,
+ origin, service_worker_registration_id,
+ application_server_key,
+ base::Bind(&Core::GetSubscriptionDidUnsubscribe,
+ weak_factory_ui_to_ui_.GetWeakPtr(),
+ base::Passed(&callback), status));
RecordGetRegistrationStatus(status);
}
@@ -889,8 +908,8 @@ void PushMessagingManager::Core::GetSubscriptionDidGetInfoOnUI(
void PushMessagingManager::Core::GetSubscriptionDidUnsubscribe(
GetSubscriptionCallback callback,
- mojom::PushGetRegistrationStatus get_status,
- mojom::PushUnregistrationStatus unsubscribe_status) {
+ blink::mojom::PushGetRegistrationStatus get_status,
+ blink::mojom::PushUnregistrationStatus unsubscribe_status) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
diff --git a/chromium/content/browser/push_messaging/push_messaging_manager.h b/chromium/content/browser/push_messaging/push_messaging_manager.h
index 36ce6e248b9..ec6c0a55bf5 100644
--- a/chromium/content/browser/push_messaging/push_messaging_manager.h
+++ b/chromium/content/browser/push_messaging/push_messaging_manager.h
@@ -13,38 +13,41 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "content/common/push_messaging.mojom.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 "third_party/blink/public/mojom/push_messaging/push_messaging.mojom.h"
#include "url/gurl.h"
-namespace content {
-
+namespace blink {
namespace mojom {
+class PushMessagingService;
enum class PushRegistrationStatus;
enum class PushUnregistrationStatus;
} // namespace mojom
-class PushMessagingService;
+struct WebPushSubscriptionOptions;
+} // namespace blink
+
+namespace content {
+
class ServiceWorkerContextWrapper;
-struct PushSubscriptionOptions;
// Documented at definition.
extern const char kPushSenderIdServiceWorkerKey[];
extern const char kPushRegistrationIdServiceWorkerKey[];
-class PushMessagingManager : public mojom::PushMessaging {
+class PushMessagingManager : public blink::mojom::PushMessaging {
public:
PushMessagingManager(int render_process_id,
ServiceWorkerContextWrapper* service_worker_context);
- void BindRequest(mojom::PushMessagingRequest request);
+ void BindRequest(blink::mojom::PushMessagingRequest request);
- // mojom::PushMessaging impl, run on IO thread.
+ // blink::mojom::PushMessaging impl, run on IO thread.
void Subscribe(int32_t render_frame_id,
int64_t service_worker_registration_id,
- const PushSubscriptionOptions& options,
+ const blink::WebPushSubscriptionOptions& options,
bool user_gesture,
SubscribeCallback callback) override;
void Unsubscribe(int64_t service_worker_registration_id,
@@ -77,22 +80,22 @@ class PushMessagingManager : public mojom::PushMessaging {
const std::string& push_subscription_id,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth,
- mojom::PushRegistrationStatus status);
+ blink::mojom::PushRegistrationStatus status);
void DidPersistRegistrationOnIO(
RegisterData data,
const std::string& push_subscription_id,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth,
- mojom::PushRegistrationStatus push_registration_status,
+ blink::mojom::PushRegistrationStatus push_registration_status,
blink::ServiceWorkerStatusCode service_worker_status);
// Called both from IO thread, and via PostTask from UI thread.
void SendSubscriptionError(RegisterData data,
- mojom::PushRegistrationStatus status);
+ blink::mojom::PushRegistrationStatus status);
// Called both from IO thread, and via PostTask from UI thread.
void SendSubscriptionSuccess(RegisterData data,
- mojom::PushRegistrationStatus status,
+ blink::mojom::PushRegistrationStatus status,
const std::string& push_subscription_id,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth);
@@ -105,8 +108,9 @@ class PushMessagingManager : public mojom::PushMessaging {
blink::ServiceWorkerStatusCode service_worker_status);
// Called both from IO thread, and via PostTask from UI thread.
- void DidUnregister(UnsubscribeCallback callback,
- mojom::PushUnregistrationStatus unregistration_status);
+ void DidUnregister(
+ UnsubscribeCallback callback,
+ blink::mojom::PushUnregistrationStatus unregistration_status);
void DidGetSubscription(
GetSubscriptionCallback callback,
@@ -136,7 +140,7 @@ class PushMessagingManager : public mojom::PushMessaging {
GURL default_endpoint_;
GURL web_push_protocol_endpoint_;
- mojo::BindingSet<mojom::PushMessaging> bindings_;
+ mojo::BindingSet<blink::mojom::PushMessaging> bindings_;
base::WeakPtrFactory<PushMessagingManager> weak_factory_io_to_io_;
diff --git a/chromium/content/browser/push_messaging/push_messaging_router.cc b/chromium/content/browser/push_messaging/push_messaging_router.cc
index ede879d7003..faf517677a3 100644
--- a/chromium/content/browser/push_messaging/push_messaging_router.cc
+++ b/chromium/content/browser/push_messaging/push_messaging_router.cc
@@ -9,15 +9,16 @@
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "base/task/post_task.h"
+#include "content/browser/devtools/devtools_background_services_context_impl.h"
#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/browser/storage_partition_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/common/push_messaging_status.mojom.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom.h"
namespace content {
@@ -25,7 +26,7 @@ namespace {
void RunDeliverCallback(
const PushMessagingRouter::DeliverMessageCallback& deliver_message_callback,
- mojom::PushDeliveryStatus delivery_status) {
+ blink::mojom::PushDeliveryStatus delivery_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
@@ -39,6 +40,7 @@ void PushMessagingRouter::DeliverMessage(
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
+ const std::string& message_id,
base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -47,20 +49,28 @@ void PushMessagingRouter::DeliverMessage(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
static_cast<ServiceWorkerContextWrapper*>(
partition->GetServiceWorkerContext());
+ auto devtools_context =
+ base::WrapRefCounted<DevToolsBackgroundServicesContextImpl>(
+ service_worker_context->storage_partition()
+ ->GetDevToolsBackgroundServicesContext());
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PushMessagingRouter::FindServiceWorkerRegistration,
- origin, service_worker_registration_id, std::move(payload),
- deliver_message_callback, service_worker_context));
+ std::move(service_worker_context),
+ std::move(devtools_context), origin,
+ service_worker_registration_id, message_id,
+ std::move(payload), deliver_message_callback));
}
// static
void PushMessagingRouter::FindServiceWorkerRegistration(
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context,
const GURL& origin,
int64_t service_worker_registration_id,
+ const std::string& message_id,
base::Optional<std::string> payload,
- const DeliverMessageCallback& deliver_message_callback,
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
+ const DeliverMessageCallback& deliver_message_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Try to acquire the registration from storage. If it's already live we'll
// receive it right away. If not, it will be revived from storage.
@@ -68,11 +78,14 @@ void PushMessagingRouter::FindServiceWorkerRegistration(
service_worker_registration_id, origin,
base::BindOnce(
&PushMessagingRouter::FindServiceWorkerRegistrationCallback,
- std::move(payload), deliver_message_callback));
+ std::move(devtools_context), message_id, std::move(payload),
+ deliver_message_callback));
}
// static
void PushMessagingRouter::FindServiceWorkerRegistrationCallback(
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context,
+ const std::string& message_id,
base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback,
blink::ServiceWorkerStatusCode service_worker_status,
@@ -82,12 +95,12 @@ void PushMessagingRouter::FindServiceWorkerRegistrationCallback(
service_worker_status);
if (service_worker_status == blink::ServiceWorkerStatusCode::kErrorNotFound) {
RunDeliverCallback(deliver_message_callback,
- mojom::PushDeliveryStatus::NO_SERVICE_WORKER);
+ blink::mojom::PushDeliveryStatus::NO_SERVICE_WORKER);
return;
}
if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
RunDeliverCallback(deliver_message_callback,
- mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR);
+ blink::mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR);
return;
}
@@ -101,54 +114,80 @@ void PushMessagingRouter::FindServiceWorkerRegistrationCallback(
version->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::PUSH,
base::BindOnce(&PushMessagingRouter::DeliverMessageToWorker,
- base::WrapRefCounted(version), service_worker_registration,
+ base::WrapRefCounted(version),
+ std::move(service_worker_registration),
+ std::move(devtools_context), message_id,
std::move(payload), deliver_message_callback));
}
// static
void PushMessagingRouter::DeliverMessageToWorker(
- const scoped_refptr<ServiceWorkerVersion>& service_worker,
- const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
+ scoped_refptr<ServiceWorkerVersion> service_worker,
+ scoped_refptr<ServiceWorkerRegistration> service_worker_registration,
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context,
+ const std::string& message_id,
base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback,
blink::ServiceWorkerStatusCode start_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
- DeliverMessageEnd(deliver_message_callback, service_worker_registration,
- start_worker_status);
+ DeliverMessageEnd(std::move(service_worker),
+ std::move(service_worker_registration),
+ std::move(devtools_context), message_id,
+ deliver_message_callback, start_worker_status);
return;
}
int request_id = service_worker->StartRequestWithCustomTimeout(
ServiceWorkerMetrics::EventType::PUSH,
- base::BindOnce(&PushMessagingRouter::DeliverMessageEnd,
- deliver_message_callback, service_worker_registration),
+ base::BindOnce(&PushMessagingRouter::DeliverMessageEnd, service_worker,
+ std::move(service_worker_registration), devtools_context,
+ message_id, deliver_message_callback),
base::TimeDelta::FromSeconds(blink::mojom::kPushEventTimeoutSeconds),
ServiceWorkerVersion::KILL_ON_TIMEOUT);
service_worker->endpoint()->DispatchPushEvent(
payload, service_worker->CreateSimpleEventCallback(request_id));
+
+ if (devtools_context->IsRecording(
+ DevToolsBackgroundService::kPushMessaging)) {
+ std::map<std::string, std::string> event_metadata;
+ if (payload)
+ event_metadata["Payload"] = *payload;
+ devtools_context->LogBackgroundServiceEventOnIO(
+ service_worker->registration_id(), service_worker->script_origin(),
+ DevToolsBackgroundService::kPushMessaging, "Push event dispatched",
+ message_id, event_metadata);
+ }
}
// static
void PushMessagingRouter::DeliverMessageEnd(
+ scoped_refptr<ServiceWorkerVersion> service_worker,
+ scoped_refptr<ServiceWorkerRegistration> service_worker_registration,
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context,
+ const std::string& message_id,
const DeliverMessageCallback& deliver_message_callback,
- const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus.ServiceWorkerEvent",
service_worker_status);
- mojom::PushDeliveryStatus delivery_status =
- mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR;
+ blink::mojom::PushDeliveryStatus delivery_status =
+ blink::mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR;
+ std::string status_description;
switch (service_worker_status) {
case blink::ServiceWorkerStatusCode::kOk:
- delivery_status = mojom::PushDeliveryStatus::SUCCESS;
+ delivery_status = blink::mojom::PushDeliveryStatus::SUCCESS;
+ status_description = "Success";
break;
case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
- delivery_status = mojom::PushDeliveryStatus::EVENT_WAITUNTIL_REJECTED;
+ delivery_status =
+ blink::mojom::PushDeliveryStatus::EVENT_WAITUNTIL_REJECTED;
+ status_description = "waitUntil Rejected";
break;
case blink::ServiceWorkerStatusCode::kErrorTimeout:
- delivery_status = mojom::PushDeliveryStatus::TIMEOUT;
+ delivery_status = blink::mojom::PushDeliveryStatus::TIMEOUT;
+ status_description = "Timeout";
break;
case blink::ServiceWorkerStatusCode::kErrorFailed:
case blink::ServiceWorkerStatusCode::kErrorAbort:
@@ -160,7 +199,7 @@ void PushMessagingRouter::DeliverMessageEnd(
case blink::ServiceWorkerStatusCode::kErrorDiskCache:
case blink::ServiceWorkerStatusCode::kErrorRedundant:
case blink::ServiceWorkerStatusCode::kErrorDisallowed:
- delivery_status = mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR;
+ delivery_status = blink::mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR;
break;
case blink::ServiceWorkerStatusCode::kErrorExists:
case blink::ServiceWorkerStatusCode::kErrorInstallWorkerFailed:
@@ -172,10 +211,20 @@ void PushMessagingRouter::DeliverMessageEnd(
NOTREACHED() << "Got unexpected error code: "
<< static_cast<uint32_t>(service_worker_status) << " "
<< blink::ServiceWorkerStatusToString(service_worker_status);
- delivery_status = mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR;
+ delivery_status = blink::mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR;
break;
}
RunDeliverCallback(deliver_message_callback, delivery_status);
+
+ if (devtools_context->IsRecording(
+ DevToolsBackgroundService::kPushMessaging) &&
+ delivery_status !=
+ blink::mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR) {
+ devtools_context->LogBackgroundServiceEventOnIO(
+ service_worker->registration_id(), service_worker->script_origin(),
+ DevToolsBackgroundService::kPushMessaging, "Push event completed",
+ message_id, {{"Status", status_description}});
+ }
}
} // namespace content
diff --git a/chromium/content/browser/push_messaging/push_messaging_router.h b/chromium/content/browser/push_messaging/push_messaging_router.h
index 773bed1ee05..13b1f106169 100644
--- a/chromium/content/browser/push_messaging/push_messaging_router.h
+++ b/chromium/content/browser/push_messaging/push_messaging_router.h
@@ -9,18 +9,21 @@
#include "base/callback_forward.h"
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
-namespace content {
-
+namespace blink {
namespace mojom {
enum class PushDeliveryStatus;
-}
+} // namespace mojom
+} // namespace blink
+
+namespace content {
class BrowserContext;
+class DevToolsBackgroundServicesContextImpl;
class ServiceWorkerContextWrapper;
class ServiceWorkerRegistration;
class ServiceWorkerVersion;
@@ -28,7 +31,7 @@ class ServiceWorkerVersion;
class PushMessagingRouter {
public:
using DeliverMessageCallback =
- base::Callback<void(mojom::PushDeliveryStatus)>;
+ base::Callback<void(blink::mojom::PushDeliveryStatus)>;
// Delivers a push message with |data| to the Service Worker identified by
// |origin| and |service_worker_registration_id|. Must be called on the UI
@@ -37,6 +40,7 @@ class PushMessagingRouter {
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
+ const std::string& message_id,
base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback);
@@ -44,16 +48,20 @@ class PushMessagingRouter {
// Attempts to find a Service Worker registration so that a push event can be
// dispatched. Must be called on the IO thread.
static void FindServiceWorkerRegistration(
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context,
const GURL& origin,
int64_t service_worker_registration_id,
+ const std::string& message_id,
base::Optional<std::string> payload,
- const DeliverMessageCallback& deliver_message_callback,
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
+ const DeliverMessageCallback& deliver_message_callback);
// If a registration was successfully retrieved, dispatches a push event with
// |data| on the Service Worker identified by |service_worker_registration|.
// Must be called on the IO thread.
static void FindServiceWorkerRegistrationCallback(
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context,
+ const std::string& message_id,
base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback,
blink::ServiceWorkerStatusCode service_worker_status,
@@ -62,9 +70,10 @@ class PushMessagingRouter {
// Delivers a push message with |data| to a specific |service_worker|.
// Must be called on the IO thread.
static void DeliverMessageToWorker(
- const scoped_refptr<ServiceWorkerVersion>& service_worker,
- const scoped_refptr<ServiceWorkerRegistration>&
- service_worker_registration,
+ scoped_refptr<ServiceWorkerVersion> service_worker,
+ scoped_refptr<ServiceWorkerRegistration> service_worker_registration,
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context,
+ const std::string& message_id,
base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback,
blink::ServiceWorkerStatusCode start_worker_status);
@@ -72,9 +81,11 @@ class PushMessagingRouter {
// Gets called asynchronously after the Service Worker has dispatched the push
// event. Must be called on the IO thread.
static void DeliverMessageEnd(
+ scoped_refptr<ServiceWorkerVersion> service_worker,
+ scoped_refptr<ServiceWorkerRegistration> service_worker_registration,
+ scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context,
+ const std::string& message_id,
const DeliverMessageCallback& deliver_message_callback,
- const scoped_refptr<ServiceWorkerRegistration>&
- service_worker_registration,
blink::ServiceWorkerStatusCode service_worker_status);
DISALLOW_IMPLICIT_CONSTRUCTORS(PushMessagingRouter);
diff --git a/chromium/content/browser/renderer_host/DEPS b/chromium/content/browser/renderer_host/DEPS
index 0e360ca4a10..83f75617505 100644
--- a/chromium/content/browser/renderer_host/DEPS
+++ b/chromium/content/browser/renderer_host/DEPS
@@ -27,16 +27,16 @@ specific_include_rules = {
"+content/public/browser/web_contents_delegate.h",
"+content/public/browser/web_contents_view.h",
],
+ ".*_mac.*": [
+ "+content/app_shim_remote_cocoa",
+ "+components/remote_cocoa",
+ ],
"render_process_host_impl\.cc": [
"+content/browser/frame_host/render_frame_message_filter.h",
# TODO(crbug.com/734668): Dependencies on ozone should be removed, as content
# embedded in mus won't be able to talk to the native ozone.
"+ui/ozone/public/ozone_switches.h",
],
- "render_widget_host_view_cocoa\.mm": [
- "+content/browser/frame_host",
- "+content/public/browser/web_contents.h",
- ],
"render_widget_host_view_mac\.mm": [
"+content/browser/frame_host",
"+content/public/browser/web_contents.h",
diff --git a/chromium/content/browser/renderer_host/OWNERS b/chromium/content/browser/renderer_host/OWNERS
index 8fd8f853478..16fba62bfcd 100644
--- a/chromium/content/browser/renderer_host/OWNERS
+++ b/chromium/content/browser/renderer_host/OWNERS
@@ -15,7 +15,6 @@ per-file *android*=khushalsagar@chromium.org
# For touch/gesture specific changes
rjkroege@chromium.org
sadrul@chromium.org
-tdresser@chromium.org
# For surface ID propagation and synchronization
fsamuel@chromium.org
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 625566d5ad2..4b3f3c7e97e 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/containers/circular_deque.h"
#include "base/lazy_instance.h"
+#include "base/optional.h"
#include "base/trace_event/trace_event.h"
#include "components/viz/common/features.h"
#include "components/viz/common/surfaces/local_surface_id_allocation.h"
@@ -293,7 +294,7 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
delegated_frame_host_->HasSavedFrame();
delegated_frame_host_->WasShown(
GetRendererLocalSurfaceIdAllocation().local_surface_id(), dfh_size_dip_,
- false /* record_presentation_time */);
+ base::nullopt /* record_tab_switch_time_request */);
}
// static
diff --git a/chromium/content/browser/renderer_host/clipboard_host_impl.cc b/chromium/content/browser/renderer_host/clipboard_host_impl.cc
index dfeacca8fb8..a000b88cc65 100644
--- a/chromium/content/browser/renderer_host/clipboard_host_impl.cc
+++ b/chromium/content/browser/renderer_host/clipboard_host_impl.cc
@@ -141,23 +141,20 @@ void ClipboardHostImpl::ReadCustomData(ui::ClipboardType clipboard_type,
std::move(callback).Run(result);
}
-void ClipboardHostImpl::WriteText(ui::ClipboardType,
- const base::string16& text) {
+void ClipboardHostImpl::WriteText(const base::string16& text) {
clipboard_writer_->WriteText(text);
}
-void ClipboardHostImpl::WriteHtml(ui::ClipboardType,
- const base::string16& markup,
+void ClipboardHostImpl::WriteHtml(const base::string16& markup,
const GURL& url) {
clipboard_writer_->WriteHTML(markup, url.spec());
}
-void ClipboardHostImpl::WriteSmartPasteMarker(ui::ClipboardType) {
+void ClipboardHostImpl::WriteSmartPasteMarker() {
clipboard_writer_->WriteWebSmartPaste();
}
void ClipboardHostImpl::WriteCustomData(
- ui::ClipboardType,
const base::flat_map<base::string16, base::string16>& data) {
base::Pickle pickle;
ui::WriteCustomDataToPickle(data, &pickle);
@@ -165,17 +162,16 @@ void ClipboardHostImpl::WriteCustomData(
pickle, ui::ClipboardFormatType::GetWebCustomDataType());
}
-void ClipboardHostImpl::WriteBookmark(ui::ClipboardType,
- const std::string& url,
+void ClipboardHostImpl::WriteBookmark(const std::string& url,
const base::string16& title) {
clipboard_writer_->WriteBookmark(title, url);
}
-void ClipboardHostImpl::WriteImage(ui::ClipboardType, const SkBitmap& bitmap) {
+void ClipboardHostImpl::WriteImage(const SkBitmap& bitmap) {
clipboard_writer_->WriteImage(bitmap);
}
-void ClipboardHostImpl::CommitWrite(ui::ClipboardType) {
+void ClipboardHostImpl::CommitWrite() {
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 82a0d6be9de..dd64dec79db 100644
--- a/chromium/content/browser/renderer_host/clipboard_host_impl.h
+++ b/chromium/content/browser/renderer_host/clipboard_host_impl.h
@@ -55,21 +55,15 @@ class CONTENT_EXPORT ClipboardHostImpl : public blink::mojom::ClipboardHost {
void ReadCustomData(ui::ClipboardType clipboard_type,
const base::string16& type,
ReadCustomDataCallback callback) override;
- void WriteText(ui::ClipboardType clipboard_type,
- const base::string16& text) override;
- void WriteHtml(ui::ClipboardType clipboard_type,
- const base::string16& markup,
- const GURL& url) override;
- void WriteSmartPasteMarker(ui::ClipboardType clipboard_type) override;
+ void WriteText(const base::string16& text) override;
+ void WriteHtml(const base::string16& markup, const GURL& url) override;
+ void WriteSmartPasteMarker() override;
void WriteCustomData(
- ui::ClipboardType clipboard_type,
const base::flat_map<base::string16, base::string16>& data) override;
- void WriteBookmark(ui::ClipboardType clipboard_type,
- const std::string& url,
+ void WriteBookmark(const std::string& url,
const base::string16& title) override;
- void WriteImage(ui::ClipboardType clipboard_type,
- const SkBitmap& bitmap) override;
- void CommitWrite(ui::ClipboardType clipboard_type) override;
+ void WriteImage(const SkBitmap& bitmap) override;
+ void CommitWrite() override;
#if defined(OS_MACOSX)
void WriteStringToFindPboard(const base::string16& text) override;
#endif
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 05cb4a1249d..62ee6894603 100644
--- a/chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc
@@ -47,10 +47,10 @@ TEST_F(ClipboardHostImplTest, SimpleImage) {
SkBitmap bitmap;
bitmap.allocN32Pixels(3, 2);
bitmap.eraseARGB(255, 0, 255, 0);
- mojo_clipboard()->WriteImage(ui::CLIPBOARD_TYPE_COPY_PASTE, bitmap);
+ mojo_clipboard()->WriteImage(bitmap);
uint64_t sequence_number =
system_clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE);
- mojo_clipboard()->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ mojo_clipboard()->CommitWrite();
base::RunLoop().RunUntilIdle();
EXPECT_NE(sequence_number, system_clipboard()->GetSequenceNumber(
diff --git a/chromium/content/browser/renderer_host/code_cache_host_impl.cc b/chromium/content/browser/renderer_host/code_cache_host_impl.cc
index b40aafdbc98..e2a51508009 100644
--- a/chromium/content/browser/renderer_host/code_cache_host_impl.cc
+++ b/chromium/content/browser/renderer_host/code_cache_host_impl.cc
@@ -9,6 +9,7 @@
#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
+#include "content/browser/cache_storage/cache_storage.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
@@ -126,7 +127,7 @@ void CodeCacheHostImpl::DidGenerateCacheableMetadata(
blink::mojom::CodeCacheType cache_type,
const GURL& url,
base::Time expected_response_time,
- const std::vector<uint8_t>& data) {
+ mojo_base::BigBuffer data) {
if (!url.SchemeIsHTTPOrHTTPS()) {
mojo::ReportBadMessage("Invalid URL scheme for code cache.");
return;
@@ -141,7 +142,7 @@ void CodeCacheHostImpl::DidGenerateCacheableMetadata(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&CodeCacheHostImpl::DidGenerateCacheableMetadataOnUI,
render_process_id_, url, expected_response_time,
- data));
+ std::move(data)));
} else {
mojo::ReportBadMessage("Single-keyed code cache is Javascript only.");
return;
@@ -200,7 +201,7 @@ void CodeCacheHostImpl::ClearCodeCacheEntry(
void CodeCacheHostImpl::DidGenerateCacheableMetadataInCacheStorage(
const GURL& url,
base::Time expected_response_time,
- const std::vector<uint8_t>& data,
+ mojo_base::BigBuffer data,
const url::Origin& cache_storage_origin,
const std::string& cache_storage_cache_name) {
int64_t trace_id = blink::cache_storage::CreateTraceId();
@@ -214,8 +215,8 @@ void CodeCacheHostImpl::DidGenerateCacheableMetadataInCacheStorage(
scoped_refptr<net::IOBuffer> buf =
base::MakeRefCounted<net::IOBuffer>(data.size());
- if (!data.empty())
- memcpy(buf->data(), &data.front(), data.size());
+ if (data.size())
+ memcpy(buf->data(), data.data(), data.size());
CacheStorageHandle cache_storage =
cache_storage_context_->cache_manager()->OpenCacheStorage(
@@ -272,7 +273,7 @@ void CodeCacheHostImpl::DidGenerateCacheableMetadataOnUI(
int render_process_id,
const GURL& url,
base::Time expected_response_time,
- const std::vector<uint8_t>& data) {
+ mojo_base::BigBuffer data) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
if (!host)
@@ -285,7 +286,7 @@ void CodeCacheHostImpl::DidGenerateCacheableMetadataOnUI(
// in weburlloader_impl.cc).
const net::RequestPriority kPriority = net::LOW;
host->GetStoragePartition()->GetNetworkContext()->WriteCacheMetadata(
- url, kPriority, expected_response_time, data);
+ url, kPriority, expected_response_time, std::move(data));
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/code_cache_host_impl.h b/chromium/content/browser/renderer_host/code_cache_host_impl.h
index 368f8886221..f80f7ed3c48 100644
--- a/chromium/content/browser/renderer_host/code_cache_host_impl.h
+++ b/chromium/content/browser/renderer_host/code_cache_host_impl.h
@@ -13,6 +13,7 @@
#include "build/build_config.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/common/content_export.h"
+#include "mojo/public/cpp/base/big_buffer.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h"
#include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
@@ -57,7 +58,7 @@ class CONTENT_EXPORT CodeCacheHostImpl : public blink::mojom::CodeCacheHost {
void DidGenerateCacheableMetadata(blink::mojom::CodeCacheType cache_type,
const GURL& url,
base::Time expected_response_time,
- const std::vector<uint8_t>& data) override;
+ mojo_base::BigBuffer data) override;
void FetchCachedCode(blink::mojom::CodeCacheType cache_type,
const GURL& url,
FetchCachedCodeCallback) override;
@@ -66,7 +67,7 @@ class CONTENT_EXPORT CodeCacheHostImpl : public blink::mojom::CodeCacheHost {
void DidGenerateCacheableMetadataInCacheStorage(
const GURL& url,
base::Time expected_response_time,
- const std::vector<uint8_t>& data,
+ mojo_base::BigBuffer data,
const url::Origin& cache_storage_origin,
const std::string& cache_storage_cache_name) override;
@@ -86,7 +87,7 @@ class CONTENT_EXPORT CodeCacheHostImpl : public blink::mojom::CodeCacheHost {
int render_process_id,
const GURL& url,
base::Time expected_response_time,
- const std::vector<uint8_t>& data);
+ mojo_base::BigBuffer data);
// Our render process host ID, used to bind to the correct render process.
const int render_process_id_;
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index aa5eb516dbe..9c0dbd139c4 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -57,7 +57,7 @@
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/output_surface_client.h"
#include "components/viz/service/display/output_surface_frame.h"
-#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.h"
+#include "components/viz/service/display_embedder/overlay_candidate_validator_android.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/frame_sink_manager_impl.h"
@@ -103,11 +103,42 @@ namespace {
static const char* kBrowser = "Browser";
+// NOINLINE to make sure crashes use this for magic signature.
+NOINLINE void FatalSurfaceFailure() {
+ LOG(FATAL) << "Fatal surface initialization failure";
+}
+
+gfx::OverlayTransform RotationToDisplayTransform(
+ display::Display::Rotation rotation) {
+ // Note that the angle provided by |rotation| here is the opposite direction
+ // of the physical rotation of the device, which is the space in which the UI
+ // prepares the scene (see
+ // https://developer.android.com/reference/android/view/Display#getRotation()
+ // for details).
+ //
+ // The rotation which needs to be applied by the display compositor to allow
+ // the buffers produced by it to be used directly by the system compositor
+ // needs to be the inverse of this rotation. Since display::Rotation is in
+ // clockwise direction while gfx::OverlayTransform is anti-clockwise, directly
+ // mapping them below performs this inversion.
+ switch (rotation) {
+ case display::Display::ROTATE_0:
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ case display::Display::ROTATE_90:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_90;
+ case display::Display::ROTATE_180:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+ case display::Display::ROTATE_270:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_270;
+ }
+ NOTREACHED();
+ return gfx::OVERLAY_TRANSFORM_NONE;
+}
+
// These functions are called based on application visibility status.
void SendOnBackgroundedToGpuService() {
content::GpuProcessHost::CallOnIO(
- content::GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- false /* force_create */,
+ content::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
base::BindRepeating([](content::GpuProcessHost* host) {
if (host) {
host->gpu_service()->OnBackgrounded();
@@ -117,8 +148,7 @@ void SendOnBackgroundedToGpuService() {
void SendOnForegroundedToGpuService() {
content::GpuProcessHost::CallOnIO(
- content::GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- false /* force_create */,
+ content::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
base::BindRepeating([](content::GpuProcessHost* host) {
if (host) {
host->gpu_service()->OnForegrounded();
@@ -267,8 +297,7 @@ class CompositorDependencies {
// Next, notify the GPU process to do background processing, which will
// lose all renderer contexts.
content::GpuProcessHost::CallOnIO(
- content::GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- false /* force_create */,
+ content::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
base::BindRepeating([](content::GpuProcessHost* host) {
if (host) {
host->gpu_service()->OnBackgroundCleanup();
@@ -404,7 +433,7 @@ class AndroidOutputSurface : public viz::OutputSurface {
: viz::OutputSurface(std::move(context_provider)),
swap_buffers_callback_(std::move(swap_buffers_callback)),
overlay_candidate_validator_(
- new viz::CompositorOverlayCandidateValidatorAndroid()),
+ new viz::OverlayCandidateValidatorAndroid()),
weak_ptr_factory_(this) {
capabilities_.max_frames_pending = kMaxDisplaySwapBuffers;
}
@@ -458,9 +487,9 @@ class AndroidOutputSurface : public viz::OutputSurface {
gl::ColorSpaceUtils::GetGLColorSpace(color_space), has_alpha);
}
- viz::OverlayCandidateValidator* GetOverlayCandidateValidator()
- const override {
- return overlay_candidate_validator_.get();
+ std::unique_ptr<viz::OverlayCandidateValidator>
+ TakeOverlayCandidateValidator() override {
+ return std::move(overlay_candidate_validator_);
}
bool IsDisplayedAsOverlayPlane() const override { return false; }
@@ -479,6 +508,14 @@ class AndroidOutputSurface : public viz::OutputSurface {
unsigned UpdateGpuFence() override { return 0; }
+ void SetUpdateVSyncParametersCallback(
+ viz::UpdateVSyncParametersCallback callback) override {}
+
+ void SetDisplayTransformHint(gfx::OverlayTransform transform) override {}
+ gfx::OverlayTransform GetDisplayTransform() override {
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ }
+
private:
gpu::CommandBufferProxyImpl* GetCommandBufferProxy() {
ws::ContextProviderCommandBuffer* provider_command_buffer =
@@ -526,9 +563,8 @@ class CompositorImpl::AndroidHostDisplayClient : public viz::HostDisplayClient {
void DidCompleteSwapWithSize(const gfx::Size& pixel_size) override {
compositor_->DidSwapBuffers(pixel_size);
}
- void OnFatalOrSurfaceContextCreationFailure(
- gpu::ContextResult context_result) override {
- compositor_->OnFatalOrSurfaceContextCreationFailure(context_result);
+ void OnContextCreationResult(gpu::ContextResult context_result) override {
+ compositor_->OnContextCreationResult(context_result);
}
void SetPreferredRefreshRate(float refresh_rate) override {
if (compositor_->root_window_)
@@ -539,6 +575,20 @@ class CompositorImpl::AndroidHostDisplayClient : public viz::HostDisplayClient {
CompositorImpl* compositor_;
};
+class CompositorImpl::ScopedCachedBackBuffer {
+ public:
+ ScopedCachedBackBuffer(const viz::FrameSinkId& root_sink_id) {
+ cache_id_ =
+ GetHostFrameSinkManager()->CacheBackBufferForRootSink(root_sink_id);
+ }
+ ~ScopedCachedBackBuffer() {
+ GetHostFrameSinkManager()->EvictCachedBackBuffer(cache_id_);
+ }
+
+ private:
+ uint32_t cache_id_;
+};
+
// static
Compositor* Compositor::Create(CompositorClient* client,
gfx::NativeWindow root_window) {
@@ -680,7 +730,7 @@ void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
}
void CompositorImpl::SetSurface(jobject surface,
- bool backed_by_surface_texture) {
+ bool can_be_used_with_surface_control) {
JNIEnv* env = base::android::AttachCurrentThread();
gpu::GpuSurfaceTracker* tracker = gpu::GpuSurfaceTracker::Get();
@@ -691,7 +741,6 @@ void CompositorImpl::SetSurface(jobject surface,
ANativeWindow_release(window_);
window_ = NULL;
surface_handle_ = gpu::kNullSurfaceHandle;
- backed_by_surface_texture_ = false;
}
ANativeWindow* window = NULL;
@@ -705,11 +754,11 @@ void CompositorImpl::SetSurface(jobject surface,
if (window) {
window_ = window;
- backed_by_surface_texture_ = backed_by_surface_texture;
ANativeWindow_acquire(window);
// Register first, SetVisible() might create a LayerTreeFrameSink.
surface_handle_ = tracker->AddSurfaceForNativeWidget(
- gpu::GpuSurfaceTracker::SurfaceRecord(window, surface));
+ gpu::GpuSurfaceTracker::SurfaceRecord(
+ window, surface, can_be_used_with_surface_control));
SetVisible(true);
ANativeWindow_release(window);
}
@@ -973,9 +1022,17 @@ void CompositorImpl::OnGpuChannelEstablished(
requires_alpha_channel_),
ws::command_buffer_metrics::ContextType::BROWSER_COMPOSITOR);
auto result = context_provider->BindToCurrentThread();
+
+ if (surface_handle != gpu::kNullSurfaceHandle) {
+ // Only use OnContextCreationResult for onscreen contexts, where recovering
+ // from a surface initialization failure is possible by re-creating the
+ // native window.
+ OnContextCreationResult(result);
+ } else if (result == gpu::ContextResult::kFatalFailure) {
+ LOG(FATAL) << "Fatal failure in creating offscreen context";
+ }
+
if (result != gpu::ContextResult::kSuccess) {
- if (gpu::IsFatalOrSurfaceFailure(result))
- OnFatalOrSurfaceContextCreationFailure(result);
HandlePendingLayerTreeFrameSinkRequest();
return;
}
@@ -1134,16 +1191,26 @@ void CompositorImpl::RemoveChildFrameSink(
void CompositorImpl::OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) {
- if (changed_metrics & display::DisplayObserver::DisplayMetric::
- DISPLAY_METRIC_DEVICE_SCALE_FACTOR &&
- display.id() == display::Screen::GetScreen()
+ if (display.id() != display::Screen::GetScreen()
->GetDisplayNearestWindow(root_window_)
.id()) {
+ return;
+ }
+
+ if (changed_metrics & display::DisplayObserver::DisplayMetric::
+ DISPLAY_METRIC_DEVICE_SCALE_FACTOR) {
// TODO(ccameron): This is transiently incorrect -- |size_| must be
// recalculated here as well. Is the call in SetWindowBounds sufficient?
host_->SetViewportSizeAndScale(size_, root_window_->GetDipScale(),
GenerateLocalSurfaceId());
}
+
+ if ((changed_metrics &
+ display::DisplayObserver::DisplayMetric::DISPLAY_METRIC_ROTATION) &&
+ display_private_) {
+ display_private_->SetDisplayTransformHint(
+ RotationToDisplayTransform(display.rotation()));
+ }
}
bool CompositorImpl::HavePendingReadbacks() {
@@ -1213,18 +1280,17 @@ void CompositorImpl::InitializeVizLayerTreeFrameSink(
root_params->display_client =
display_client_->GetBoundPtr(task_runner).PassInterface();
+ const auto& display_props =
+ display::Screen::GetScreen()->GetDisplayNearestWindow(root_window_);
+
viz::RendererSettings renderer_settings;
renderer_settings.partial_swap_enabled = true;
renderer_settings.allow_antialiasing = false;
renderer_settings.highp_threshold_min = 2048;
renderer_settings.requires_alpha_channel = requires_alpha_channel_;
- renderer_settings.initial_screen_size =
- display::Screen::GetScreen()
- ->GetDisplayNearestWindow(root_window_)
- .GetSizeInPixel();
+ renderer_settings.initial_screen_size = display_props.GetSizeInPixel();
renderer_settings.use_skia_renderer = features::IsUsingSkiaRenderer();
renderer_settings.color_space = display_color_space_;
- renderer_settings.backed_by_surface_texture = backed_by_surface_texture_;
root_params->frame_sink_id = frame_sink_id_;
root_params->widget = surface_handle_;
@@ -1260,6 +1326,8 @@ void CompositorImpl::InitializeVizLayerTreeFrameSink(
display_private_->SetVSyncPaused(vsync_paused_);
display_private_->SetSupportedRefreshRates(
root_window_->GetSupportedRefreshRates());
+ display_private_->SetDisplayTransformHint(
+ RotationToDisplayTransform(display_props.rotation()));
}
viz::LocalSurfaceIdAllocation CompositorImpl::GenerateLocalSurfaceId() {
@@ -1271,12 +1339,26 @@ viz::LocalSurfaceIdAllocation CompositorImpl::GenerateLocalSurfaceId() {
return viz::LocalSurfaceIdAllocation();
}
+void CompositorImpl::OnContextCreationResult(
+ gpu::ContextResult context_result) {
+ if (!gpu::IsFatalOrSurfaceFailure(context_result)) {
+ num_of_consecutive_surface_failures_ = 0u;
+ return;
+ }
+
+ OnFatalOrSurfaceContextCreationFailure(context_result);
+}
+
void CompositorImpl::OnFatalOrSurfaceContextCreationFailure(
gpu::ContextResult context_result) {
DCHECK(gpu::IsFatalOrSurfaceFailure(context_result));
LOG_IF(FATAL, context_result == gpu::ContextResult::kFatalFailure)
<< "Fatal error making Gpu context";
+ constexpr size_t kMaxConsecutiveSurfaceFailures = 10u;
+ if (++num_of_consecutive_surface_failures_ > kMaxConsecutiveSurfaceFailures)
+ FatalSurfaceFailure();
+
if (context_result == gpu::ContextResult::kSurfaceFailure) {
SetSurface(nullptr, false);
client_->RecreateSurface();
@@ -1287,4 +1369,15 @@ void CompositorImpl::OnFirstSurfaceActivation(const viz::SurfaceInfo& info) {
NOTREACHED();
}
+void CompositorImpl::CacheBackBufferForCurrentSurface() {
+ if (window_ && display_private_) {
+ cached_back_buffer_ =
+ std::make_unique<ScopedCachedBackBuffer>(frame_sink_id_);
+ }
+}
+
+void CompositorImpl::EvictCachedBackBuffer() {
+ cached_back_buffer_.reset();
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.h b/chromium/content/browser/renderer_host/compositor_impl_android.h
index ee5ff6b825d..90af50ab1b2 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -24,6 +24,7 @@
#include "components/viz/common/surfaces/local_surface_id_allocation.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/host/host_frame_sink_client.h"
+#include "components/viz/host/host_frame_sink_manager.h"
#include "content/common/content_export.h"
#include "content/public/browser/android/compositor.h"
#include "gpu/command_buffer/common/capabilities.h"
@@ -33,6 +34,7 @@
#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.h"
#include "ui/android/window_android_compositor.h"
#include "ui/compositor/compositor_lock.h"
#include "ui/compositor/external_begin_frame_client.h"
@@ -55,7 +57,6 @@ class Display;
class FrameSinkId;
class FrameSinkManagerImpl;
class HostDisplayClient;
-class HostFrameSinkManager;
class OutputSurface;
}
@@ -98,17 +99,21 @@ class CONTENT_EXPORT CompositorImpl
private:
class AndroidHostDisplayClient;
+ class ScopedCachedBackBuffer;
// Compositor implementation.
void SetRootWindow(gfx::NativeWindow root_window) override;
void SetRootLayer(scoped_refptr<cc::Layer> root) override;
- void SetSurface(jobject surface, bool backed_by_surface_texture) override;
+ void SetSurface(jobject surface,
+ bool can_be_used_with_surface_control) override;
void SetBackgroundColor(int color) override;
void SetWindowBounds(const gfx::Size& size) override;
void SetRequiresAlphaChannel(bool flag) override;
void SetNeedsComposite() override;
ui::UIResourceProvider& GetUIResourceProvider() override;
ui::ResourceManager& GetResourceManager() override;
+ void CacheBackBufferForCurrentSurface() override;
+ void EvictCachedBackBuffer() override;
// LayerTreeHostClient implementation.
void WillBeginMainFrame() override {}
@@ -141,8 +146,6 @@ class CONTENT_EXPORT CompositorImpl
const gfx::PresentationFeedback& feedback) override {}
void RecordStartOfFrameMetrics() override {}
void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override {}
- void DidGenerateLocalSurfaceIdAllocation(
- const viz::LocalSurfaceIdAllocation& allocation) override {}
// LayerTreeHostSingleThreadClient implementation.
void DidSubmitCompositorFrame() override;
@@ -205,7 +208,8 @@ class CONTENT_EXPORT CompositorImpl
// Registers the root frame sink ID.
void RegisterRootFrameSink();
- // Called when we fail to create the context for the root frame sink.
+ // Called with the result of context creation for the root frame sink.
+ void OnContextCreationResult(gpu::ContextResult context_result);
void OnFatalOrSurfaceContextCreationFailure(
gpu::ContextResult context_result);
@@ -235,7 +239,7 @@ class CONTENT_EXPORT CompositorImpl
ANativeWindow* window_;
gpu::SurfaceHandle surface_handle_;
- bool backed_by_surface_texture_ = false;
+ std::unique_ptr<ScopedCachedBackBuffer> cached_back_buffer_;
CompositorClient* client_;
@@ -278,6 +282,8 @@ class CONTENT_EXPORT CompositorImpl
base::RepeatingCallback<void(const gfx::Size&)>
swap_completed_with_size_for_testing_;
+ size_t num_of_consecutive_surface_failures_ = 0u;
+
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 c242d176a90..aa9f6f1f71d 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc
@@ -25,6 +25,7 @@
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/ipc/client/gpu_channel_host.h"
+#include "media/base/media_switches.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "ui/android/window_android.h"
#include "url/gurl.h"
@@ -46,31 +47,38 @@ class CompositorImplBrowserTest
CompositorImplBrowserTest() {}
void SetUp() override {
+ std::vector<base::Feature> features;
+
switch (GetParam()) {
case CompositorImplMode::kNormal:
break;
case CompositorImplMode::kViz:
- scoped_feature_list_.InitAndEnableFeature(
- features::kVizDisplayCompositor);
+ features =
+ std::vector<base::Feature>({features::kVizDisplayCompositor});
break;
case CompositorImplMode::kVizSkDDL:
- scoped_feature_list_.InitWithFeatures(
+ features = std::vector<base::Feature>(
{features::kVizDisplayCompositor, features::kUseSkiaRenderer,
- features::kDefaultEnableOopRasterization},
- {});
+ features::kDefaultEnableOopRasterization});
break;
}
+ AppendFeatures(&features);
+ scoped_feature_list_.InitWithFeatures(features, {});
+
ContentBrowserTest::SetUp();
}
+ virtual std::string GetTestUrl() { return "/title1.html"; }
+ virtual void AppendFeatures(std::vector<base::Feature>* features) {}
+
protected:
void SetUpOnMainThread() override {
ASSERT_TRUE(embedded_test_server()->Start());
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
ASSERT_TRUE(https_server.Start());
- GURL http_url(embedded_test_server()->GetURL("/title1.html"));
+ GURL http_url(embedded_test_server()->GetURL(GetTestUrl()));
ASSERT_TRUE(NavigateToURL(shell(), http_url));
}
@@ -91,7 +99,6 @@ class CompositorImplBrowserTest
web_contents()->GetRenderWidgetHostView());
}
- private:
base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(CompositorImplBrowserTest);
@@ -267,5 +274,40 @@ IN_PROC_BROWSER_TEST_P(CompositorImplBrowserTest,
CompositorSwapRunLoop(compositor_impl()).RunUntilSwap();
}
+class CompositorImplBrowserTestRefreshRate
+ : public CompositorImplBrowserTest,
+ public ui::WindowAndroid::TestHooks {
+ public:
+ std::string GetTestUrl() override { return "/media/tulip2.webm"; }
+ void AppendFeatures(std::vector<base::Feature>* features) override {
+ features->push_back(media::kUseSurfaceLayerForVideo);
+ }
+
+ // WindowAndroid::TestHooks impl.
+ std::vector<float> GetSupportedRates() override {
+ return {120.f, 90.f, 60.f};
+ }
+ void SetPreferredRate(float refresh_rate) override {
+ if (fabs(refresh_rate - expected_refresh_rate_) < 2.f)
+ run_loop_->Quit();
+ }
+
+ float expected_refresh_rate_ = 0.f;
+ std::unique_ptr<base::RunLoop> run_loop_;
+};
+
+IN_PROC_BROWSER_TEST_P(CompositorImplBrowserTestRefreshRate, VideoPreference) {
+ window()->SetTestHooks(this);
+ expected_refresh_rate_ = 60.f;
+ run_loop_ = std::make_unique<base::RunLoop>();
+ run_loop_->Run();
+ run_loop_.reset();
+ window()->SetTestHooks(nullptr);
+}
+
+INSTANTIATE_TEST_SUITE_P(P,
+ CompositorImplBrowserTestRefreshRate,
+ ::testing::Values(CompositorImplMode::kViz));
+
} // 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 297346e90af..3a5efa9798d 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.cc
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.cc
@@ -92,17 +92,16 @@ DelegatedFrameHost::~DelegatedFrameHost() {
void DelegatedFrameHost::WasShown(
const viz::LocalSurfaceId& new_local_surface_id,
const gfx::Size& new_dip_size,
- bool record_presentation_time,
- base::TimeTicks tab_switch_start_time) {
+ const base::Optional<RecordTabSwitchTimeRequest>&
+ record_tab_switch_time_request) {
// Cancel any pending frame eviction and unpause it if paused.
frame_eviction_state_ = FrameEvictionState::kNotStarted;
frame_evictor_->SetVisible(true);
- if (record_presentation_time && compositor_ &&
- !tab_switch_start_time.is_null()) {
+ if (record_tab_switch_time_request && compositor_) {
compositor_->RequestPresentationTimeForNextFrame(
- tab_switch_time_recorder_.BeginTimeRecording(
- tab_switch_start_time, true /* has_saved_frames */,
+ tab_switch_time_recorder_.TabWasShown(
+ true /* has_saved_frames */, record_tab_switch_time_request.value(),
base::TimeTicks::Now()));
}
@@ -124,6 +123,7 @@ bool DelegatedFrameHost::HasSavedFrame() const {
void DelegatedFrameHost::WasHidden() {
frame_evictor_->SetVisible(false);
+ tab_switch_time_recorder_.TabWasHidden();
}
void DelegatedFrameHost::CopyFromCompositingSurface(
@@ -282,7 +282,10 @@ void DelegatedFrameHost::EmbedSurface(
if (seen_first_activation_)
frame_evictor_->OnNewSurfaceEmbedded();
#else
- frame_evictor_->OnNewSurfaceEmbedded();
+ // Ignore empty frames. Extensions often create empty background page frames
+ // which shouldn't count against the saved frames.
+ if (!new_dip_size.IsEmpty())
+ frame_evictor_->OnNewSurfaceEmbedded();
#endif
if (!primary_surface_id ||
@@ -437,7 +440,8 @@ void DelegatedFrameHost::DidCopyStaleContent(
auto transfer_resource = viz::TransferableResource::MakeGL(
result->GetTextureResult()->mailbox, GL_LINEAR, GL_TEXTURE_2D,
- result->GetTextureResult()->sync_token);
+ result->GetTextureResult()->sync_token, result->size(),
+ false /* is_overlay_candidate */);
std::unique_ptr<viz::SingleReleaseCallback> release_callback =
result->TakeTextureOwnership();
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.h b/chromium/content/browser/renderer_host/delegated_frame_host.h
index ec22dddc722..3e69e97e7d2 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.h
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.h
@@ -111,8 +111,8 @@ class CONTENT_EXPORT DelegatedFrameHost
// TODO(ccameron): Include device scale factor here.
void WasShown(const viz::LocalSurfaceId& local_surface_id,
const gfx::Size& dip_size,
- bool record_presentation_time,
- base::TimeTicks tab_switch_start_time = base::TimeTicks());
+ const base::Optional<RecordTabSwitchTimeRequest>&
+ record_tab_switch_time_request);
void EmbedSurface(const viz::LocalSurfaceId& local_surface_id,
const gfx::Size& dip_size,
cc::DeadlinePolicy deadline_policy);
diff --git a/chromium/content/browser/renderer_host/direct_manipulation_helper_win.cc b/chromium/content/browser/renderer_host/direct_manipulation_helper_win.cc
index d04c3e16229..cc62fd68871 100644
--- a/chromium/content/browser/renderer_host/direct_manipulation_helper_win.cc
+++ b/chromium/content/browser/renderer_host/direct_manipulation_helper_win.cc
@@ -10,6 +10,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/win/window_event_target.h"
@@ -46,7 +47,7 @@ DirectManipulationHelper::CreateInstance(HWND window,
return nullptr;
// DM_POINTERHITTEST supported since Win10.
- if (base::win::GetVersion() < base::win::VERSION_WIN10)
+ if (base::win::GetVersion() < base::win::Version::WIN10)
return nullptr;
std::unique_ptr<DirectManipulationHelper> instance =
@@ -68,7 +69,7 @@ DirectManipulationHelper::CreateInstanceForTesting(
return nullptr;
// DM_POINTERHITTEST supported since Win10.
- if (base::win::GetVersion() < base::win::VERSION_WIN10)
+ if (base::win::GetVersion() < base::win::Version::WIN10)
return nullptr;
std::unique_ptr<DirectManipulationHelper> instance =
@@ -244,8 +245,8 @@ bool DirectManipulationHelper::OnPointerHitTest(
using GetPointerTypeFn = BOOL(WINAPI*)(UINT32, POINTER_INPUT_TYPE*);
UINT32 pointer_id = GET_POINTERID_WPARAM(w_param);
POINTER_INPUT_TYPE pointer_type;
- static GetPointerTypeFn get_pointer_type = reinterpret_cast<GetPointerTypeFn>(
- GetProcAddress(GetModuleHandleA("user32.dll"), "GetPointerType"));
+ static const auto get_pointer_type = reinterpret_cast<GetPointerTypeFn>(
+ base::win::GetUser32FunctionPointer("GetPointerType"));
if (get_pointer_type && get_pointer_type(pointer_id, &pointer_type) &&
pointer_type == PT_TOUCHPAD && event_target) {
HRESULT hr = viewport_->SetContact(pointer_id);
diff --git a/chromium/content/browser/renderer_host/direct_manipulation_win_browsertest.cc b/chromium/content/browser/renderer_host/direct_manipulation_win_browsertest.cc
index 6690f4efb8f..7648cf140d0 100644
--- a/chromium/content/browser/renderer_host/direct_manipulation_win_browsertest.cc
+++ b/chromium/content/browser/renderer_host/direct_manipulation_win_browsertest.cc
@@ -90,7 +90,7 @@ INSTANTIATE_TEST_SUITE_P(WithScrollEventPhase,
// Ensure the AnimationObserver destroy when hwnd reparent to other hwnd.
IN_PROC_BROWSER_TEST_P(DirectManipulationBrowserTest, HWNDReparent) {
- if (base::win::GetVersion() < base::win::VERSION_WIN10)
+ if (base::win::GetVersion() < base::win::Version::WIN10)
return;
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
@@ -147,7 +147,7 @@ class EventLogger : public ui::EventRewriter {
// Check DirectManipulation events convert to ui::event correctly.
IN_PROC_BROWSER_TEST_P(DirectManipulationBrowserTest, EventConvert) {
- if (base::win::GetVersion() < base::win::VERSION_WIN10)
+ if (base::win::GetVersion() < base::win::Version::WIN10)
return;
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
diff --git a/chromium/content/browser/renderer_host/direct_manipulation_win_unittest.cc b/chromium/content/browser/renderer_host/direct_manipulation_win_unittest.cc
index 3c85312232e..3bf1b55555d 100644
--- a/chromium/content/browser/renderer_host/direct_manipulation_win_unittest.cc
+++ b/chromium/content/browser/renderer_host/direct_manipulation_win_unittest.cc
@@ -422,7 +422,7 @@ class DirectManipulationUnitTest : public testing::Test {
TEST_F(DirectManipulationUnitTest, HelperShouldCreateForWin10) {
// We should create DirectManipulationHelper instance when win version >= 10.
EXPECT_EQ(GetDirectManipulationHelper() != nullptr,
- base::win::GetVersion() >= base::win::VERSION_WIN10);
+ base::win::GetVersion() >= base::win::Version::WIN10);
}
TEST_F(DirectManipulationUnitTest, ReceiveSimplePanTransform) {
diff --git a/chromium/content/browser/renderer_host/display_util.cc b/chromium/content/browser/renderer_host/display_util.cc
index 7d0d3d89f5d..2872b73ba53 100644
--- a/chromium/content/browser/renderer_host/display_util.cc
+++ b/chromium/content/browser/renderer_host/display_util.cc
@@ -24,6 +24,7 @@ void DisplayUtil::DisplayToScreenInfo(ScreenInfo* screen_info,
screen_info->depth = display.color_depth();
screen_info->depth_per_component = display.depth_per_component();
screen_info->is_monochrome = display.is_monochrome();
+ screen_info->display_frequency = display.display_frequency();
screen_info->orientation_angle = display.RotationAsDegree();
#if defined(USE_AURA)
diff --git a/chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc b/chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc
index dd757b8ed0a..e02e585ca8b 100644
--- a/chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc
+++ b/chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc
@@ -30,6 +30,7 @@
#include "base/trace_event/trace_event.h"
#include "base/win/registry.h"
#include "content/browser/renderer_host/dwrite_font_file_util_win.h"
+#include "content/browser/renderer_host/dwrite_font_proxy_impl_win.h"
#include "content/browser/renderer_host/dwrite_font_uma_logging_win.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_features.h"
@@ -46,19 +47,17 @@ namespace {
const base::FilePath::CharType kProtobufFilename[] =
FILE_PATH_LITERAL("font_unique_name_table.pb");
-// The unresponsive renderer timeout is 30 seconds (kDefaultCommitTimeout). As a
-// starting point, let's set the max time for indexing fonts to half of that 15
-// seconds. We're starting the font lookup table construction earlier at startup
-// before a renderer requests this. Once we have more UMA data, we can look
-// into performance details and reducing this timeout. This timeout is meant to
-// cover pathological cases of font indexing where a Windows installation has an
-// unusually large collection of fonts. In practice, building the unique font
-// name table should not take longer than tens of milliseconds (~26 ms on a
-// developer machine, Windows 10, default fonts).
-const base::TimeDelta kFontIndexingTimeout = base::TimeDelta::FromSeconds(15);
+// Timeout after which font scanning and metadata extraction is stopped and the
+// local lookup table is cleared. Font scanning and lookup table construction is
+// only needed pre Windows 10. If the timeout is hit, no local font matching
+// will be performed on this particular pre Win 10 system.
+constexpr base::TimeDelta kFontIndexingTimeoutDefault =
+ base::TimeDelta::FromMinutes(5);
-const base::TimeDelta kIndexingSlowDownForTesting =
- base::TimeDelta::FromMilliseconds(1200);
+// In timeout test case, slow down indexing of one font file to this percentage
+// of the timeout value. Assuming that at least two fonts are indexed, the
+// timeout should be usually hit during indexing the second font.
+constexpr float kIndexingSlowDownForTestingPercentage = 0.75;
bool ExtractCaseFoldedLocalizedStrings(
IDWriteLocalizedStrings* dwrite_localized_strings,
@@ -91,21 +90,6 @@ bool ExtractCaseFoldedLocalizedStrings(
return true;
}
-// Used in the BuildFontUniqueNameTable() method to ensure that
-// |font_table_built_| is signaled whenever the function exits due to an error
-// or otherwise.
-class ScopedAutoSignal {
- public:
- ScopedAutoSignal(base::WaitableEvent* waitable_event)
- : waitable_event_(waitable_event) {}
- ~ScopedAutoSignal() { waitable_event_->Signal(); }
-
- private:
- base::WaitableEvent* const waitable_event_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedAutoSignal);
-};
-
bool EnsureCacheDirectory(base::FilePath cache_directory) {
// If the directory does not exist already, ensure that the parent directory
// exists, which is usually the User Data directory. If it exists, we can try
@@ -128,7 +112,8 @@ DWriteFontLookupTableBuilder::FontFileWithUniqueNames::
DWriteFontLookupTableBuilder::FontFileWithUniqueNames::FontFileWithUniqueNames(
DWriteFontLookupTableBuilder::FontFileWithUniqueNames&& other) = default;
-DWriteFontLookupTableBuilder::DWriteFontLookupTableBuilder() {
+DWriteFontLookupTableBuilder::DWriteFontLookupTableBuilder()
+ : font_indexing_timeout_(kFontIndexingTimeoutDefault) {
// In FontUniqueNameBrowserTest the DWriteFontLookupTableBuilder is
// instantiated to configure the cache directory for testing explicitly before
// GetContentClient() is available. Catch this case here. It is safe to not
@@ -145,7 +130,7 @@ DWriteFontLookupTableBuilder::~DWriteFontLookupTableBuilder() = default;
base::ReadOnlySharedMemoryRegion
DWriteFontLookupTableBuilder::DuplicateMemoryRegion() {
- DCHECK(EnsureFontUniqueNameTable());
+ DCHECK(FontUniqueNameTableReady());
return font_table_memory_.region.Duplicate();
}
@@ -170,6 +155,11 @@ void DWriteFontLookupTableBuilder::InitializeDirectWrite() {
// running an older version of DirectWrite (earlier than Win8.1).
factory.As<IDWriteFactory2>(&factory2_);
+ // QueryInterface for IDwriteFactory3, needed for MatchUniqueFont on Windows
+ // 10. May fail on older versions, in which case, unique font matching must be
+ // done through indexing system fonts using DWriteFontLookupTableBuilder.
+ factory.As<IDWriteFactory3>(&factory3_);
+
HRESULT hr = factory->GetSystemFontCollection(&collection_);
DCHECK(SUCCEEDED(hr));
@@ -228,6 +218,39 @@ void DWriteFontLookupTableBuilder::SetCachingEnabledForTesting(
caching_enabled_ = caching_enabled;
}
+bool DWriteFontLookupTableBuilder::HasDWriteUniqueFontLookups() {
+ InitializeDirectWrite();
+ return factory3_;
+}
+
+void DWriteFontLookupTableBuilder::OverrideDWriteVersionChecksForTesting() {
+ InitializeDirectWrite();
+ factory3_.Reset();
+}
+
+bool DWriteFontLookupTableBuilder::EnsureFontUniqueNameTableForTesting() {
+ TRACE_EVENT0("dwrite,fonts",
+ "DWriteFontLookupTableBuilder::EnsureFontUniqueNameTable");
+ DCHECK(base::FeatureList::IsEnabled(features::kFontSrcLocalMatching));
+ DCHECK(!HasDWriteUniqueFontLookups());
+ base::ScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
+ font_table_built_.Wait();
+ return IsFontUniqueNameTableValid();
+}
+
+base::TimeDelta DWriteFontLookupTableBuilder::IndexingTimeout() {
+ return font_indexing_timeout_;
+}
+
+void DWriteFontLookupTableBuilder::PostCallbacks() {
+ for (auto& pending_callback : pending_callbacks_) {
+ pending_callback.task_runner->PostTask(
+ FROM_HERE, base::BindOnce(std::move(pending_callback.mojo_callback),
+ DuplicateMemoryRegion()));
+ }
+ pending_callbacks_.clear();
+}
+
base::FilePath DWriteFontLookupTableBuilder::TableCacheFilePath() {
if (!EnsureCacheDirectory(cache_directory_))
return base::FilePath();
@@ -299,31 +322,60 @@ bool DWriteFontLookupTableBuilder::LoadFromFile() {
return true;
}
-bool DWriteFontLookupTableBuilder::EnsureFontUniqueNameTable() {
+DWriteFontLookupTableBuilder::CallbackOnTaskRunner::CallbackOnTaskRunner(
+ scoped_refptr<base::SequencedTaskRunner> runner,
+ blink::mojom::DWriteFontProxy::GetUniqueNameLookupTableCallback callback)
+ : task_runner(std::move(runner)), mojo_callback(std::move(callback)) {}
+
+DWriteFontLookupTableBuilder::CallbackOnTaskRunner::CallbackOnTaskRunner(
+ CallbackOnTaskRunner&& other) {
+ task_runner = std::move(other.task_runner);
+ mojo_callback = std::move(other.mojo_callback);
+ other.task_runner = nullptr;
+ other.mojo_callback =
+ blink::mojom::DWriteFontProxy::GetUniqueNameLookupTableCallback();
+}
+
+DWriteFontLookupTableBuilder::CallbackOnTaskRunner::~CallbackOnTaskRunner() =
+ default;
+
+void DWriteFontLookupTableBuilder::QueueShareMemoryRegionWhenReady(
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ blink::mojom::DWriteFontProxy::GetUniqueNameLookupTableCallback callback) {
TRACE_EVENT0("dwrite,fonts",
- "DWriteFontLookupTableBuilder::EnsureFontUniqueNameTable");
- DCHECK(base::FeatureList::IsEnabled(features::kFontSrcLocalMatching));
- base::ScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
- font_table_built_.Wait();
- return IsFontUniqueNameTableValid();
+ "DWriteFontLookupTableBuilder::QueueShareMemoryRegionWhenReady");
+ DCHECK(!HasDWriteUniqueFontLookups());
+ DCHECK(!font_table_built_.IsSignaled());
+ pending_callbacks_.emplace_back(std::move(task_runner), std::move(callback));
}
bool DWriteFontLookupTableBuilder::FontUniqueNameTableReady() {
+ TRACE_EVENT0("dwrite,fonts",
+ "DWriteFontLookupTableBuilder::FontUniqueNameTableReady");
+ DCHECK(base::FeatureList::IsEnabled(features::kFontSrcLocalMatching));
+ DCHECK(!HasDWriteUniqueFontLookups());
return font_table_built_.IsSignaled() && IsFontUniqueNameTableValid();
}
-void DWriteFontLookupTableBuilder::SchedulePrepareFontUniqueNameTable() {
+void DWriteFontLookupTableBuilder::
+ SchedulePrepareFontUniqueNameTableIfNeeded() {
DCHECK(base::FeatureList::IsEnabled(features::kFontSrcLocalMatching));
+ {
+ base::ScopedBlockingCall scoped_blocking_call(
+ FROM_HERE, base::BlockingType::MAY_BLOCK);
+ InitializeDirectWrite();
+ }
+
+ // Nothing to do if we have API to directly lookup local fonts by unique name.
+ if (HasDWriteUniqueFontLookups())
+ return;
+
start_time_table_ready_ = base::TimeTicks::Now();
- // TODO(https://crbug.com/931366): Downgrade the priority of this startup
- // task once the UpdatePriority() API for sequenced task runners is in
- // place. Then bump the priority when the renderer needs the table to be
- // ready.
scoped_refptr<base::SequencedTaskRunner> results_collection_task_runner =
base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
results_collection_task_runner->PostTask(
@@ -334,7 +386,8 @@ void DWriteFontLookupTableBuilder::SchedulePrepareFontUniqueNameTable() {
void DWriteFontLookupTableBuilder::PrepareFontUniqueNameTable() {
TRACE_EVENT0("dwrite,fonts",
- "DWriteFontLookupTableBuilder::BuildFontUniqueNameTable");
+ "DWriteFontLookupTableBuilder::PrepareFontUniqueNameTable");
+ DCHECK(!HasDWriteUniqueFontLookups());
// The table must only be built once.
DCHECK(!font_table_built_.IsSignaled());
@@ -355,16 +408,11 @@ void DWriteFontLookupTableBuilder::PrepareFontUniqueNameTable() {
UMA_HISTOGRAM_MEDIUM_TIMES("DirectWrite.Fonts.Proxy.LookupTableReadyTime",
duration);
font_table_built_.Signal();
+ PostCallbacks();
return;
}
}
- {
- base::ScopedBlockingCall scoped_blocking_call(
- FROM_HERE, base::BlockingType::MAY_BLOCK);
- InitializeDirectWrite();
- }
-
start_time_table_build_ = base::TimeTicks::Now();
font_unique_name_table_ = std::make_unique<blink::FontUniqueNameTable>();
@@ -382,14 +430,19 @@ void DWriteFontLookupTableBuilder::PrepareFontUniqueNameTable() {
}
for (UINT32 family_index = 0; family_index < outstanding_family_results_;
++family_index) {
+ // Specify base::ThreadPolicy::MUST_USE_FOREGROUND because in
+ // https://crbug.com/960263 we observed a priority inversion when running
+ // DWrite worker tasks in the background.
base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE,
- {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::ThreadPolicy::MUST_USE_FOREGROUND,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(
&DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily,
collection_, family_index, start_time_table_build_,
slow_down_mode_for_testing_,
- OptionalOrNullptr(hang_event_for_testing_)),
+ OptionalOrNullptr(hang_event_for_testing_), IndexingTimeout()),
base::BindOnce(&DWriteFontLookupTableBuilder::
AppendFamilyResultAndFinalizeIfNeeded,
base::Unretained(this)));
@@ -399,7 +452,7 @@ void DWriteFontLookupTableBuilder::PrepareFontUniqueNameTable() {
timeout_callback_.Reset(base::BindOnce(
&DWriteFontLookupTableBuilder::OnTimeout, base::Unretained(this)));
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, timeout_callback_.callback(), kFontIndexingTimeout);
+ FROM_HERE, timeout_callback_.callback(), IndexingTimeout());
}
// static
@@ -409,7 +462,8 @@ DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily(
uint32_t family_index,
base::TimeTicks start_time,
SlowDownMode slow_down_mode_for_testing,
- base::WaitableEvent* hang_event_for_testing) {
+ base::WaitableEvent* hang_event_for_testing,
+ base::TimeDelta indexing_timeout) {
TRACE_EVENT0("dwrite,fonts",
"DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily");
@@ -418,8 +472,9 @@ DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily(
DWriteFontLookupTableBuilder::FamilyResult family_result;
- if (base::TimeTicks::Now() - start_time > kFontIndexingTimeout)
+ if (base::TimeTicks::Now() - start_time > indexing_timeout) {
return family_result;
+ }
Microsoft::WRL::ComPtr<IDWriteFontFamily> family;
HRESULT hr = collection->GetFontFamily(family_index, &family);
@@ -429,6 +484,10 @@ DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily(
UINT32 font_count = family->GetFontCount();
for (UINT32 font_index = 0; font_index < font_count; ++font_index) {
+ if (base::TimeTicks::Now() - start_time > indexing_timeout) {
+ return DWriteFontLookupTableBuilder::FamilyResult();
+ }
+
Microsoft::WRL::ComPtr<IDWriteFont> font;
{
base::ScopedBlockingCall scoped_blocking_call(
@@ -499,11 +558,12 @@ DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily(
extract_names(DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME);
extract_names(DWRITE_INFORMATIONAL_STRING_FULL_NAME);
- if (UNLIKELY(slow_down_mode_for_testing == SlowDownMode::kDelayEachTask))
- base::PlatformThread::Sleep(kIndexingSlowDownForTesting);
- else if (UNLIKELY(slow_down_mode_for_testing ==
- SlowDownMode::kHangOneTask) &&
- family_index == 0) {
+ if (UNLIKELY(slow_down_mode_for_testing == SlowDownMode::kDelayEachTask)) {
+ base::PlatformThread::Sleep(indexing_timeout *
+ kIndexingSlowDownForTestingPercentage);
+ } else if (UNLIKELY(slow_down_mode_for_testing ==
+ SlowDownMode::kHangOneTask) &&
+ family_index == 0) {
base::ScopedAllowBaseSyncPrimitivesForTesting scoped_allow_sync_;
DCHECK(hang_event_for_testing);
hang_event_for_testing->Wait();
@@ -559,7 +619,6 @@ void DWriteFontLookupTableBuilder::FinalizeFontTable() {
TRACE_EVENT0("dwrite,fonts",
"DWriteFontLookupTableBuilder::FinalizeFontTable");
DCHECK(!font_table_built_.IsSignaled());
- ScopedAutoSignal auto_signal(&font_table_built_);
timeout_callback_.Cancel();
@@ -569,7 +628,7 @@ void DWriteFontLookupTableBuilder::FinalizeFontTable() {
std::move(font_unique_name_table_));
bool timed_out = false;
- if (base::TimeTicks::Now() - start_time_table_build_ > kFontIndexingTimeout) {
+ if (base::TimeTicks::Now() - start_time_table_build_ > IndexingTimeout()) {
font_unique_name_table->clear_fonts();
font_unique_name_table->clear_name_map();
timed_out = true;
@@ -589,15 +648,12 @@ void DWriteFontLookupTableBuilder::FinalizeFontTable() {
font_table_memory_ = base::ReadOnlySharedMemoryRegion::Create(
font_unique_name_table->ByteSizeLong());
- if (!IsFontUniqueNameTableValid()) {
- return;
- }
- if (!font_unique_name_table->SerializeToArray(
+ if (!IsFontUniqueNameTableValid() ||
+ !font_unique_name_table->SerializeToArray(
font_table_memory_.mapping.memory(),
font_table_memory_.mapping.size())) {
font_table_memory_ = base::MappedReadOnlyRegion();
- return;
}
if (caching_enabled_) {
@@ -606,6 +662,12 @@ void DWriteFontLookupTableBuilder::FinalizeFontTable() {
persist_succeeded);
}
+ font_table_built_.Signal();
+ PostCallbacks();
+
+ if (!IsFontUniqueNameTableValid())
+ return;
+
base::TimeDelta duration = base::TimeTicks::Now() - start_time_table_build_;
UMA_HISTOGRAM_MEDIUM_TIMES("DirectWrite.Fonts.Proxy.LookupTableBuildTime",
duration);
@@ -633,15 +695,18 @@ void DWriteFontLookupTableBuilder::OnTimeout() {
FinalizeFontTable();
}
-void DWriteFontLookupTableBuilder::SetSlowDownIndexingForTesting(
- SlowDownMode slow_down_mode) {
+void DWriteFontLookupTableBuilder::SetSlowDownIndexingForTestingWithTimeout(
+ SlowDownMode slow_down_mode,
+ base::TimeDelta new_timeout) {
slow_down_mode_for_testing_ = slow_down_mode;
+ font_indexing_timeout_ = new_timeout;
if (slow_down_mode == SlowDownMode::kHangOneTask)
hang_event_for_testing_.emplace();
}
void DWriteFontLookupTableBuilder::ResetLookupTableForTesting() {
slow_down_mode_for_testing_ = SlowDownMode::kNoSlowdown;
+ font_indexing_timeout_ = kFontIndexingTimeoutDefault;
font_table_memory_ = base::MappedReadOnlyRegion();
caching_enabled_ = true;
font_table_built_.Reset();
diff --git a/chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h b/chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h
index bbd066fb89a..0543a28c81b 100644
--- a/chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h
+++ b/chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h
@@ -7,6 +7,7 @@
#include <dwrite.h>
#include <dwrite_2.h>
+#include <dwrite_3.h>
#include <wrl.h>
#include <memory>
#include <string>
@@ -22,6 +23,7 @@
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/common/font_unique_name_lookup/font_unique_name_table.pb.h"
+#include "third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom.h"
namespace base {
template <typename T>
@@ -47,25 +49,34 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder {
// EnsureFontUniqueNameTable() must be checked before.
base::ReadOnlySharedMemoryRegion DuplicateMemoryRegion();
- // Wait for the internal WaitableEvent to be signaled if needed and return
- // true if the font unique name lookup table was successfully
- // constructed. Call only after ScheduleBuildFontUniqueNameTable().
- bool EnsureFontUniqueNameTable();
+ // Enqueue a request to get notified about the availability of the shared
+ // memory region holding the unique font lookup table.
+ // https://crbug.com/967316 shows that we do have a higher number of
+ // DWriteFontProxyImpl instances, potentially running on different
+ // TaskRunners. Capture each relevant task runner with a call to this method.
+ void QueueShareMemoryRegionWhenReady(
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ blink::mojom::DWriteFontProxy::GetUniqueNameLookupTableCallback callback);
// Returns whether the indexing has completed and the shared memory region is
// immediately ready without any sync operations.
bool FontUniqueNameTableReady();
- // Posts a task to load from cache or build (if cache not available) the
- // unique name table index, should only be called once at browser startup,
- // after that, use EnsureFontUniqueNameTable() and
- // DuplicatedMemoryRegion() to retrieve the lookup structure buffer.
- void SchedulePrepareFontUniqueNameTable();
+ // If needed, i.e. if we're on pre-Windows 10, posts a task to load from cache
+ // or build (if cache not available) the unique name table index, should only
+ // be called once at browser startup, after that,
+ // QueueShareMemoryRegionWhenReady() to trigger the mojo callbacks when the
+ // table is ready.
+ void SchedulePrepareFontUniqueNameTableIfNeeded();
enum class SlowDownMode { kDelayEachTask, kHangOneTask, kNoSlowdown };
- // Slow down each family indexing step for testing the internal timeout.
- void SetSlowDownIndexingForTesting(SlowDownMode slowdown_mode);
+ // Slow down each family indexing step for testing the internal timeout,
+ // either with a single hung task or by delaying each indexing step. At the
+ // same time, configure a new timeout value for testing, overriding the
+ // default timeout.
+ void SetSlowDownIndexingForTestingWithTimeout(SlowDownMode slowdown_mode,
+ base::TimeDelta new_timeout);
// Needed to trigger rebuilding the lookup table, when testing using
// slowed-down indexing. Otherwise, the test methods would use the already
@@ -91,6 +102,12 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder {
// repeated rebuilding of the font table lookup structure.
void SetCachingEnabledForTesting(bool caching_enabled);
+ // Disables DCHECKs that ensure DWriteFontLookupTableBuilder is only run pre
+ // Windows 10, used for testing only to allow running the tests on Windows 10.
+ void OverrideDWriteVersionChecksForTesting();
+
+ bool EnsureFontUniqueNameTableForTesting();
+
private:
friend class base::NoDestructor<DWriteFontLookupTableBuilder>;
@@ -130,7 +147,8 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder {
uint32_t family_index,
base::TimeTicks start_time,
SlowDownMode slow_down_mode,
- base::WaitableEvent* hang_event_for_testing);
+ base::WaitableEvent* hang_event_for_testing,
+ base::TimeDelta indexing_timeout);
// Callback from scheduled tasks to add the retrieved font names to the
// protobuf.
@@ -149,6 +167,15 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder {
base::FilePath TableCacheFilePath();
+ // Returns true if IDWriteFactory3 is available, which means that we can
+ // access IDWriteFontSet API which provides direct lookup by PostScript name
+ // and full font name, in which case we do not need to build this table.
+ bool HasDWriteUniqueFontLookups();
+
+ base::TimeDelta IndexingTimeout();
+
+ void PostCallbacks();
+
DWriteFontLookupTableBuilder();
~DWriteFontLookupTableBuilder();
@@ -159,8 +186,10 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder {
base::WaitableEvent font_table_built_;
bool direct_write_initialized_ = false;
+ base::TimeDelta font_indexing_timeout_;
Microsoft::WRL::ComPtr<IDWriteFontCollection> collection_;
Microsoft::WRL::ComPtr<IDWriteFactory2> factory2_;
+ Microsoft::WRL::ComPtr<IDWriteFactory3> factory3_;
SlowDownMode slow_down_mode_for_testing_ = SlowDownMode::kNoSlowdown;
uint32_t outstanding_family_results_ = 0;
base::TimeTicks start_time_table_ready_;
@@ -172,6 +201,19 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder {
base::Optional<base::WaitableEvent> hang_event_for_testing_;
base::CancelableOnceCallback<void()> timeout_callback_;
+ struct CallbackOnTaskRunner {
+ CallbackOnTaskRunner(
+ scoped_refptr<base::SequencedTaskRunner>,
+ blink::mojom::DWriteFontProxy::GetUniqueNameLookupTableCallback);
+ CallbackOnTaskRunner(CallbackOnTaskRunner&&);
+ ~CallbackOnTaskRunner();
+ scoped_refptr<base::SequencedTaskRunner> task_runner;
+ blink::mojom::DWriteFontProxy::GetUniqueNameLookupTableCallback
+ mojo_callback;
+ };
+
+ std::vector<CallbackOnTaskRunner> pending_callbacks_;
+
DISALLOW_COPY_AND_ASSIGN(DWriteFontLookupTableBuilder);
};
diff --git a/chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win_unittest.cc b/chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win_unittest.cc
index c0400fd0164..7cc8d19b47e 100644
--- a/chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win_unittest.cc
+++ b/chromium/content/browser/renderer_host/dwrite_font_lookup_table_builder_win_unittest.cc
@@ -32,16 +32,19 @@ constexpr FontExpectation kExpectedTestFonts[] = {{u8"CambriaMath", 1},
{u8"NSimSun", 1},
{u8"calibri-bolditalic", 0}};
+constexpr base::TimeDelta kTestingTimeout = base::TimeDelta::FromSeconds(10);
+
class DWriteFontLookupTableBuilderTest : public testing::Test {
public:
DWriteFontLookupTableBuilderTest()
: scoped_task_environment_(
- base::test::ScopedTaskEnvironment::ExecutionMode::ASYNC) {
+ base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::ASYNC) {
feature_list_.InitAndEnableFeature(features::kFontSrcLocalMatching);
}
void SetUp() override {
font_lookup_table_builder_ = DWriteFontLookupTableBuilder::GetInstance();
+ font_lookup_table_builder_->OverrideDWriteVersionChecksForTesting();
font_lookup_table_builder_->ResetLookupTableForTesting();
bool temp_dir_created = scoped_temp_dir_.CreateUniqueTempDir();
ASSERT_TRUE(temp_dir_created);
@@ -88,15 +91,16 @@ class DWriteFontLookupTableBuilderTimeoutTest
// without going through Mojo and running it on the DWRiteFontLookupTableBuilder
// class directly.
TEST_F(DWriteFontLookupTableBuilderTest, TestFindUniqueFontDirect) {
- font_lookup_table_builder_->SchedulePrepareFontUniqueNameTable();
- font_lookup_table_builder_->EnsureFontUniqueNameTable();
+ font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded();
+ font_lookup_table_builder_->EnsureFontUniqueNameTableForTesting();
TestMatchFonts();
}
TEST_P(DWriteFontLookupTableBuilderTimeoutTest, TestTimeout) {
- font_lookup_table_builder_->SetSlowDownIndexingForTesting(GetParam());
- font_lookup_table_builder_->SchedulePrepareFontUniqueNameTable();
- font_lookup_table_builder_->EnsureFontUniqueNameTable();
+ font_lookup_table_builder_->SetSlowDownIndexingForTestingWithTimeout(
+ GetParam(), kTestingTimeout);
+ font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded();
+ font_lookup_table_builder_->EnsureFontUniqueNameTableForTesting();
base::ReadOnlySharedMemoryRegion font_table_memory =
font_lookup_table_builder_->DuplicateMemoryRegion();
blink::FontTableMatcher font_table_matcher(font_table_memory.Map());
@@ -118,12 +122,13 @@ INSTANTIATE_TEST_SUITE_P(
DWriteFontLookupTableBuilder::SlowDownMode::kHangOneTask));
TEST_F(DWriteFontLookupTableBuilderTest, TestReadyEarly) {
- font_lookup_table_builder_->SetSlowDownIndexingForTesting(
- DWriteFontLookupTableBuilder::SlowDownMode::kHangOneTask);
- font_lookup_table_builder_->SchedulePrepareFontUniqueNameTable();
+ font_lookup_table_builder_->SetSlowDownIndexingForTestingWithTimeout(
+ DWriteFontLookupTableBuilder::SlowDownMode::kHangOneTask,
+ kTestingTimeout);
+ font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded();
ASSERT_FALSE(font_lookup_table_builder_->FontUniqueNameTableReady());
font_lookup_table_builder_->ResumeFromHangForTesting();
- font_lookup_table_builder_->EnsureFontUniqueNameTable();
+ font_lookup_table_builder_->EnsureFontUniqueNameTableForTesting();
ASSERT_TRUE(font_lookup_table_builder_->FontUniqueNameTableReady());
}
@@ -131,8 +136,8 @@ TEST_F(DWriteFontLookupTableBuilderTest, RepeatedScheduling) {
for (unsigned i = 0; i < 3; ++i) {
font_lookup_table_builder_->ResetLookupTableForTesting();
font_lookup_table_builder_->SetCachingEnabledForTesting(false);
- font_lookup_table_builder_->SchedulePrepareFontUniqueNameTable();
- font_lookup_table_builder_->EnsureFontUniqueNameTable();
+ font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded();
+ font_lookup_table_builder_->EnsureFontUniqueNameTableForTesting();
}
}
@@ -143,8 +148,9 @@ TEST_F(DWriteFontLookupTableBuilderTest, FontsHash) {
TEST_F(DWriteFontLookupTableBuilderTest, HandleCorruptCacheFile) {
// Cycle once to build cache file.
font_lookup_table_builder_->ResetLookupTableForTesting();
- font_lookup_table_builder_->SchedulePrepareFontUniqueNameTable();
- font_lookup_table_builder_->EnsureFontUniqueNameTable();
+ font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded();
+ ASSERT_TRUE(
+ font_lookup_table_builder_->EnsureFontUniqueNameTableForTesting());
// Truncate table for testing
base::FilePath cache_file_path = scoped_temp_dir_.GetPath().Append(
FILE_PATH_LITERAL("font_unique_name_table.pb"));
@@ -164,14 +170,16 @@ TEST_F(DWriteFontLookupTableBuilderTest, HandleCorruptCacheFile) {
// Reload the cache file.
font_lookup_table_builder_->ResetLookupTableForTesting();
- font_lookup_table_builder_->SchedulePrepareFontUniqueNameTable();
- ASSERT_TRUE(font_lookup_table_builder_->EnsureFontUniqueNameTable());
+ font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded();
+ ASSERT_TRUE(
+ font_lookup_table_builder_->EnsureFontUniqueNameTableForTesting());
TestMatchFonts();
// Ensure that the table is still valid even though persisting has failed due
// to the exclusive write lock on the file.
- ASSERT_TRUE(font_lookup_table_builder_->EnsureFontUniqueNameTable());
+ ASSERT_TRUE(
+ font_lookup_table_builder_->EnsureFontUniqueNameTableForTesting());
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc b/chromium/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc
index 5b64a37d9fc..2fae4d05a2e 100644
--- a/chromium/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc
+++ b/chromium/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc
@@ -503,14 +503,8 @@ void DWriteFontProxyImpl::GetUniqueNameLookupTable(
callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun(
std::move(callback), base::ReadOnlySharedMemoryRegion());
- // ScheduleBuildFontUniqueNameTable() is called early in browser startup
- // before EnsureFontUniqueNameTable() can be called. See
- // BrowserMainLoop::BrowserThreadsStarted().
- if (!DWriteFontLookupTableBuilder::GetInstance()->EnsureFontUniqueNameTable())
- return;
-
- std::move(callback).Run(
- DWriteFontLookupTableBuilder::GetInstance()->DuplicateMemoryRegion());
+ DWriteFontLookupTableBuilder::GetInstance()->QueueShareMemoryRegionWhenReady(
+ base::SequencedTaskRunnerHandle::Get(), std::move(callback));
}
void DWriteFontProxyImpl::InitializeDirectWrite() {
diff --git a/chromium/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc b/chromium/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc
index aa6f45f8329..c64885b9794 100644
--- a/chromium/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc
+++ b/chromium/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc
@@ -42,6 +42,16 @@ constexpr FontExpectation kExpectedTestFonts[] = {{u8"CambriaMath", 1},
{u8"NSimSun", 1},
{u8"calibri-bolditalic", 0}};
+// DirectWrite on Windows supports IDWriteFontSet API which allows for querying
+// by PostScript name and full font name directly. In the implementation of
+// DWriteFontProxy we check whether this API is available by checking for
+// whether IDWriteFactory3 is available. In order to validate in a unit test
+// whether this check works, compare it against the dwrite.dll major version -
+// versions starting from 10 have the required functionality.
+constexpr int kDWriteMajorVersionSupportingSingleLookups = 10;
+
+// Base test class that sets up the Mojo connection to DWriteFontProxy so that
+// tests can call its Mojo methods.
class DWriteFontProxyImplUnitTest : public testing::Test {
public:
DWriteFontProxyImplUnitTest()
@@ -51,34 +61,50 @@ class DWriteFontProxyImplUnitTest : public testing::Test {
return *dwrite_font_proxy_;
}
+ bool SupportsSingleLookups() {
+ blink::mojom::UniqueFontLookupMode lookup_mode;
+ dwrite_font_proxy().GetUniqueFontLookupMode(&lookup_mode);
+ return lookup_mode == blink::mojom::UniqueFontLookupMode::kSingleLookups;
+ }
+
base::test::ScopedTaskEnvironment scoped_task_environment_;
blink::mojom::DWriteFontProxyPtr dwrite_font_proxy_;
DWriteFontProxyImpl impl_;
mojo::Binding<blink::mojom::DWriteFontProxy> binding_;
};
-class DWriteFontProxyUniqueNameMatchingTest
- : public DWriteFontProxyImplUnitTest {
+// Derived class for tests that exercise font unique local matching mojo methods
+// of DWriteFontProxy. Needs a ScopedFeatureList to activate the feature as it
+// is currently behind a flag.
+class DWriteFontProxyLocalMatchingTest : public DWriteFontProxyImplUnitTest {
public:
- DWriteFontProxyUniqueNameMatchingTest() {
+ DWriteFontProxyLocalMatchingTest() {
feature_list_.InitAndEnableFeature(features::kFontSrcLocalMatching);
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+};
+
+// Derived class for tests that exercise the parts of the DWriteFontProxy Mojo
+// interface that deal with accessing the font lookup table created by
+// DWriteFontLookupTableBuilder. Initializes the DWriteFontLookupTableBuilder
+// and has a ScopedTempDir for testing persisting the lookup table to disk.
+class DWriteFontProxyTableMatchingTest
+ : public DWriteFontProxyLocalMatchingTest {
+ public:
+ DWriteFontProxyTableMatchingTest() {
DWriteFontLookupTableBuilder* table_builder_instance =
DWriteFontLookupTableBuilder::GetInstance();
DCHECK(scoped_temp_dir_.CreateUniqueTempDir());
+ table_builder_instance->OverrideDWriteVersionChecksForTesting();
table_builder_instance->SetCacheDirectoryForTesting(
scoped_temp_dir_.GetPath());
table_builder_instance->ResetLookupTableForTesting();
- table_builder_instance->SchedulePrepareFontUniqueNameTable();
- }
-
- bool SupportsSingleLookups() {
- blink::mojom::UniqueFontLookupMode lookup_mode;
- dwrite_font_proxy().GetUniqueFontLookupMode(&lookup_mode);
- return lookup_mode == blink::mojom::UniqueFontLookupMode::kSingleLookups;
+ table_builder_instance->SchedulePrepareFontUniqueNameTableIfNeeded();
}
private:
- base::test::ScopedFeatureList feature_list_;
base::ScopedTempDir scoped_temp_dir_;
};
@@ -247,7 +273,7 @@ void TestWhenLookupTableReady(
}
} // namespace
-TEST_F(DWriteFontProxyUniqueNameMatchingTest, TestFindUniqueFont) {
+TEST_F(DWriteFontProxyTableMatchingTest, TestFindUniqueFont) {
bool lookup_table_results_were_tested = false;
dwrite_font_proxy().GetUniqueNameLookupTable(base::BindOnce(
&TestWhenLookupTableReady, &lookup_table_results_were_tested));
@@ -255,7 +281,7 @@ TEST_F(DWriteFontProxyUniqueNameMatchingTest, TestFindUniqueFont) {
ASSERT_TRUE(lookup_table_results_were_tested);
}
-TEST_F(DWriteFontProxyUniqueNameMatchingTest, TestSingleLookup) {
+TEST_F(DWriteFontProxyLocalMatchingTest, TestSingleLookup) {
// Do not run this test on unsupported Windows versions.
if (!SupportsSingleLookups())
return;
@@ -274,7 +300,7 @@ TEST_F(DWriteFontProxyUniqueNameMatchingTest, TestSingleLookup) {
}
}
-TEST_F(DWriteFontProxyUniqueNameMatchingTest, TestSingleLookupUnavailable) {
+TEST_F(DWriteFontProxyLocalMatchingTest, TestSingleLookupUnavailable) {
// Do not run this test on unsupported Windows versions.
if (!SupportsSingleLookups())
return;
@@ -288,7 +314,7 @@ TEST_F(DWriteFontProxyUniqueNameMatchingTest, TestSingleLookupUnavailable) {
ASSERT_EQ(ttc_index, 0u);
}
-TEST_F(DWriteFontProxyUniqueNameMatchingTest, TestLookupMode) {
+TEST_F(DWriteFontProxyLocalMatchingTest, TestLookupMode) {
std::unique_ptr<FileVersionInfo> dwrite_version_info =
FileVersionInfo::CreateFileVersionInfo(
base::FilePath(FILE_PATH_LITERAL("DWrite.dll")));
@@ -300,7 +326,8 @@ TEST_F(DWriteFontProxyUniqueNameMatchingTest, TestLookupMode) {
std::stoi(dwrite_version.substr(0, dwrite_version.find(".")));
blink::mojom::UniqueFontLookupMode expected_lookup_mode;
- if (dwrite_major_version_number >= 10) {
+ if (dwrite_major_version_number >=
+ kDWriteMajorVersionSupportingSingleLookups) {
expected_lookup_mode = blink::mojom::UniqueFontLookupMode::kSingleLookups;
} else {
expected_lookup_mode = blink::mojom::UniqueFontLookupMode::kRetrieveTable;
diff --git a/chromium/content/browser/renderer_host/frame_connector_delegate.cc b/chromium/content/browser/renderer_host/frame_connector_delegate.cc
index c0d82a91709..88a2f7e4cf0 100644
--- a/chromium/content/browser/renderer_host/frame_connector_delegate.cc
+++ b/chromium/content/browser/renderer_host/frame_connector_delegate.cc
@@ -38,9 +38,6 @@ void FrameConnectorDelegate::SynchronizeVisualProperties(
if (!view_)
return;
-#if defined(USE_AURA)
- view_->SetFrameSinkId(frame_sink_id);
-#endif // defined(USE_AURA)
RenderWidgetHostImpl* render_widget_host = view_->host();
DCHECK(render_widget_host);
diff --git a/chromium/content/browser/renderer_host/frame_connector_delegate.h b/chromium/content/browser/renderer_host/frame_connector_delegate.h
index aaa39449c43..91b8859ca7e 100644
--- a/chromium/content/browser/renderer_host/frame_connector_delegate.h
+++ b/chromium/content/browser/renderer_host/frame_connector_delegate.h
@@ -17,10 +17,6 @@
#include "third_party/blink/public/common/frame/occlusion_state.h"
#include "ui/gfx/geometry/rect.h"
-#if defined(USE_AURA)
-#include "services/ws/public/mojom/window_tree.mojom.h"
-#endif
-
namespace blink {
class WebGestureEvent;
struct WebIntrinsicSizingInfo;
@@ -247,13 +243,6 @@ class CONTENT_EXPORT FrameConnectorDelegate {
// zoom-for-dsf is enabled, and in DIP if not.
virtual void SetScreenSpaceRect(const gfx::Rect& screen_space_rect);
-#if defined(USE_AURA)
- // Embeds a WindowTreeClient in the parent. This results in the parent
- // creating a window in the ui server so that this can render to the screen.
- virtual void EmbedRendererWindowTreeClientInParent(
- ws::mojom::WindowTreeClientPtr window_tree_client) {}
-#endif
-
// Called by RenderWidgetHostViewChildFrame when the child frame has updated
// its visual properties and its viz::LocalSurfaceId has changed.
virtual void DidUpdateVisualProperties(
diff --git a/chromium/content/browser/renderer_host/input/OWNERS b/chromium/content/browser/renderer_host/input/OWNERS
index e6d74ae941f..5b9322974ab 100644
--- a/chromium/content/browser/renderer_host/input/OWNERS
+++ b/chromium/content/browser/renderer_host/input/OWNERS
@@ -1,6 +1,7 @@
dtapuska@chromium.org
tdresser@chromium.org
nzolghadr@chromium.org
+bokan@chromium.org
# TEAM: input-dev@chromium.org
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 87c6b651a03..910af141dc3 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
@@ -266,7 +266,7 @@ IN_PROC_BROWSER_TEST_F(CompositorEventAckBrowserTest,
blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
gesture_scroll_begin.SetSourceDevice(blink::WebGestureDevice::kTouchscreen);
gesture_scroll_begin.data.scroll_begin.delta_hint_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0.f;
gesture_scroll_begin.data.scroll_begin.delta_y_hint = -5.f;
GetWidgetHost()->ForwardGestureEvent(gesture_scroll_begin);
diff --git a/chromium/content/browser/renderer_host/input/fling_browsertest.cc b/chromium/content/browser/renderer_host/input/fling_browsertest.cc
index fecba2dcf4b..a2c8eccce20 100644
--- a/chromium/content/browser/renderer_host/input/fling_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/fling_browsertest.cc
@@ -151,7 +151,7 @@ class BrowserSideFlingBrowserTest : public ContentBrowserTest {
blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
gesture_scroll_begin.SetSourceDevice(blink::WebGestureDevice::kTouchscreen);
gesture_scroll_begin.data.scroll_begin.delta_hint_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
gesture_scroll_begin.data.scroll_begin.delta_x_hint = fling_velocity.x();
gesture_scroll_begin.data.scroll_begin.delta_y_hint = fling_velocity.y();
const gfx::PointF scroll_location_in_widget(1, 1);
diff --git a/chromium/content/browser/renderer_host/input/fling_controller.cc b/chromium/content/browser/renderer_host/input/fling_controller.cc
index 545fac1c32d..0d6fda5817c 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller.cc
+++ b/chromium/content/browser/renderer_host/input/fling_controller.cc
@@ -333,11 +333,11 @@ void FlingController::GenerateAndSendGestureScrollEvents(
synthetic_gesture.event.data.scroll_update.delta_x = delta.x();
synthetic_gesture.event.data.scroll_update.delta_y = delta.y();
synthetic_gesture.event.data.scroll_update.inertial_phase =
- WebGestureEvent::kMomentumPhase;
+ WebGestureEvent::InertialPhaseState::kMomentum;
} else {
DCHECK_EQ(WebInputEvent::kGestureScrollEnd, type);
synthetic_gesture.event.data.scroll_end.inertial_phase =
- WebGestureEvent::kMomentumPhase;
+ WebGestureEvent::InertialPhaseState::kMomentum;
synthetic_gesture.event.data.scroll_end.generated_by_fling_controller =
true;
}
@@ -417,19 +417,14 @@ void FlingController::CancelCurrentFling() {
(last_fling_boost_event.GetType() == WebInputEvent::kGestureScrollBegin ||
last_fling_boost_event.GetType() ==
WebInputEvent::kGestureScrollUpdate)) {
- WebGestureEvent scroll_begin_event = last_fling_boost_event;
- scroll_begin_event.SetType(WebInputEvent::kGestureScrollBegin);
- bool is_update =
- last_fling_boost_event.GetType() == WebInputEvent::kGestureScrollUpdate;
- float delta_x_hint =
- is_update ? last_fling_boost_event.data.scroll_update.delta_x
- : last_fling_boost_event.data.scroll_begin.delta_x_hint;
- float delta_y_hint =
- is_update ? last_fling_boost_event.data.scroll_update.delta_y
- : 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;
-
+ WebGestureEvent scroll_begin_event;
+ if (last_fling_boost_event.GetType() ==
+ WebInputEvent::kGestureScrollUpdate) {
+ scroll_begin_event =
+ ui::ScrollBeginFromScrollUpdate(last_fling_boost_event);
+ } else {
+ scroll_begin_event = last_fling_boost_event;
+ }
event_sender_client_->SendGeneratedGestureScrollEvents(
GestureEventWithLatencyInfo(
scroll_begin_event,
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 a3d2d8d757b..1405a5adcba 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc
@@ -110,9 +110,9 @@ class FlingControllerTest : public FlingControllerEventSenderClient,
scroll_update.data.scroll_update.velocity_x = delta.x();
scroll_update.data.scroll_update.velocity_y = delta.y();
scroll_update.data.scroll_update.inertial_phase =
- WebGestureEvent::kNonMomentumPhase;
+ WebGestureEvent::InertialPhaseState::kNonMomentum;
scroll_update.data.scroll_update.delta_units =
- WebGestureEvent::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
GestureEventWithLatencyInfo scroll_update_with_latency(scroll_update);
fling_controller_->ObserveAndMaybeConsumeGestureEvent(
@@ -257,7 +257,7 @@ TEST_P(FlingControllerTest, ControllerHandlesTouchscreenGestureFling) {
AdvanceTime();
ProgressFling(NowTicks());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
- EXPECT_EQ(WebGestureEvent::kMomentumPhase,
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum,
last_sent_gesture_.data.scroll_update.inertial_phase);
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
@@ -316,7 +316,7 @@ TEST_P(FlingControllerTest, ControllerSendsGSEWhenTouchscreenFlingIsOver) {
while (FlingInProgress()) {
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate,
last_sent_gesture_.GetType());
- EXPECT_EQ(WebGestureEvent::kMomentumPhase,
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum,
last_sent_gesture_.data.scroll_update.inertial_phase);
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
AdvanceTime();
@@ -361,7 +361,7 @@ TEST_P(FlingControllerTest, EarlyTouchscreenFlingCancelationOnFlingStop) {
AdvanceTime();
ProgressFling(NowTicks());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
- EXPECT_EQ(WebGestureEvent::kMomentumPhase,
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum,
last_sent_gesture_.data.scroll_update.inertial_phase);
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
@@ -405,7 +405,7 @@ TEST_P(FlingControllerTest, GestureFlingNotCancelledBySmallTimeDelta) {
EXPECT_EQ(blink::WebGestureDevice::kTouchscreen,
last_sent_gesture_.SourceDevice());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
- EXPECT_EQ(WebGestureEvent::kMomentumPhase,
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum,
last_sent_gesture_.data.scroll_update.inertial_phase);
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
}
@@ -430,7 +430,7 @@ TEST_P(FlingControllerTest, GestureFlingWithNegativeTimeDelta) {
EXPECT_EQ(blink::WebGestureDevice::kTouchscreen,
last_sent_gesture_.SourceDevice());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
- EXPECT_EQ(WebGestureEvent::kMomentumPhase,
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum,
last_sent_gesture_.data.scroll_update.inertial_phase);
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
}
@@ -529,7 +529,7 @@ TEST_P(FlingControllerTest, ControllerBoostsTouchscreenFling) {
AdvanceTime();
ProgressFling(NowTicks());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
- EXPECT_EQ(WebGestureEvent::kMomentumPhase,
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum,
last_sent_gesture_.data.scroll_update.inertial_phase);
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
@@ -570,7 +570,7 @@ TEST_P(FlingControllerTest, MiddleClickAutoScrollFling) {
AdvanceTime();
ProgressFling(NowTicks());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
- EXPECT_EQ(WebGestureEvent::kMomentumPhase,
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum,
last_sent_gesture_.data.scroll_update.inertial_phase);
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
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 3d6f61c5414..929ed1c5482 100644
--- a/chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc
@@ -135,14 +135,14 @@ class TracingRenderWidgetHostFactory : public RenderWidgetHostFactory {
RenderWidgetHostFactory::UnregisterFactory();
}
- RenderWidgetHostImpl* CreateRenderWidgetHost(
+ std::unique_ptr<RenderWidgetHostImpl> CreateRenderWidgetHost(
RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int32_t routing_id,
mojom::WidgetPtr widget_interface,
bool hidden) override {
- return new TracingRenderWidgetHost(delegate, process, routing_id,
- std::move(widget_interface), hidden);
+ return std::make_unique<TracingRenderWidgetHost>(
+ delegate, process, routing_id, std::move(widget_interface), hidden);
}
private:
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 d0c25d82e4c..05e2d2bfb3c 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
@@ -168,14 +168,15 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
if (event_sent_for_gesture_ack_->event.momentum_phase !=
blink::WebMouseWheelEvent::kPhaseNone) {
scroll_update.data.scroll_update.inertial_phase =
- WebGestureEvent::kMomentumPhase;
+ WebGestureEvent::InertialPhaseState::kMomentum;
} else if (event_sent_for_gesture_ack_->event.phase !=
blink::WebMouseWheelEvent::kPhaseNone) {
scroll_update.data.scroll_update.inertial_phase =
- WebGestureEvent::kNonMomentumPhase;
+ WebGestureEvent::InertialPhaseState::kNonMomentum;
}
if (event_sent_for_gesture_ack_->event.scroll_by_page) {
- scroll_update.data.scroll_update.delta_units = WebGestureEvent::kPage;
+ scroll_update.data.scroll_update.delta_units =
+ ui::input_types::ScrollGranularity::kScrollByPage;
// Turn page scrolls into a *single* page scroll because
// the magnitude the number of ticks is lost when coalescing.
@@ -188,8 +189,8 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
} else {
scroll_update.data.scroll_update.delta_units =
event_sent_for_gesture_ack_->event.has_precise_scrolling_deltas
- ? WebGestureEvent::kPrecisePixels
- : WebGestureEvent::kPixels;
+ ? ui::input_types::ScrollGranularity::kScrollByPrecisePixel
+ : ui::input_types::ScrollGranularity::kScrollByPixel;
if (event_sent_for_gesture_ack_->event.rails_mode ==
WebInputEvent::kRailsModeVertical)
@@ -316,7 +317,7 @@ void MouseWheelEventQueue::SendScrollEnd(WebGestureEvent update_event,
// blink::WebMouseWheelEvent::kPhaseEnded are generated by the fling
// controller to terminate touchpad flings.
if (scroll_end.data.scroll_end.inertial_phase ==
- WebGestureEvent::kMomentumPhase &&
+ WebGestureEvent::InertialPhaseState::kMomentum &&
synthetic) {
scroll_end.data.scroll_end.generated_by_fling_controller = true;
}
@@ -330,18 +331,9 @@ void MouseWheelEventQueue::SendScrollBegin(
bool synthetic) {
DCHECK(!client_->IsWheelScrollInProgress());
- WebGestureEvent scroll_begin(gesture_update);
- scroll_begin.SetType(WebInputEvent::kGestureScrollBegin);
+ WebGestureEvent scroll_begin =
+ ui::ScrollBeginFromScrollUpdate(gesture_update);
scroll_begin.data.scroll_begin.synthetic = synthetic;
- scroll_begin.data.scroll_begin.inertial_phase =
- gesture_update.data.scroll_update.inertial_phase;
- scroll_begin.data.scroll_begin.delta_x_hint =
- gesture_update.data.scroll_update.delta_x;
- scroll_begin.data.scroll_begin.delta_y_hint =
- gesture_update.data.scroll_update.delta_y;
- scroll_begin.data.scroll_begin.target_viewport = false;
- scroll_begin.data.scroll_begin.delta_hint_units =
- gesture_update.data.scroll_update.delta_units;
client_->ForwardGestureEventWithLatencyInfo(
scroll_begin, ui::LatencyInfo(ui::SourceEventType::WHEEL));
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 408f7ce1b83..38cdfa1f62d 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
@@ -42,34 +42,34 @@ const float kWheelScrollGlobalY = 72;
EXPECT_EQ(kWheelScrollGlobalY, event->PositionInScreen().y); \
EXPECT_EQ(scroll_units, event->data.scroll_begin.delta_hint_units);
-#define EXPECT_GESTURE_SCROLL_BEGIN(event) \
- EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
- EXPECT_FALSE(event->data.scroll_begin.synthetic); \
- EXPECT_EQ(WebGestureEvent::kUnknownMomentumPhase, \
+#define EXPECT_GESTURE_SCROLL_BEGIN(event) \
+ EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
+ EXPECT_FALSE(event->data.scroll_begin.synthetic); \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kUnknownMomentum, \
event->data.scroll_begin.inertial_phase);
-#define EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(event) \
- EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
- EXPECT_FALSE(event->data.scroll_begin.synthetic); \
- EXPECT_EQ(WebGestureEvent::kNonMomentumPhase, \
+#define EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(event) \
+ EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
+ EXPECT_FALSE(event->data.scroll_begin.synthetic); \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kNonMomentum, \
event->data.scroll_begin.inertial_phase);
-#define EXPECT_SYNTHETIC_GESTURE_SCROLL_BEGIN(event) \
- EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
- EXPECT_TRUE(event->data.scroll_begin.synthetic); \
- EXPECT_EQ(WebGestureEvent::kNonMomentumPhase, \
+#define EXPECT_SYNTHETIC_GESTURE_SCROLL_BEGIN(event) \
+ EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
+ EXPECT_TRUE(event->data.scroll_begin.synthetic); \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kNonMomentum, \
event->data.scroll_begin.inertial_phase);
-#define EXPECT_INERTIAL_GESTURE_SCROLL_BEGIN(event) \
- EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
- EXPECT_FALSE(event->data.scroll_begin.synthetic); \
- EXPECT_EQ(WebGestureEvent::kMomentumPhase, \
+#define EXPECT_INERTIAL_GESTURE_SCROLL_BEGIN(event) \
+ EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
+ EXPECT_FALSE(event->data.scroll_begin.synthetic); \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum, \
event->data.scroll_begin.inertial_phase);
#define EXPECT_SYNTHETIC_INERTIAL_GESTURE_SCROLL_BEGIN(event) \
EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
EXPECT_TRUE(event->data.scroll_begin.synthetic); \
- EXPECT_EQ(WebGestureEvent::kMomentumPhase, \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum, \
event->data.scroll_begin.inertial_phase);
#define EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event) \
@@ -80,19 +80,19 @@ const float kWheelScrollGlobalY = 72;
EXPECT_EQ(kWheelScrollGlobalX, event->PositionInScreen().x); \
EXPECT_EQ(kWheelScrollGlobalY, event->PositionInScreen().y);
-#define EXPECT_GESTURE_SCROLL_UPDATE(event) \
- EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event); \
- EXPECT_EQ(WebGestureEvent::kUnknownMomentumPhase, \
+#define EXPECT_GESTURE_SCROLL_UPDATE(event) \
+ EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event); \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kUnknownMomentum, \
event->data.scroll_update.inertial_phase);
-#define EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(event) \
- EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event); \
- EXPECT_EQ(WebGestureEvent::kNonMomentumPhase, \
+#define EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(event) \
+ EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event); \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kNonMomentum, \
event->data.scroll_update.inertial_phase);
-#define EXPECT_INERTIAL_GESTURE_SCROLL_UPDATE(event) \
- EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event); \
- EXPECT_EQ(WebGestureEvent::kMomentumPhase, \
+#define EXPECT_INERTIAL_GESTURE_SCROLL_UPDATE(event) \
+ EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event); \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum, \
event->data.scroll_update.inertial_phase);
#define EXPECT_GESTURE_SCROLL_END_IMPL(event) \
@@ -103,35 +103,35 @@ const float kWheelScrollGlobalY = 72;
EXPECT_EQ(kWheelScrollGlobalX, event->PositionInScreen().x); \
EXPECT_EQ(kWheelScrollGlobalY, event->PositionInScreen().y);
-#define EXPECT_GESTURE_SCROLL_END(event) \
- EXPECT_GESTURE_SCROLL_END_IMPL(event); \
- EXPECT_FALSE(event->data.scroll_end.synthetic); \
- EXPECT_EQ(WebGestureEvent::kUnknownMomentumPhase, \
+#define EXPECT_GESTURE_SCROLL_END(event) \
+ EXPECT_GESTURE_SCROLL_END_IMPL(event); \
+ EXPECT_FALSE(event->data.scroll_end.synthetic); \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kUnknownMomentum, \
event->data.scroll_end.inertial_phase);
-#define EXPECT_GESTURE_SCROLL_END_WITH_PHASE(event) \
- EXPECT_GESTURE_SCROLL_END_IMPL(event); \
- EXPECT_FALSE(event->data.scroll_end.synthetic); \
- EXPECT_EQ(WebGestureEvent::kNonMomentumPhase, \
+#define EXPECT_GESTURE_SCROLL_END_WITH_PHASE(event) \
+ EXPECT_GESTURE_SCROLL_END_IMPL(event); \
+ EXPECT_FALSE(event->data.scroll_end.synthetic); \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kNonMomentum, \
event->data.scroll_end.inertial_phase);
-#define EXPECT_SYNTHETIC_GESTURE_SCROLL_END(event) \
- EXPECT_GESTURE_SCROLL_END_IMPL(event); \
- EXPECT_TRUE(event->data.scroll_end.synthetic); \
- EXPECT_EQ(WebGestureEvent::kNonMomentumPhase, \
+#define EXPECT_SYNTHETIC_GESTURE_SCROLL_END(event) \
+ EXPECT_GESTURE_SCROLL_END_IMPL(event); \
+ EXPECT_TRUE(event->data.scroll_end.synthetic); \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kNonMomentum, \
event->data.scroll_end.inertial_phase);
-#define EXPECT_INERTIAL_GESTURE_SCROLL_END(event) \
- EXPECT_GESTURE_SCROLL_END_IMPL(event); \
- EXPECT_FALSE(event->data.scroll_end.synthetic); \
- EXPECT_EQ(WebGestureEvent::kMomentumPhase, \
+#define EXPECT_INERTIAL_GESTURE_SCROLL_END(event) \
+ EXPECT_GESTURE_SCROLL_END_IMPL(event); \
+ EXPECT_FALSE(event->data.scroll_end.synthetic); \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum, \
event->data.scroll_end.inertial_phase);
#if defined(CHROME_OS)
#define EXPECT_SYNTHETIC_INERTIAL_GESTURE_SCROLL_END(event) \
EXPECT_GESTURE_SCROLL_END_IMPL(event); \
EXPECT_TRUE(event->data.scroll_end.synthetic); \
- EXPECT_EQ(WebGestureEvent::kMomentumPhase, \
+ EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum, \
event->data.scroll_end.inertial_phase); \
EXPECT_TRUE(event->data.scroll_end.generated_by_fling_controller);
#endif
@@ -277,9 +277,10 @@ class MouseWheelEventQueueTest : public testing::Test,
}
void GestureSendingTest(bool high_precision) {
- const WebGestureEvent::ScrollUnits scroll_units =
- high_precision ? WebGestureEvent::kPrecisePixels
- : WebGestureEvent::kPixels;
+ const ui::input_types::ScrollGranularity scroll_units =
+ high_precision
+ ? ui::input_types::ScrollGranularity::kScrollByPrecisePixel
+ : ui::input_types::ScrollGranularity::kScrollByPixel;
SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
kWheelScrollGlobalY, 1, 1, 0, high_precision,
WebMouseWheelEvent::kPhaseBegan,
@@ -313,9 +314,10 @@ class MouseWheelEventQueueTest : public testing::Test,
}
void PhaseGestureSendingTest(bool high_precision) {
- const WebGestureEvent::ScrollUnits scroll_units =
- high_precision ? WebGestureEvent::kPrecisePixels
- : WebGestureEvent::kPixels;
+ const ui::input_types::ScrollGranularity scroll_units =
+ high_precision
+ ? ui::input_types::ScrollGranularity::kScrollByPrecisePixel
+ : ui::input_types::ScrollGranularity::kScrollByPixel;
SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
kWheelScrollGlobalY, 1, 1, 0, high_precision,
@@ -441,8 +443,8 @@ TEST_F(MouseWheelEventQueueTest,
// scroll_end.data.scroll_end.generated_by_fling_controller.
#if defined(CHROME_OS)
TEST_F(MouseWheelEventQueueTest, WheelEndWithMomentumPhaseEndedInformation) {
- const WebGestureEvent::ScrollUnits scroll_units =
- WebGestureEvent::kPrecisePixels;
+ const ui::input_types::ScrollGranularity scroll_units =
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
kWheelScrollGlobalY, 1, 1, 0, true /* high_precision */,
WebMouseWheelEvent::kPhaseBegan,
@@ -471,7 +473,8 @@ TEST_F(MouseWheelEventQueueTest, WheelEndWithMomentumPhaseEndedInformation) {
#endif // defined(CHROME_OS)
TEST_F(MouseWheelEventQueueTest, GestureSendingInterrupted) {
- const WebGestureEvent::ScrollUnits scroll_units = WebGestureEvent::kPixels;
+ const ui::input_types::ScrollGranularity scroll_units =
+ ui::input_types::ScrollGranularity::kScrollByPixel;
SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
kWheelScrollGlobalY, 1, 1, 0, false,
WebMouseWheelEvent::kPhaseBegan,
@@ -551,7 +554,8 @@ TEST_F(MouseWheelEventQueueTest, GestureSendingInterrupted) {
}
TEST_F(MouseWheelEventQueueTest, GestureRailScrolling) {
- const WebGestureEvent::ScrollUnits scroll_units = WebGestureEvent::kPixels;
+ const ui::input_types::ScrollGranularity scroll_units =
+ ui::input_types::ScrollGranularity::kScrollByPixel;
SendMouseWheel(
kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX, kWheelScrollGlobalY, 1,
1, 0, false, WebMouseWheelEvent::kPhaseBegan,
@@ -600,7 +604,8 @@ TEST_F(MouseWheelEventQueueTest, GestureRailScrolling) {
}
TEST_F(MouseWheelEventQueueTest, WheelScrollLatching) {
- const WebGestureEvent::ScrollUnits scroll_units = WebGestureEvent::kPixels;
+ const ui::input_types::ScrollGranularity scroll_units =
+ ui::input_types::ScrollGranularity::kScrollByPixel;
SendMouseWheel(
kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX, kWheelScrollGlobalY, 1,
1, 0, false, WebMouseWheelEvent::kPhaseBegan,
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 d615b825c10..42bdfd8ce8a 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
@@ -692,6 +692,64 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToScrollHistograms) {
}
}
+TEST_F(RenderWidgetHostLatencyTrackerTest, ScrollbarEndToEndHistograms) {
+ // For all combinations of ScrollBegin/ScrollUpdate main/impl rendering,
+ // ensure that the LatencyTracker logs the correct set of histograms.
+ const GURL url(kUrl);
+ contents()->NavigateAndCommit(url);
+ ResetHistograms();
+ {
+ auto mouse_move =
+ SyntheticWebMouseEventBuilder::Build(blink::WebMouseEvent::kMouseMove);
+ base::TimeTicks now = base::TimeTicks::Now();
+
+ const ui::LatencyComponentType scroll_components[] = {
+ ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
+ ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
+ };
+ for (ui::LatencyComponentType component : scroll_components) {
+ const bool on_main[] = {true, false};
+ for (bool on_main_thread : on_main) {
+ ui::LatencyInfo scrollbar_latency(ui::SourceEventType::SCROLLBAR);
+ AddFakeComponentsWithTimeStamp(*tracker(), &scrollbar_latency, now);
+ scrollbar_latency.AddLatencyNumberWithTimestamp(component, now, 1);
+ AddRenderingScheduledComponent(&scrollbar_latency, on_main_thread, now);
+ tracker()->OnInputEvent(mouse_move, &scrollbar_latency);
+ EXPECT_TRUE(scrollbar_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
+ EXPECT_TRUE(scrollbar_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, nullptr));
+ tracker()->OnInputEventAck(mouse_move, &scrollbar_latency,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ viz_tracker()->OnGpuSwapBuffersCompleted(scrollbar_latency);
+ }
+ }
+ }
+
+ const std::string scroll_types[] = {"ScrollBegin", "ScrollUpdate"};
+ for (const std::string& scroll_type : scroll_types) {
+ // Each histogram that doesn't take main/impl into account should have
+ // two samples (one each for main and impl).
+ const std::string histogram_prefix = "Event.Latency." + scroll_type;
+ histogram_tester().ExpectUniqueSample(
+ histogram_prefix + ".Scrollbar.TimeToScrollUpdateSwapBegin4", 0, 2);
+ histogram_tester().ExpectUniqueSample(
+ histogram_prefix + ".Scrollbar.RendererSwapToBrowserNotified2", 0, 2);
+ histogram_tester().ExpectUniqueSample(
+ histogram_prefix + ".Scrollbar.BrowserNotifiedToBeforeGpuSwap2", 0, 2);
+ histogram_tester().ExpectUniqueSample(
+ histogram_prefix + ".Scrollbar.GpuSwap2", 0, 2);
+ const std::string main_or_impl[] = {"Main", "Impl"};
+ for (const std::string& thread : main_or_impl) {
+ histogram_tester().ExpectUniqueSample(
+ histogram_prefix + ".Scrollbar.TimeToHandled2_" + thread, 0, 1);
+ histogram_tester().ExpectUniqueSample(
+ histogram_prefix + ".Scrollbar.HandledToRendererSwap2_" + thread, 0,
+ 1);
+ }
+ }
+}
+
TEST_F(RenderWidgetHostLatencyTrackerTest,
LatencyTerminatedOnAckIfRenderingNotScheduled) {
{
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 b40589c4f28..1f98c08075c 100644
--- a/chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc
@@ -8,6 +8,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
#include "cc/base/switches.h"
#include "content/browser/renderer_host/input/synthetic_gesture.h"
#include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
@@ -25,6 +26,7 @@
#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 "ui/base/ui_base_features.h"
namespace {
@@ -119,7 +121,7 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest {
SyntheticWebGestureEventBuilder::BuildScrollBegin(
distance.x(), -distance.y(), blink::WebGestureDevice::kTouchpad, 1);
event.data.scroll_begin.delta_hint_units =
- blink::WebGestureEvent::ScrollUnits::kPixels;
+ ui::input_types::ScrollGranularity::kScrollByPixel;
GetWidgetHost()->ForwardGestureEvent(event);
const uint32_t kNumWheelScrolls = 2;
@@ -139,7 +141,7 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest {
distance.x(), -distance.y(), 0,
blink::WebGestureDevice::kTouchpad);
event2.data.scroll_update.delta_units =
- blink::WebGestureEvent::ScrollUnits::kPixels;
+ ui::input_types::ScrollGranularity::kScrollByPixel;
GetWidgetHost()->ForwardGestureEvent(event2);
while (visual_state_callback_count_ <= i) {
@@ -172,6 +174,102 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest {
}
}
+ void RunScrollbarButtonLatencyTest() {
+ // Click on the forward scrollbar button to induce a compositor thread
+ // scrollbar scroll.
+ blink::WebFloatPoint scrollbar_forward_button(795, 595);
+ blink::WebMouseEvent mouse_event = SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseDown, scrollbar_forward_button.x,
+ scrollbar_forward_button.y, 0);
+ mouse_event.button = blink::WebMouseEvent::Button::kLeft;
+ mouse_event.SetTimeStamp(base::TimeTicks::Now());
+ GetWidgetHost()->ForwardMouseEvent(mouse_event);
+
+ mouse_event.SetType(blink::WebInputEvent::kMouseUp);
+ GetWidgetHost()->ForwardMouseEvent(mouse_event);
+
+ RunUntilInputProcessed(GetWidgetHost());
+
+ FetchHistogramsFromChildProcesses();
+ VerifyRecordedSamplesForHistogram(
+ 1, "Event.Latency.ScrollBegin.Scrollbar.TimeToScrollUpdateSwapBegin4");
+ VerifyRecordedSamplesForHistogram(
+ 1,
+ "Event.Latency.ScrollBegin.Scrollbar.RendererSwapToBrowserNotified2");
+ VerifyRecordedSamplesForHistogram(
+ 1,
+ "Event.Latency.ScrollBegin.Scrollbar.BrowserNotifiedToBeforeGpuSwap2");
+ VerifyRecordedSamplesForHistogram(
+ 1, "Event.Latency.ScrollBegin.Scrollbar.GpuSwap2");
+ VerifyRecordedSamplesForHistogram(
+ 1, "Event.Latency.ScrollBegin.Scrollbar.TimeToScrollUpdateSwapBegin4");
+ std::string thread_name =
+ DoesScrollbarScrollOnMainThread() ? "Main" : "Impl";
+ VerifyRecordedSamplesForHistogram(
+ 1, "Event.Latency.ScrollBegin.Scrollbar.TimeToHandled_" + thread_name);
+ VerifyRecordedSamplesForHistogram(
+ 1, "Event.Latency.ScrollBegin.Scrollbar.HandledToRendererSwap2_" +
+ thread_name);
+ }
+
+ void RunScrollbarThumbDragLatencyTest() {
+ // Click on the scrollbar thumb and drag it twice to induce a compositor
+ // thread scrollbar ScrollBegin and ScrollUpdate.
+ blink::WebFloatPoint scrollbar_thumb(795, 30);
+ blink::WebMouseEvent mouse_down = SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseDown, scrollbar_thumb.x, scrollbar_thumb.y,
+ 0);
+ mouse_down.button = blink::WebMouseEvent::Button::kLeft;
+ mouse_down.SetTimeStamp(base::TimeTicks::Now());
+ GetWidgetHost()->ForwardMouseEvent(mouse_down);
+
+ blink::WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseMove, scrollbar_thumb.x,
+ scrollbar_thumb.y + 10, 0);
+ mouse_move.button = blink::WebMouseEvent::Button::kLeft;
+ mouse_move.SetTimeStamp(base::TimeTicks::Now());
+ GetWidgetHost()->ForwardMouseEvent(mouse_move);
+ mouse_move.SetPositionInWidget(scrollbar_thumb.x, scrollbar_thumb.y + 20);
+ mouse_move.SetPositionInScreen(scrollbar_thumb.x, scrollbar_thumb.y + 20);
+ GetWidgetHost()->ForwardMouseEvent(mouse_move);
+
+ blink::WebMouseEvent mouse_up = SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseUp, scrollbar_thumb.x,
+ scrollbar_thumb.y + 20, 0);
+ mouse_up.button = blink::WebMouseEvent::Button::kLeft;
+ mouse_up.SetTimeStamp(base::TimeTicks::Now());
+ GetWidgetHost()->ForwardMouseEvent(mouse_up);
+
+ RunUntilInputProcessed(GetWidgetHost());
+
+ FetchHistogramsFromChildProcesses();
+ const std::string scroll_types[] = {"ScrollBegin", "ScrollUpdate"};
+ for (const std::string& scroll_type : scroll_types) {
+ VerifyRecordedSamplesForHistogram(
+ 1, "Event.Latency." + scroll_type +
+ ".Scrollbar.TimeToScrollUpdateSwapBegin4");
+ VerifyRecordedSamplesForHistogram(
+ 1, "Event.Latency." + scroll_type +
+ ".Scrollbar.RendererSwapToBrowserNotified2");
+ VerifyRecordedSamplesForHistogram(
+ 1, "Event.Latency." + scroll_type +
+ ".Scrollbar.BrowserNotifiedToBeforeGpuSwap2");
+ VerifyRecordedSamplesForHistogram(
+ 1, "Event.Latency." + scroll_type + ".Scrollbar.GpuSwap2");
+ VerifyRecordedSamplesForHistogram(
+ 1, "Event.Latency." + scroll_type +
+ ".Scrollbar.TimeToScrollUpdateSwapBegin4");
+ std::string thread_name =
+ DoesScrollbarScrollOnMainThread() ? "Main" : "Impl";
+ VerifyRecordedSamplesForHistogram(1, "Event.Latency." + scroll_type +
+ ".Scrollbar.TimeToHandled_" +
+ thread_name);
+ VerifyRecordedSamplesForHistogram(
+ 1, "Event.Latency." + scroll_type +
+ ".Scrollbar.HandledToRendererSwap2_" + thread_name);
+ }
+ }
+
// Returns true if the given histogram has recorded the expected number of
// samples.
bool VerifyRecordedSamplesForHistogram(
@@ -181,6 +279,8 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest {
histogram_tester_.GetAllSamples(histogram_name).size();
}
+ virtual bool DoesScrollbarScrollOnMainThread() const { return true; }
+
std::unique_ptr<base::RunLoop> run_loop_;
bool disable_threaded_scrolling_ = false;
@@ -255,4 +355,45 @@ IN_PROC_BROWSER_TEST_F(ScrollLatencyBrowserTest,
0, "Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin4"));
}
+IN_PROC_BROWSER_TEST_F(ScrollLatencyBrowserTest, ScrollbarButtonLatency) {
+ LoadURL();
+
+ RunScrollbarButtonLatencyTest();
+}
+
+IN_PROC_BROWSER_TEST_F(ScrollLatencyBrowserTest, ScrollbarThumbDragLatency) {
+ LoadURL();
+
+ RunScrollbarThumbDragLatencyTest();
+}
+
+class ScrollLatencyCompositedScrollbarBrowserTest
+ : public ScrollLatencyBrowserTest {
+ public:
+ ScrollLatencyCompositedScrollbarBrowserTest() {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kCompositorThreadedScrollbarScrolling);
+ }
+ ~ScrollLatencyCompositedScrollbarBrowserTest() override {}
+
+ protected:
+ bool DoesScrollbarScrollOnMainThread() const override { return false; }
+
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(ScrollLatencyCompositedScrollbarBrowserTest,
+ ScrollbarButtonLatency) {
+ LoadURL();
+
+ RunScrollbarButtonLatencyTest();
+}
+
+IN_PROC_BROWSER_TEST_F(ScrollLatencyCompositedScrollbarBrowserTest,
+ ScrollbarThumbDragLatency) {
+ LoadURL();
+
+ RunScrollbarThumbDragLatencyTest();
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.mm b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.mm
index 90871e812b3..449627c936c 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.mm
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.mm
@@ -7,7 +7,7 @@
#include "base/mac/scoped_nsautorelease_pool.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
-#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
+#import "content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
// Unlike some event APIs, Apple does not provide a way to programmatically
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 30ae6812bdb..be65d1aa674 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
@@ -80,10 +80,8 @@ class TouchSelectionControllerClientAura::EnvEventObserver
// Check IsMouseEventsEnabled, except on Mus, where it's disabled on touch
// events in this client, but not re-enabled on mouse events elsewhere.
auto* cursor = aura::client::GetCursorClient(window_->GetRootWindow());
- if (cursor && !cursor->IsMouseEventsEnabled() &&
- aura::Env::GetInstance()->mode() != aura::Env::Mode::MUS) {
+ if (cursor && !cursor->IsMouseEventsEnabled())
return;
- }
// Windows OS unhandled WM_POINTER* may be redispatched as WM_MOUSE*.
// Avoid adjusting the handles on synthesized events or events generated
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h
index d38d5c28e85..3e6b3c2ec48 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h
@@ -63,6 +63,12 @@ class TouchSelectionControllerClientManagerAndroid
const viz::FrameSinkId& frame_sink_id,
const std::vector<viz::AggregatedHitTestRegion>& hit_test_data) override;
+ bool has_active_selection() const {
+ return manager_selection_start_.type() !=
+ gfx::SelectionBound::Type::EMPTY ||
+ manager_selection_end_.type() != gfx::SelectionBound::Type::EMPTY;
+ }
+
private:
// Neither of the following pointers are owned, and both are assumed to
// outlive this object.
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 b24aebf372d..f4bada5e694 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
@@ -286,8 +286,8 @@ IN_PROC_BROWSER_TEST_F(WheelScrollLatchingBrowserTest,
blink::WebInputEvent::GetStaticTimeStampForTests(),
blink::WebGestureDevice::kTouchpad);
gesture_scroll_begin.data.scroll_begin.delta_hint_units =
- precise ? blink::WebGestureEvent::ScrollUnits::kPrecisePixels
- : blink::WebGestureEvent::ScrollUnits::kPixels;
+ precise ? ui::input_types::ScrollGranularity::kScrollByPrecisePixel
+ : ui::input_types::ScrollGranularity::kScrollByPixel;
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0.f;
gesture_scroll_begin.data.scroll_begin.delta_y_hint = -20.f;
gesture_scroll_begin.SetPositionInWidget(gfx::PointF(x, y));
@@ -298,8 +298,8 @@ IN_PROC_BROWSER_TEST_F(WheelScrollLatchingBrowserTest,
blink::WebGestureEvent gesture_scroll_update(gesture_scroll_begin);
gesture_scroll_update.SetType(blink::WebGestureEvent::kGestureScrollUpdate);
gesture_scroll_update.data.scroll_update.delta_units =
- precise ? blink::WebGestureEvent::ScrollUnits::kPrecisePixels
- : blink::WebGestureEvent::ScrollUnits::kPixels;
+ precise ? ui::input_types::ScrollGranularity::kScrollByPrecisePixel
+ : ui::input_types::ScrollGranularity::kScrollByPixel;
gesture_scroll_update.data.scroll_update.delta_x = 0.f;
gesture_scroll_update.data.scroll_update.delta_y = -20.f;
GetRootView()->ProcessGestureEvent(gesture_scroll_update, ui::LatencyInfo());
diff --git a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.h b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.h
index 950515b4f9f..4f12296e318 100644
--- a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.h
+++ b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.h
@@ -5,6 +5,10 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_LEGACY_RENDER_WIDGET_HOST_WIN_H_
#define CONTENT_BROWSER_RENDERER_HOST_LEGACY_RENDER_WIDGET_HOST_WIN_H_
+// Must be included before <atlapp.h>.
+#include "base/win/atl.h" // NOLINT(build/include_order)
+
+#include <atlapp.h>
#include <atlcrack.h>
#include <oleacc.h>
#include <wrl/client.h>
@@ -12,7 +16,6 @@
#include <memory>
#include "base/macros.h"
-#include "base/win/atl.h"
#include "content/common/content_export.h"
#include "ui/compositor/compositor_animation_observer.h"
#include "ui/gfx/geometry/rect.h"
diff --git a/chromium/content/browser/renderer_host/media/OWNERS b/chromium/content/browser/renderer_host/media/OWNERS
index bc81f308b4a..866abc0797b 100644
--- a/chromium/content/browser/renderer_host/media/OWNERS
+++ b/chromium/content/browser/renderer_host/media/OWNERS
@@ -1,7 +1,6 @@
file://media/OWNERS
# WebRTC OWNERS.
-emircan@chromium.org
guidou@chromium.org
tommi@chromium.org
olka@chromium.org
@@ -10,6 +9,7 @@ maxmorin@chromium.org
per-file *video*=chfremer@chromium.org
# Original (legacy) owner.
+per-file *video*=emircan@chromium.org
per-file *video*=mcasas@chromium.org
# TEAM: webrtc-dev@chromium.org
diff --git a/chromium/content/browser/renderer_host/media/audio_output_delegate_impl.cc b/chromium/content/browser/renderer_host/media/audio_output_delegate_impl.cc
index aa87128fe0b..4c516cdf1f3 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_delegate_impl.cc
+++ b/chromium/content/browser/renderer_host/media/audio_output_delegate_impl.cc
@@ -197,6 +197,11 @@ void AudioOutputDelegateImpl::OnPauseStream() {
audio_log_->OnStopped();
}
+void AudioOutputDelegateImpl::OnFlushStream() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ controller_->Flush();
+}
+
void AudioOutputDelegateImpl::OnSetVolume(double volume) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_GE(volume, 0);
diff --git a/chromium/content/browser/renderer_host/media/audio_output_delegate_impl.h b/chromium/content/browser/renderer_host/media/audio_output_delegate_impl.h
index f5d3a026d06..59f0fc89e9f 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_delegate_impl.h
+++ b/chromium/content/browser/renderer_host/media/audio_output_delegate_impl.h
@@ -66,6 +66,7 @@ class CONTENT_EXPORT AudioOutputDelegateImpl
int GetStreamId() override;
void OnPlayStream() override;
void OnPauseStream() override;
+ void OnFlushStream() override;
void OnSetVolume(double volume) override;
private:
diff --git a/chromium/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc b/chromium/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
index e4d186b9a65..86070c3ab89 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
@@ -106,6 +106,7 @@ class DummyAudioOutputStream : public media::AudioOutputStream {
void SetVolume(double volume) override {}
void GetVolume(double* volume) override { *volume = 1; }
void Close() override {}
+ void Flush() override {}
};
class MockAudioOutputStreamObserver
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 567c9001b64..b46c804d28e 100644
--- a/chromium/content/browser/renderer_host/media/audio_service_listener.cc
+++ b/chromium/content/browser/renderer_host/media/audio_service_listener.cc
@@ -11,6 +11,7 @@
#include "base/time/default_tick_clock.h"
#include "content/browser/media/audio_log_factory.h"
#include "content/public/common/content_features.h"
+#include "mojo/public/cpp/bindings/remote.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"
@@ -222,10 +223,10 @@ void AudioServiceListener::MaybeSetLogFactory() {
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(*current_instance_identity_,
- mojo::MakeRequest(&log_factory_manager_ptr));
- log_factory_manager_ptr->SetLogFactory(std::move(audio_log_factory_ptr));
+ mojo::Remote<audio::mojom::LogFactoryManager> log_factory_manager;
+ connector_->Connect(*current_instance_identity_,
+ log_factory_manager.BindNewPipeAndPassReceiver());
+ log_factory_manager->SetLogFactory(audio_log_factory_ptr.PassInterface());
log_factory_is_set_ = true;
}
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 181838da74e..1408405bd85 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
@@ -9,9 +9,12 @@
#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.h"
#include "media/capture/video/video_frame_receiver_on_task_runner.h"
+#if defined(OS_CHROMEOS)
+#include "media/capture/video/chromeos/video_capture_jpeg_decoder.h"
+#endif // defined(OS_CHROMEOS)
+
namespace {
static const int kMaxBufferCount = 3;
@@ -72,17 +75,25 @@ void FakeVideoCaptureDeviceLauncher::LaunchDeviceAsync(
Callbacks* callbacks,
base::OnceClosure done_cb) {
auto device = system_->CreateDevice(device_id);
- auto empty_jpeg_decoder_factory_cb = base::BindRepeating(
- []() { return std::unique_ptr<media::VideoCaptureJpegDecoder>(); });
scoped_refptr<media::VideoCaptureBufferPool> buffer_pool(
new media::VideoCaptureBufferPoolImpl(
std::make_unique<media::VideoCaptureBufferTrackerFactoryImpl>(),
kMaxBufferCount));
+#if defined(OS_CHROMEOS)
+ auto device_client = std::make_unique<media::VideoCaptureDeviceClient>(
+ media::VideoCaptureBufferType::kSharedMemory,
+ std::make_unique<media::VideoFrameReceiverOnTaskRunner>(
+ receiver, base::ThreadTaskRunnerHandle::Get()),
+ std::move(buffer_pool), base::BindRepeating([]() {
+ return std::unique_ptr<media::VideoCaptureJpegDecoder>();
+ }));
+#else
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));
+ std::move(buffer_pool));
+#endif // defined(OS_CHROMEOS)
device->AllocateAndStart(params, std::move(device_client));
auto launched_device =
std::make_unique<FakeLaunchedVideoCaptureDevice>(std::move(device));
diff --git a/chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc b/chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc
index 3990b6dca62..8dafe4571e6 100644
--- a/chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc
+++ b/chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc
@@ -4,6 +4,8 @@
#include "content/browser/renderer_host/media/in_process_launched_video_capture_device.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/metrics/histogram_macros.h"
@@ -22,7 +24,7 @@ void StopAndReleaseDeviceOnDeviceThread(media::VideoCaptureDevice* device,
device->StopAndDeAllocate();
DVLOG(3) << "StopAndReleaseDeviceOnDeviceThread";
delete device;
- base::ResetAndReturn(&done_cb).Run();
+ std::move(done_cb).Run();
}
} // anonymous namespace
@@ -157,7 +159,7 @@ void InProcessLaunchedVideoCaptureDevice::
desktop_device->SetNotificationWindowId(window_id);
VLOG(2) << "Screen capture notification window passed on device thread.";
#endif
- base::ResetAndReturn(&done_cb).Run();
+ std::move(done_cb).Run();
}
} // namespace content
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 90a8815fa92..d311c63a2db 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
@@ -13,7 +13,6 @@
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "build/build_config.h"
-#include "content/browser/gpu/video_capture_dependencies.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/public/browser/browser_task_traits.h"
@@ -23,11 +22,9 @@
#include "media/base/media_switches.h"
#include "media/capture/video/fake_video_capture_device.h"
#include "media/capture/video/fake_video_capture_device_factory.h"
-#include "media/capture/video/scoped_video_capture_jpeg_decoder.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"
#include "third_party/blink/public/common/mediastream/media_stream_request.h"
@@ -45,8 +42,15 @@
#endif // defined(OS_ANDROID)
#endif // defined(ENABLE_SCREEN_CAPTURE)
+#if defined(OS_CHROMEOS)
+#include "content/browser/gpu/chromeos/video_capture_dependencies.h"
+#include "media/capture/video/chromeos/scoped_video_capture_jpeg_decoder.h"
+#include "media/capture/video/chromeos/video_capture_jpeg_decoder_impl.h"
+#endif // defined(OS_CHROMEOS)
+
namespace {
+#if defined(OS_CHROMEOS)
std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder(
media::VideoCaptureJpegDecoder::DecodeDoneCB decode_done_cb,
base::Callback<void(const std::string&)> send_log_message_cb) {
@@ -60,6 +64,7 @@ std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder(
std::move(send_log_message_cb)),
io_task_runner);
}
+#endif // defined(OS_CHROMEOS)
// The maximum number of video frame buffers in-flight at any one time. This
// value should be based on the logical capacity of the capture pipeline, and
@@ -248,6 +253,7 @@ InProcessVideoCaptureDeviceLauncher::CreateDeviceClient(
std::make_unique<media::VideoCaptureBufferTrackerFactoryImpl>(),
buffer_pool_max_buffer_count);
+#if defined(OS_CHROMEOS)
return std::make_unique<media::VideoCaptureDeviceClient>(
requested_buffer_type, std::move(receiver), std::move(buffer_pool),
base::BindRepeating(
@@ -256,6 +262,10 @@ InProcessVideoCaptureDeviceLauncher::CreateDeviceClient(
receiver_on_io_thread),
base::BindRepeating(&media::VideoFrameReceiver::OnLog,
receiver_on_io_thread)));
+#else
+ return std::make_unique<media::VideoCaptureDeviceClient>(
+ requested_buffer_type, std::move(receiver), std::move(buffer_pool));
+#endif // defined(OS_CHROMEOS)
}
void InProcessVideoCaptureDeviceLauncher::OnDeviceStarted(
@@ -271,11 +281,11 @@ void InProcessVideoCaptureDeviceLauncher::OnDeviceStarted(
callbacks->OnDeviceLaunchFailed(
media::VideoCaptureError::
kInProcessDeviceLauncherFailedToCreateDeviceInstance);
- base::ResetAndReturn(&done_cb).Run();
+ std::move(done_cb).Run();
return;
case State::DEVICE_START_ABORTING:
callbacks->OnDeviceLaunchAborted();
- base::ResetAndReturn(&done_cb).Run();
+ std::move(done_cb).Run();
return;
case State::READY_TO_LAUNCH:
NOTREACHED();
@@ -289,12 +299,12 @@ void InProcessVideoCaptureDeviceLauncher::OnDeviceStarted(
switch (state_copy) {
case State::DEVICE_START_IN_PROGRESS:
callbacks->OnDeviceLaunched(std::move(launched_device));
- base::ResetAndReturn(&done_cb).Run();
+ std::move(done_cb).Run();
return;
case State::DEVICE_START_ABORTING:
launched_device.reset();
callbacks->OnDeviceLaunchAborted();
- base::ResetAndReturn(&done_cb).Run();
+ std::move(done_cb).Run();
return;
case State::READY_TO_LAUNCH:
NOTREACHED();
diff --git a/chromium/content/browser/renderer_host/media/in_process_video_capture_provider.cc b/chromium/content/browser/renderer_host/media/in_process_video_capture_provider.cc
index 9ae149033e6..9fdeae4ad94 100644
--- a/chromium/content/browser/renderer_host/media/in_process_video_capture_provider.cc
+++ b/chromium/content/browser/renderer_host/media/in_process_video_capture_provider.cc
@@ -4,6 +4,8 @@
#include "content/browser/renderer_host/media/in_process_video_capture_provider.h"
+#include <utility>
+
#include "base/bind.h"
#include "content/browser/renderer_host/media/in_process_video_capture_device_launcher.h"
@@ -51,7 +53,7 @@ void InProcessVideoCaptureProvider::GetDeviceInfosAsync(
"InProcessVideoCaptureProvider::GetDeviceInfosAsync: No video capture "
"system, returning empty results.");
std::vector<media::VideoCaptureDeviceInfo> empty_result;
- base::ResetAndReturn(&result_callback).Run(empty_result);
+ std::move(result_callback).Run(empty_result);
return;
}
emit_log_message_cb_.Run(
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 e24c056e16c..77c0dab7fe8 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager.cc
@@ -346,7 +346,7 @@ class MediaDevicesManager::AudioServiceDeviceListener
audio::mojom::DeviceListenerPtr audio_device_listener_ptr;
binding_.Bind(mojo::MakeRequest(&audio_device_listener_ptr));
mojo_audio_device_notifier_->RegisterListener(
- std::move(audio_device_listener_ptr));
+ audio_device_listener_ptr.PassInterface());
}
void OnConnectionError(service_manager::Connector* connector) {
diff --git a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index b0ada0c270c..c0c30efe939 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -6,6 +6,7 @@
#include <stddef.h>
#include <stdint.h>
+
#include <memory>
#include <string>
#include <utility>
@@ -169,7 +170,7 @@ class MockMediaStreamDispatcherHost
// Notify that the event have occurred.
base::Closure quit_closure = quit_closures_.front();
quit_closures_.pop();
- task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
+ task_runner_->PostTask(FROM_HERE, std::move(quit_closure));
label_ = label;
audio_devices_ = audio_devices;
@@ -182,7 +183,7 @@ class MockMediaStreamDispatcherHost
if (!quit_closures_.empty()) {
base::Closure quit_closure = quit_closures_.front();
quit_closures_.pop();
- task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
+ task_runner_->PostTask(FROM_HERE, std::move(quit_closure));
}
label_.clear();
@@ -203,7 +204,7 @@ class MockMediaStreamDispatcherHost
const blink::MediaStreamDevice& device) {
base::Closure quit_closure = quit_closures_.front();
quit_closures_.pop();
- task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
+ task_runner_->PostTask(FROM_HERE, std::move(quit_closure));
if (success) {
label_ = label;
opened_device_ = device;
@@ -288,7 +289,7 @@ class MediaStreamDispatcherHostTest : public testing::Test {
info.descriptor.capture_api = kStubCaptureApi;
result.push_back(info);
}
- base::ResetAndReturn(&result_callback).Run(result);
+ std::move(result_callback).Run(result);
}));
base::RunLoop run_loop;
@@ -315,7 +316,7 @@ class MediaStreamDispatcherHostTest : public testing::Test {
std::unique_ptr<FakeMediaStreamUIProxy> CreateMockUI(bool expect_started) {
std::unique_ptr<MockMediaStreamUIProxy> fake_ui =
std::make_unique<MockMediaStreamUIProxy>();
- testing::Mock::AllowLeak(fake_ui.get());
+
if (expect_started)
EXPECT_CALL(*fake_ui, MockOnStarted(_));
return fake_ui;
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager.cc b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
index e8a3b75b992..e0ef26029b4 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -30,7 +30,6 @@
#include "build/build_config.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/gpu/video_capture_dependencies.h"
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/audio_service_listener.h"
@@ -78,6 +77,7 @@
#if defined(OS_CHROMEOS)
#include "chromeos/audio/cras_audio_handler.h"
+#include "content/browser/gpu/chromeos/video_capture_dependencies.h"
#include "content/browser/gpu/gpu_memory_buffer_manager_singleton.h"
#include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
#include "media/capture/video/chromeos/public/cros_features.h"
@@ -656,16 +656,16 @@ std::string MediaStreamManager::MakeMediaAccessRequest(
MediaAccessRequestCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DeviceRequest* request = new DeviceRequest(
+ auto request = std::make_unique<DeviceRequest>(
render_process_id, render_frame_id, requester_id, page_request_id,
false /* user gesture */, blink::MEDIA_DEVICE_ACCESS, controls,
MediaDeviceSaltAndOrigin{std::string() /* salt */,
std::string() /* group_id_salt */,
security_origin});
- const std::string& label = AddRequest(request);
-
request->media_access_request_cb = std::move(callback);
+ const std::string& label = AddRequest(std::move(request));
+
// Post a task and handle the request asynchronously. The reason is that the
// requester won't have a label for the request until this function returns
// and thus can not handle a response. Using base::Unretained is safe since
@@ -697,7 +697,7 @@ void MediaStreamManager::GenerateStream(
std::move(salt_and_origin), std::move(device_stopped_cb));
request->device_changed_cb = std::move(device_changed_cb);
- const std::string& label = AddRequest(request);
+ const std::string& label = AddRequest(base::WrapUnique(request));
request->generate_stream_cb = std::move(generate_stream_cb);
@@ -729,7 +729,7 @@ void MediaStreamManager::CancelRequest(int render_process_id,
int page_request_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
for (const LabeledDeviceRequest& labeled_request : requests_) {
- DeviceRequest* const request = labeled_request.second;
+ DeviceRequest* const request = labeled_request.second.get();
if (request->requesting_process_id == render_process_id &&
request->requesting_frame_id == render_frame_id &&
request->requester_id == requester_id &&
@@ -798,7 +798,7 @@ void MediaStreamManager::StopStreamDevice(int render_process_id,
// of type MEDIA_GENERATE_STREAM that has requested to use |device_id| and
// stop it.
for (const LabeledDeviceRequest& device_request : requests_) {
- DeviceRequest* const request = device_request.second;
+ DeviceRequest* const request = device_request.second.get();
if (request->requesting_process_id != render_process_id ||
request->requesting_frame_id != render_frame_id ||
request->requester_id != requester_id ||
@@ -838,7 +838,7 @@ void MediaStreamManager::StopDevice(MediaStreamType type, int session_id) {
<< "{session_id = " << session_id << "}";
auto request_it = requests_.begin();
while (request_it != requests_.end()) {
- DeviceRequest* request = request_it->second;
+ DeviceRequest* request = request_it->second.get();
MediaStreamDevices* devices = &request->devices;
if (devices->empty()) {
// There is no device in use yet by this request.
@@ -878,7 +878,7 @@ void MediaStreamManager::CloseDevice(MediaStreamType type, int session_id) {
GetDeviceManager(type)->Close(session_id);
for (const LabeledDeviceRequest& labeled_request : requests_) {
- DeviceRequest* const request = labeled_request.second;
+ DeviceRequest* const request = labeled_request.second.get();
for (const MediaStreamDevice& device : request->devices) {
if (device.session_id == session_id && device.type == type) {
// Notify observers that this device is being closed.
@@ -914,14 +914,14 @@ void MediaStreamManager::OpenDevice(int render_process_id,
} else {
NOTREACHED();
}
- DeviceRequest* request = new DeviceRequest(
+ auto request = std::make_unique<DeviceRequest>(
render_process_id, render_frame_id, requester_id, page_request_id,
false /* user gesture */, blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY, controls,
std::move(salt_and_origin), std::move(device_stopped_cb));
- const std::string& label = AddRequest(request);
-
request->open_device_cb = std::move(open_device_cb);
+ const std::string& label = AddRequest(std::move(request));
+
// Post a task and handle the request asynchronously. The reason is that the
// requester won't have a label for the request until this function returns
// and thus can not handle a response. Using base::Unretained is safe since
@@ -968,7 +968,7 @@ void MediaStreamManager::StopRemovedDevice(
MediaStreamType stream_type = ConvertToMediaStreamType(type);
std::vector<int> session_ids;
for (const LabeledDeviceRequest& labeled_request : requests_) {
- const DeviceRequest* request = labeled_request.second;
+ const DeviceRequest* request = labeled_request.second.get();
for (const MediaStreamDevice& device : request->devices) {
const std::string source_id = GetHMACForMediaDeviceID(
request->salt_and_origin.device_id_salt,
@@ -1074,7 +1074,8 @@ void MediaStreamManager::StartEnumeration(DeviceRequest* request,
request_video_input, label));
}
-std::string MediaStreamManager::AddRequest(DeviceRequest* request) {
+std::string MediaStreamManager::AddRequest(
+ std::unique_ptr<DeviceRequest> request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Create a label for this request and verify it is unique.
@@ -1083,7 +1084,7 @@ std::string MediaStreamManager::AddRequest(DeviceRequest* request) {
unique_label = RandomLabel();
} while (FindRequest(unique_label) != nullptr);
- requests_.push_back(std::make_pair(unique_label, request));
+ requests_.push_back(std::make_pair(unique_label, std::move(request)));
return unique_label;
}
@@ -1093,7 +1094,7 @@ MediaStreamManager::DeviceRequest* MediaStreamManager::FindRequest(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
for (const LabeledDeviceRequest& labeled_request : requests_) {
if (labeled_request.first == label)
- return labeled_request.second;
+ return labeled_request.second.get();
}
return nullptr;
}
@@ -1104,7 +1105,6 @@ void MediaStreamManager::DeleteRequest(const std::string& label) {
for (auto request_it = requests_.begin(); request_it != requests_.end();
++request_it) {
if (request_it->first == label) {
- std::unique_ptr<DeviceRequest> request(request_it->second);
requests_.erase(request_it);
return;
}
@@ -1465,7 +1465,7 @@ bool MediaStreamManager::FindExistingRequestedDevice(
new_request.salt_and_origin.origin, new_device.id);
for (const LabeledDeviceRequest& labeled_request : requests_) {
- const DeviceRequest* request = labeled_request.second;
+ const DeviceRequest* request = labeled_request.second.get();
if (request->requesting_process_id == new_request.requesting_process_id &&
request->requesting_frame_id == new_request.requesting_frame_id &&
request->request_type() == new_request.request_type()) {
@@ -1662,7 +1662,7 @@ void MediaStreamManager::Opened(MediaStreamType stream_type,
// requested from the same web page.
for (const LabeledDeviceRequest& labeled_request : requests_) {
const std::string& label = labeled_request.first;
- DeviceRequest* request = labeled_request.second;
+ DeviceRequest* request = labeled_request.second.get();
for (MediaStreamDevice& device : request->devices) {
if (device.type == stream_type &&
device.session_id == capture_session_id) {
@@ -2173,7 +2173,7 @@ void MediaStreamManager::SetCapturingLinkSecured(int render_process_id,
bool is_secure) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
for (LabeledDeviceRequest& labeled_request : requests_) {
- DeviceRequest* request = labeled_request.second;
+ DeviceRequest* request = labeled_request.second.get();
if (request->requesting_process_id != render_process_id)
continue;
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 5152f7e6f7b..5c5b4491bd1 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.h
@@ -351,7 +351,8 @@ class CONTENT_EXPORT MediaStreamManager
// |DeviceRequests| is a list to ensure requests are processed in the order
// they arrive. The first member of the pair is the label of the
// |DeviceRequest|.
- using LabeledDeviceRequest = std::pair<std::string, DeviceRequest*>;
+ using LabeledDeviceRequest =
+ std::pair<std::string, std::unique_ptr<DeviceRequest>>;
using DeviceRequests = std::list<LabeledDeviceRequest>;
void InitializeMaybeAsync(
@@ -386,7 +387,7 @@ class CONTENT_EXPORT MediaStreamManager
bool RequestDone(const DeviceRequest& request) const;
MediaStreamProvider* GetDeviceManager(blink::MediaStreamType stream_type);
void StartEnumeration(DeviceRequest* request, const std::string& label);
- std::string AddRequest(DeviceRequest* request);
+ std::string AddRequest(std::unique_ptr<DeviceRequest> request);
DeviceRequest* FindRequest(const std::string& label) const;
void DeleteRequest(const std::string& label);
// Prepare the request with label |label| by starting device enumeration if
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
index 92258b85ba7..2c66686aaee 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -5,6 +5,7 @@
#include <stddef.h>
#include <string>
+#include <utility>
#include "base/bind.h"
#include "base/command_line.h"
@@ -200,7 +201,7 @@ class MediaStreamManagerTest : public ::testing::Test {
.WillByDefault(Invoke(
[](VideoCaptureProvider::GetDeviceInfosCallback& result_callback) {
std::vector<media::VideoCaptureDeviceInfo> stub_results;
- base::ResetAndReturn(&result_callback).Run(stub_results);
+ std::move(result_callback).Run(stub_results);
}));
}
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
index a568bb75150..c8209bde039 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
@@ -273,14 +273,14 @@ void MediaStreamUIProxy::ProcessAccessRequestResponse(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!response_callback_.is_null());
- base::ResetAndReturn(&response_callback_).Run(devices, result);
+ std::move(response_callback_).Run(devices, result);
}
void MediaStreamUIProxy::ProcessStopRequestFromUI() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!stop_callback_.is_null());
- base::ResetAndReturn(&stop_callback_).Run();
+ std::move(stop_callback_).Run();
}
void MediaStreamUIProxy::ProcessChangeSourceRequestFromUI() {
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 b3f6212309e..c1f510a283d 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
@@ -78,6 +78,7 @@ class MockAudioOutputDelegate : public media::AudioOutputDelegate {
MOCK_METHOD0(GetStreamId, int());
MOCK_METHOD0(OnPlayStream, void());
MOCK_METHOD0(OnPauseStream, void());
+ MOCK_METHOD0(OnFlushStream, void());
MOCK_METHOD1(OnSetVolume, void(double));
private:
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 3a3e01619d3..a70b052a9f1 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
@@ -106,10 +106,10 @@ class MAYBE_RenderFrameAudioInputStreamFactoryTest
~MockStreamFactory() override {}
void CreateInputStream(
- media::mojom::AudioInputStreamRequest stream_request,
- media::mojom::AudioInputStreamClientPtr client,
- media::mojom::AudioInputStreamObserverPtr observer,
- media::mojom::AudioLogPtr log,
+ mojo::PendingReceiver<media::mojom::AudioInputStream> stream_receiver,
+ mojo::PendingRemote<media::mojom::AudioInputStreamClient> client,
+ mojo::PendingRemote<media::mojom::AudioInputStreamObserver> observer,
+ mojo::PendingRemote<media::mojom::AudioLog> log,
const std::string& device_id,
const media::AudioParameters& params,
uint32_t shared_memory_count,
@@ -121,9 +121,9 @@ class MAYBE_RenderFrameAudioInputStreamFactoryTest
}
void CreateLoopbackStream(
- media::mojom::AudioInputStreamRequest stream_request,
- media::mojom::AudioInputStreamClientPtr client,
- media::mojom::AudioInputStreamObserverPtr observer,
+ mojo::PendingReceiver<media::mojom::AudioInputStream> receiver,
+ mojo::PendingRemote<media::mojom::AudioInputStreamClient> client,
+ mojo::PendingRemote<media::mojom::AudioInputStreamObserver> observer,
const media::AudioParameters& params,
uint32_t shared_memory_count,
const base::UnguessableToken& group_id,
diff --git a/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc b/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc
index 90d506d2ca5..e9e55f745d3 100644
--- a/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc
@@ -88,9 +88,10 @@ class RenderFrameAudioOutputStreamFactoryTest
RenderViewHostTestHarness::TearDown();
}
- void BindFactory(mojo::ScopedMessagePipeHandle factory_request) {
- audio_service_stream_factory_.binding_.Bind(
- audio::mojom::StreamFactoryRequest(std::move(factory_request)));
+ void BindFactory(mojo::ScopedMessagePipeHandle factory_receiver) {
+ audio_service_stream_factory_.receiver_.Bind(
+ mojo::PendingReceiver<audio::mojom::StreamFactory>(
+ std::move(factory_receiver)));
}
class MockStreamFactory : public audio::FakeStreamFactory {
@@ -99,9 +100,10 @@ class RenderFrameAudioOutputStreamFactoryTest
~MockStreamFactory() override {}
void CreateOutputStream(
- media::mojom::AudioOutputStreamRequest stream_request,
- media::mojom::AudioOutputStreamObserverAssociatedPtrInfo observer_info,
- media::mojom::AudioLogPtr log,
+ mojo::PendingReceiver<media::mojom::AudioOutputStream> stream_receiver,
+ mojo::PendingAssociatedRemote<media::mojom::AudioOutputStreamObserver>
+ observer,
+ mojo::PendingRemote<media::mojom::AudioLog> log,
const std::string& output_device_id,
const media::AudioParameters& params,
const base::UnguessableToken& group_id,
diff --git a/chromium/content/browser/renderer_host/media/service_launched_video_capture_device.cc b/chromium/content/browser/renderer_host/media/service_launched_video_capture_device.cc
index c52a2c9e49a..d11894030b7 100644
--- a/chromium/content/browser/renderer_host/media/service_launched_video_capture_device.cc
+++ b/chromium/content/browser/renderer_host/media/service_launched_video_capture_device.cc
@@ -4,6 +4,8 @@
#include "content/browser/renderer_host/media/service_launched_video_capture_device.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -100,7 +102,7 @@ void ServiceLaunchedVideoCaptureDevice::
DCHECK(sequence_checker_.CalledOnValidSequence());
source_.reset();
subscription_.reset();
- base::ResetAndReturn(&connection_lost_cb_).Run();
+ std::move(connection_lost_cb_).Run();
}
void ServiceLaunchedVideoCaptureDevice::OnGetPhotoStateResponse(
diff --git a/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.cc b/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
index 87aca6126da..84d2237461d 100644
--- a/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
+++ b/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
@@ -4,6 +4,8 @@
#include "content/browser/renderer_host/media/service_video_capture_device_launcher.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/task/post_task.h"
@@ -30,7 +32,7 @@ void ConcludeLaunchDeviceWithSuccess(
std::make_unique<ServiceLaunchedVideoCaptureDevice>(
std::move(source), std::move(subscription),
std::move(connection_lost_cb)));
- base::ResetAndReturn(&done_cb).Run();
+ std::move(done_cb).Run();
}
void ConcludeLaunchDeviceWithFailure(
@@ -44,7 +46,7 @@ void ConcludeLaunchDeviceWithFailure(
callbacks->OnDeviceLaunchAborted();
else
callbacks->OnDeviceLaunchFailed(error);
- base::ResetAndReturn(&done_cb).Run();
+ std::move(done_cb).Run();
}
} // anonymous namespace
@@ -181,7 +183,7 @@ void ServiceVideoCaptureDeviceLauncher::OnCreatePushSubscriptionCallback(
source.reset();
service_connection_.reset();
callbacks->OnDeviceLaunchAborted();
- base::ResetAndReturn(&done_cb_).Run();
+ std::move(done_cb_).Run();
return;
}
ConcludeLaunchDeviceWithSuccess(
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 c656d4a1280..bf0df78229f 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,6 +4,8 @@
#include "content/browser/renderer_host/media/service_video_capture_provider.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/task/post_task.h"
#include "build/build_config.h"
@@ -12,7 +14,6 @@
#include "content/common/child_process_host_impl.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/delegate_to_browser_gpu_service_accelerator_factory.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"
@@ -20,6 +21,10 @@
#include "services/video_capture/public/mojom/constants.mojom.h"
#include "services/video_capture/public/uma/video_capture_service_event.h"
+#if defined(OS_CHROMEOS)
+#include "content/public/browser/chromeos/delegate_to_browser_gpu_service_accelerator_factory.h"
+#endif // defined(OS_CHROMEOS)
+
#if defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#include "base/metrics/histogram_macros.h"
@@ -30,11 +35,13 @@
namespace {
+#if defined(OS_CHROMEOS)
std::unique_ptr<video_capture::mojom::AcceleratorFactory>
CreateAcceleratorFactory() {
return std::make_unique<
content::DelegateToBrowserGpuServiceAcceleratorFactory>();
}
+#endif // defined(OS_CHROMEOS)
#if defined(OS_MACOSX)
static const int kMaxRetriesForGetDeviceInfos = 1;
@@ -47,11 +54,19 @@ namespace content {
ServiceVideoCaptureProvider::ServiceVideoCaptureProvider(
service_manager::Connector* connector,
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb)
- : ServiceVideoCaptureProvider(
- base::BindRepeating(&CreateAcceleratorFactory),
- connector,
- std::move(emit_log_message_cb)) {}
+ : connector_(connector ? connector->Clone() : nullptr),
+ emit_log_message_cb_(std::move(emit_log_message_cb)),
+ launcher_has_connected_to_source_provider_(false),
+ service_listener_binding_(this),
+ weak_ptr_factory_(this) {
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(
+ &ServiceVideoCaptureProvider::RegisterServiceListenerOnIOThread,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+#if defined(OS_CHROMEOS)
ServiceVideoCaptureProvider::ServiceVideoCaptureProvider(
CreateAcceleratorFactoryCallback create_accelerator_factory_cb,
service_manager::Connector* connector,
@@ -68,6 +83,7 @@ ServiceVideoCaptureProvider::ServiceVideoCaptureProvider(
&ServiceVideoCaptureProvider::RegisterServiceListenerOnIOThread,
weak_ptr_factory_.GetWeakPtr()));
}
+#endif // defined(OS_CHROMEOS)
ServiceVideoCaptureProvider::~ServiceVideoCaptureProvider() {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
@@ -177,10 +193,6 @@ ServiceVideoCaptureProvider::LazyConnectToService() {
launcher_has_connected_to_source_provider_ = 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));
-
DCHECK(connector_)
<< "Attempted to connect to the video capture service from "
"a process that does not provide a "
@@ -189,8 +201,17 @@ ServiceVideoCaptureProvider::LazyConnectToService() {
connector_->BindInterface(video_capture::mojom::kServiceName,
&device_factory_provider);
+#if defined(OS_CHROMEOS)
+ video_capture::mojom::AcceleratorFactoryPtr accelerator_factory;
+ if (!create_accelerator_factory_cb_)
+ create_accelerator_factory_cb_ =
+ base::BindRepeating(&CreateAcceleratorFactory);
+ mojo::MakeStrongBinding(create_accelerator_factory_cb_.Run(),
+ mojo::MakeRequest(&accelerator_factory));
device_factory_provider->InjectGpuDependencies(
std::move(accelerator_factory));
+#endif // defined(OS_CHROMEOS)
+
video_capture::mojom::VideoSourceProviderPtr source_provider;
device_factory_provider->ConnectToVideoSourceProvider(
mojo::MakeRequest(&source_provider));
@@ -265,7 +286,7 @@ void ServiceVideoCaptureProvider::OnDeviceInfosReceived(
}
}
#endif
- base::ResetAndReturn(&result_callback).Run(infos);
+ std::move(result_callback).Run(infos);
}
void ServiceVideoCaptureProvider::OnDeviceInfosRequestDropped(
@@ -285,8 +306,7 @@ void ServiceVideoCaptureProvider::OnDeviceInfosRequestDropped(
SERVICE_DROPPED_DEVICE_INFOS_REQUEST_ON_RETRY);
}
#endif
- base::ResetAndReturn(&result_callback)
- .Run(std::vector<media::VideoCaptureDeviceInfo>());
+ std::move(result_callback).Run(std::vector<media::VideoCaptureDeviceInfo>());
}
void ServiceVideoCaptureProvider::OnLostConnectionToSourceProvider() {
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 44dc929b12b..cdf2386c0c7 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,20 +27,24 @@ class CONTENT_EXPORT ServiceVideoCaptureProvider
: public VideoCaptureProvider,
public service_manager::mojom::ServiceManagerListener {
public:
- using CreateAcceleratorFactoryCallback = base::RepeatingCallback<
- std::unique_ptr<video_capture::mojom::AcceleratorFactory>()>;
// This constructor uses a default factory for instances of
// ws::mojom::Gpu which produces instances of class content::GpuClient.
ServiceVideoCaptureProvider(
service_manager::Connector* connector,
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb);
+
+#if defined(OS_CHROMEOS)
+ using CreateAcceleratorFactoryCallback = base::RepeatingCallback<
+ std::unique_ptr<video_capture::mojom::AcceleratorFactory>()>;
// Lets clients provide a custom mojo::Connector and factory method for
// creating instances of ws::mojom::Gpu.
ServiceVideoCaptureProvider(
CreateAcceleratorFactoryCallback create_accelerator_factory_cb,
service_manager::Connector* connector,
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb);
+#endif // defined(OS_CHROMEOS)
+
~ServiceVideoCaptureProvider() override;
// VideoCaptureProvider implementation.
@@ -89,7 +93,9 @@ class CONTENT_EXPORT ServiceVideoCaptureProvider
void OnServiceConnectionClosed(ReasonForDisconnect reason);
std::unique_ptr<service_manager::Connector> connector_;
+#if defined(OS_CHROMEOS)
CreateAcceleratorFactoryCallback create_accelerator_factory_cb_;
+#endif // defined(OS_CHROMEOS)
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb_;
base::WeakPtr<RefCountedVideoSourceProvider> weak_service_connection_;
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 7423f840485..55a927f0b47 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
@@ -4,6 +4,8 @@
#include "content/browser/renderer_host/media/service_video_capture_provider.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/run_loop.h"
@@ -109,11 +111,16 @@ class ServiceVideoCaptureProviderTest : public testing::Test {
protected:
void SetUp() override {
+#if defined(OS_CHROMEOS)
provider_ = std::make_unique<ServiceVideoCaptureProvider>(
base::BindRepeating([]() {
return std::unique_ptr<video_capture::mojom::AcceleratorFactory>();
}),
connector_factory_.GetDefaultConnector(), kIgnoreLogMessageCB);
+#else
+ provider_ = std::make_unique<ServiceVideoCaptureProvider>(
+ connector_factory_.GetDefaultConnector(), kIgnoreLogMessageCB);
+#endif // defined(OS_CHROMEOS)
ON_CALL(fake_video_capture_service_, BindFactoryProvider(_))
.WillByDefault(Invoke(
@@ -143,7 +150,7 @@ class ServiceVideoCaptureProviderTest : public testing::Test {
.WillByDefault(Invoke([](video_capture::mojom::VideoSourceProvider::
GetSourceInfosCallback& callback) {
std::vector<media::VideoCaptureDeviceInfo> arbitrarily_empty_results;
- base::ResetAndReturn(&callback).Run(arbitrarily_empty_results);
+ std::move(callback).Run(arbitrarily_empty_results);
}));
ON_CALL(mock_source_provider_, DoGetVideoSource(_, _))
@@ -276,8 +283,7 @@ TEST_F(ServiceVideoCaptureProviderTest,
// Exercise part 2: The service responds
std::vector<media::VideoCaptureDeviceInfo> arbitrarily_empty_results;
- base::ResetAndReturn(&callback_to_be_called_by_service)
- .Run(arbitrarily_empty_results);
+ std::move(callback_to_be_called_by_service).Run(arbitrarily_empty_results);
// Verification: Expect |provider_| to close the connection to the service.
wait_for_connection_to_source_provider_to_close.Run();
@@ -415,7 +421,7 @@ TEST_F(ServiceVideoCaptureProviderTest,
// The service now responds to the first request.
std::vector<media::VideoCaptureDeviceInfo> arbitrarily_empty_results;
- base::ResetAndReturn(&callbacks_to_be_called_by_service[0])
+ std::move(callbacks_to_be_called_by_service[0])
.Run(arbitrarily_empty_results);
{
base::RunLoop give_provider_chance_to_disconnect;
@@ -433,7 +439,7 @@ TEST_F(ServiceVideoCaptureProviderTest,
ASSERT_FALSE(connection_has_been_closed);
// The service now responds to the second request.
- base::ResetAndReturn(&callbacks_to_be_called_by_service[1])
+ std::move(callbacks_to_be_called_by_service[1])
.Run(arbitrarily_empty_results);
{
base::RunLoop give_provider_chance_to_disconnect;
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 ba759a0c889..ea6e1810671 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
@@ -276,6 +276,7 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest,
std::move(quit_run_loop_on_current_thread_cb), true);
bool must_wait_for_gpu_decode_to_start = false;
+#if defined(OS_CHROMEOS)
if (params_.exercise_accelerated_jpeg_decoding) {
// Since the GPU jpeg decoder is created asynchronously while decoding
// in software is ongoing, we have to keep pushing frames until a message
@@ -288,6 +289,7 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest,
must_wait_for_gpu_decode_to_start = false;
}));
}
+#endif // defined(OS_CHROMEOS)
EXPECT_CALL(mock_controller_event_handler_, DoOnNewBuffer(_, _, _))
.Times(AtLeast(1));
EXPECT_CALL(mock_controller_event_handler_, OnBufferReady(_, _, _))
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 e3ee4cece01..d0e73149bbd 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
@@ -34,12 +34,15 @@
#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"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_CHROMEOS)
+#include "media/capture/video/chromeos/video_capture_jpeg_decoder_impl.h"
+#endif // defined(OS_CHROMEOS)
+
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::InSequence;
@@ -88,6 +91,7 @@ class MockVideoCaptureControllerEventHandler
int buffer_id,
const media::mojom::VideoFrameInfoPtr& frame_info) override {
EXPECT_EQ(expected_pixel_format_, frame_info->pixel_format);
+ EXPECT_EQ(expected_color_space_, frame_info->color_space);
media::VideoFrameMetadata metadata;
metadata.MergeInternalValuesFrom(frame_info->metadata);
base::TimeTicks reference_time;
@@ -112,6 +116,7 @@ class MockVideoCaptureControllerEventHandler
VideoCaptureController* controller_;
media::VideoPixelFormat expected_pixel_format_ = media::PIXEL_FORMAT_I420;
+ gfx::ColorSpace expected_color_space_ = gfx::ColorSpace::CreateREC709();
double resource_utilization_;
bool enable_auto_return_buffer_on_buffer_ready_ = true;
};
@@ -126,6 +131,7 @@ class VideoCaptureControllerTest
public:
VideoCaptureControllerTest()
: arbitrary_format_(gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420),
+ arbitrary_color_space_(gfx::ColorSpace::CreateREC709()),
arbitrary_route_id_(0x99),
arbitrary_session_id_(100) {}
~VideoCaptureControllerTest() override {}
@@ -160,15 +166,25 @@ class VideoCaptureControllerTest
buffer_pool_ = new media::VideoCaptureBufferPoolImpl(
std::make_unique<media::VideoCaptureBufferTrackerFactoryImpl>(),
kPoolSize);
+#if defined(OS_CHROMEOS)
device_client_.reset(new media::VideoCaptureDeviceClient(
media::VideoCaptureBufferType::kSharedMemory,
std::make_unique<media::VideoFrameReceiverOnTaskRunner>(
controller_->GetWeakPtrForIOThread(),
base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})),
buffer_pool_, media::VideoCaptureJpegDecoderFactoryCB()));
+#else
+ device_client_.reset(new media::VideoCaptureDeviceClient(
+ media::VideoCaptureBufferType::kSharedMemory,
+ std::make_unique<media::VideoFrameReceiverOnTaskRunner>(
+ controller_->GetWeakPtrForIOThread(),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})),
+ buffer_pool_));
+#endif // defined(OS_CHROMEOS)
}
- void SendStubFrameToDeviceClient(const media::VideoCaptureFormat format) {
+ void SendStubFrameToDeviceClient(const media::VideoCaptureFormat format,
+ const gfx::ColorSpace& color_space) {
auto stub_frame = media::VideoFrame::CreateZeroInitializedFrame(
format.pixel_format, format.frame_size,
gfx::Rect(format.frame_size.width(), format.frame_size.height()),
@@ -179,7 +195,7 @@ class VideoCaptureControllerTest
stub_frame->data(0),
media::VideoFrame::AllocationSize(stub_frame->format(),
stub_frame->coded_size()),
- format, rotation, base::TimeTicks(), base::TimeDelta(),
+ format, color_space, rotation, base::TimeTicks(), base::TimeDelta(),
frame_feedback_id);
}
@@ -194,6 +210,7 @@ class VideoCaptureControllerTest
const base::TimeTicks arbitrary_reference_time_ = base::TimeTicks();
const base::TimeDelta arbitrary_timestamp_ = base::TimeDelta();
const media::VideoCaptureFormat arbitrary_format_;
+ const gfx::ColorSpace arbitrary_color_space_;
const VideoCaptureControllerID arbitrary_route_id_;
const media::VideoCaptureSessionId arbitrary_session_id_;
@@ -290,6 +307,10 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
const media::VideoPixelFormat format = GetParam();
client_a_->expected_pixel_format_ = format;
client_b_->expected_pixel_format_ = format;
+ // OnIncomingCapturedBuffer keeps the color space unset. If needed use
+ // OnIncomingCapturedBufferExt.
+ client_a_->expected_color_space_ = gfx::ColorSpace();
+ client_b_->expected_color_space_ = gfx::ColorSpace();
session_100.requested_format =
media::VideoCaptureFormat(gfx::Size(320, 240), 30, format);
@@ -615,6 +636,9 @@ TEST_F(VideoCaptureControllerTest, FrameFeedbackIsReportedForSequenceOfFrames) {
const int kTestFrameSequenceLength = 10;
media::VideoCaptureFormat arbitrary_format(
gfx::Size(320, 240), arbitrary_frame_rate_, media::PIXEL_FORMAT_I420);
+ // OnIncomingCapturedBuffer keeps the color space unset. If needed use
+ // OnIncomingCapturedBufferExt.
+ client_a_->expected_color_space_ = gfx::ColorSpace();
// Register |client_a_| at |controller_|.
media::VideoCaptureParams session_100;
@@ -695,7 +719,7 @@ TEST_F(VideoCaptureControllerTest,
EXPECT_CALL(*client_a_, DoBufferReady(_, _)).Times(1);
}
EXPECT_CALL(*client_a_, DoBufferDestroyed(_, _)).Times(0);
- SendStubFrameToDeviceClient(arbitrary_format_);
+ SendStubFrameToDeviceClient(arbitrary_format_, arbitrary_color_space_);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
@@ -725,7 +749,7 @@ TEST_F(VideoCaptureControllerTest,
.WillOnce(SaveArg<1>(&buffer_id_reported_to_client));
EXPECT_CALL(*client_a_, DoBufferReady(_, _)).Times(1);
}
- SendStubFrameToDeviceClient(arbitrary_format_);
+ SendStubFrameToDeviceClient(arbitrary_format_, arbitrary_color_space_);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
@@ -765,7 +789,7 @@ TEST_F(VideoCaptureControllerTest,
.WillOnce(SaveArg<1>(&first_buffer_id));
EXPECT_CALL(*client_a_, DoBufferReady(_, _)).Times(1);
}
- SendStubFrameToDeviceClient(arbitrary_format_);
+ SendStubFrameToDeviceClient(arbitrary_format_, arbitrary_color_space_);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
@@ -787,7 +811,7 @@ TEST_F(VideoCaptureControllerTest,
.WillOnce(SaveArg<1>(&second_buffer_id));
EXPECT_CALL(*client_a_, DoBufferReady(_, _)).Times(1);
}
- SendStubFrameToDeviceClient(arbitrary_format_);
+ SendStubFrameToDeviceClient(arbitrary_format_, arbitrary_color_space_);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
@@ -908,7 +932,7 @@ TEST_F(VideoCaptureControllerTest,
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
}
- SendStubFrameToDeviceClient(arbitrary_format_);
+ SendStubFrameToDeviceClient(arbitrary_format_, arbitrary_color_space_);
base::RunLoop().RunUntilIdle();
for (int i = 0;
@@ -936,7 +960,7 @@ TEST_F(VideoCaptureControllerTest, DeliveredFrameReenablesDroppedFrameLogging) {
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
}
- SendStubFrameToDeviceClient(arbitrary_format_);
+ SendStubFrameToDeviceClient(arbitrary_format_, arbitrary_color_space_);
base::RunLoop().RunUntilIdle();
controller_->OnFrameDropped(
@@ -975,4 +999,43 @@ TEST_F(VideoCaptureControllerTest,
media::VideoCaptureFrameDropReason::kBufferPoolMaxBufferCountExceeded, 1);
}
+TEST_F(VideoCaptureControllerTest, DeviceClientWithColorSpace) {
+ // Register |client_a_| at |controller_|.
+ media::VideoCaptureParams requested_params;
+ requested_params.requested_format = media::VideoCaptureFormat(
+ gfx::Size(128, 80), 30, media::PIXEL_FORMAT_ARGB);
+ const gfx::ColorSpace data_color_space =
+ gfx::ColorSpace::CreateDisplayP3D65();
+ const gfx::ColorSpace overriden_color_space =
+ data_color_space.GetWithMatrixAndRange(
+ gfx::ColorSpace::MatrixID::SMPTE170M,
+ gfx::ColorSpace::RangeID::LIMITED);
+ client_a_->expected_color_space_ = overriden_color_space;
+ controller_->AddClient(arbitrary_route_id_, client_a_.get(),
+ arbitrary_session_id_, requested_params);
+ base::RunLoop().RunUntilIdle();
+
+ // Device sends a frame to |device_client_| and |client_a_| reports to
+ // |controller_| that it has finished consuming the frame.
+ int buffer_id_reported_to_client = media::VideoCaptureBufferPool::kInvalidId;
+ {
+ InSequence s;
+ EXPECT_CALL(*client_a_, DoBufferCreated(_, _))
+ .Times(1)
+ .WillOnce(SaveArg<1>(&buffer_id_reported_to_client));
+ EXPECT_CALL(*client_a_, DoBufferReady(_, _)).Times(1);
+ }
+ EXPECT_CALL(*client_a_, DoBufferDestroyed(_, _)).Times(0);
+ SendStubFrameToDeviceClient(requested_params.requested_format,
+ data_color_space);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+
+ // |device_client_| is released by the device.
+ EXPECT_CALL(*client_a_, DoBufferDestroyed(_, buffer_id_reported_to_client));
+ device_client_.reset();
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_provider_switcher.cc b/chromium/content/browser/renderer_host/media/video_capture_provider_switcher.cc
index ce3458dc04b..87e9bf3f336 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_provider_switcher.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_provider_switcher.cc
@@ -5,8 +5,9 @@
#include "content/browser/renderer_host/media/video_capture_provider_switcher.h"
#include "content/public/browser/video_capture_device_launcher.h"
+#include <utility>
+
#include "base/bind.h"
-#include "base/callback_helpers.h"
namespace content {
@@ -52,7 +53,7 @@ class VideoCaptureDeviceLauncherSwitcher : public VideoCaptureDeviceLauncher {
void AbortLaunch() override {
if (abort_launch_cb_.is_null())
return;
- base::ResetAndReturn(&abort_launch_cb_).Run();
+ std::move(abort_launch_cb_).Run();
}
private:
diff --git a/chromium/content/browser/renderer_host/overscroll_configuration.cc b/chromium/content/browser/renderer_host/overscroll_configuration.cc
index 4b81ecff2a1..3a10d62c759 100644
--- a/chromium/content/browser/renderer_host/overscroll_configuration.cc
+++ b/chromium/content/browser/renderer_host/overscroll_configuration.cc
@@ -16,12 +16,6 @@ bool g_is_ptr_mode_initialized = false;
content::OverscrollConfig::PullToRefreshMode g_ptr_mode =
content::OverscrollConfig::PullToRefreshMode::kDisabled;
-const float kThresholdCompleteTouchpad = 0.3f;
-const float kThresholdCompleteTouchscreen = 0.25f;
-
-const float kThresholdStartTouchpad = 60.f;
-const float kThresholdStartTouchscreen = 50.f;
-
bool g_is_touchpad_overscroll_history_navigation_enabled_initialized = false;
bool g_touchpad_overscroll_history_navigation_enabled = false;
@@ -29,27 +23,19 @@ bool g_touchpad_overscroll_history_navigation_enabled = false;
// overscroll if it is not completed yet.
int g_max_inertial_events_before_overscroll_cancellation_in_ms = 300;
-float GetStartThresholdMultiplier() {
- base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
- if (!cmd->HasSwitch(switches::kOverscrollStartThreshold))
- return 1.f;
-
- std::string string_value =
- cmd->GetSwitchValueASCII(switches::kOverscrollStartThreshold);
- int percentage;
- if (base::StringToInt(string_value, &percentage) && percentage > 0)
- return percentage / 100.f;
-
- DLOG(WARNING) << "Failed to parse switch "
- << switches::kOverscrollStartThreshold << ": " << string_value;
- return 1.f;
-}
-
} // namespace
namespace content {
// static
+const float OverscrollConfig::kCompleteTouchpadThresholdPercent = 0.3f;
+const float OverscrollConfig::kCompleteTouchscreenThresholdPercent = 0.25f;
+
+// static
+const float OverscrollConfig::kStartTouchpadThresholdDips = 60.f;
+const float OverscrollConfig::kStartTouchscreenThresholdDips = 50.f;
+
+// static
OverscrollConfig::PullToRefreshMode OverscrollConfig::GetPullToRefreshMode() {
if (g_is_ptr_mode_initialized)
return g_ptr_mode;
@@ -66,30 +52,6 @@ OverscrollConfig::PullToRefreshMode OverscrollConfig::GetPullToRefreshMode() {
}
// static
-float OverscrollConfig::GetThreshold(Threshold threshold) {
- switch (threshold) {
- case Threshold::kCompleteTouchpad:
- return kThresholdCompleteTouchpad;
-
- case Threshold::kCompleteTouchscreen:
- return kThresholdCompleteTouchscreen;
-
- case Threshold::kStartTouchpad:
- static const float threshold_start_touchpad =
- GetStartThresholdMultiplier() * kThresholdStartTouchpad;
- return threshold_start_touchpad;
-
- case Threshold::kStartTouchscreen:
- static const float threshold_start_touchscreen =
- GetStartThresholdMultiplier() * kThresholdStartTouchscreen;
- return threshold_start_touchscreen;
- }
-
- NOTREACHED();
- return -1.f;
-}
-
-// static
void OverscrollConfig::SetPullToRefreshMode(PullToRefreshMode mode) {
g_ptr_mode = mode;
g_is_ptr_mode_initialized = true;
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.cc b/chromium/content/browser/renderer_host/overscroll_controller.cc
index 6d71c9fb4b6..f8b5aaeb7c5 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller.cc
@@ -40,7 +40,7 @@ bool IsGestureScrollUpdateInertialEvent(const blink::WebInputEvent& event) {
const blink::WebGestureEvent& gesture =
static_cast<const blink::WebGestureEvent&>(event);
return gesture.data.scroll_update.inertial_phase ==
- blink::WebGestureEvent::kMomentumPhase;
+ blink::WebGestureEvent::InertialPhaseState::kMomentum;
}
float ClampAbsoluteValue(float value, float max_abs) {
@@ -76,23 +76,24 @@ bool OverscrollController::ShouldProcessEvent(
if (IsGestureEventFromAutoscroll(gesture))
return false;
- blink::WebGestureEvent::ScrollUnits scrollUnits;
+ ui::input_types::ScrollGranularity granularity;
switch (event.GetType()) {
case blink::WebInputEvent::kGestureScrollBegin:
- scrollUnits = gesture.data.scroll_begin.delta_hint_units;
+ granularity = gesture.data.scroll_begin.delta_hint_units;
break;
case blink::WebInputEvent::kGestureScrollUpdate:
- scrollUnits = gesture.data.scroll_update.delta_units;
+ granularity = gesture.data.scroll_update.delta_units;
break;
case blink::WebInputEvent::kGestureScrollEnd:
- scrollUnits = gesture.data.scroll_end.delta_units;
+ granularity = gesture.data.scroll_end.delta_units;
break;
default:
- scrollUnits = blink::WebGestureEvent::kPixels;
+ granularity = ui::input_types::ScrollGranularity::kScrollByPixel;
break;
}
- return scrollUnits == blink::WebGestureEvent::kPrecisePixels;
+ return granularity ==
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
}
default:
break;
@@ -266,7 +267,7 @@ bool OverscrollController::DispatchEventCompletesAction(
const blink::WebGestureEvent gesture_event =
static_cast<const blink::WebGestureEvent&>(event);
if (gesture_event.data.scroll_update.inertial_phase !=
- blink::WebGestureEvent::kMomentumPhase)
+ blink::WebGestureEvent::InertialPhaseState::kMomentum)
return false;
}
@@ -278,7 +279,7 @@ bool OverscrollController::DispatchEventCompletesAction(
const blink::WebGestureEvent gesture_event =
static_cast<const blink::WebGestureEvent&>(event);
if (gesture_event.data.scroll_end.inertial_phase !=
- blink::WebGestureEvent::kMomentumPhase)
+ blink::WebGestureEvent::InertialPhaseState::kMomentum)
return false;
}
@@ -320,10 +321,10 @@ bool OverscrollController::DispatchEventCompletesAction(
? overscroll_delta_x_
: overscroll_delta_y_;
const float ratio = fabs(delta) / std::max(size.width(), size.height());
- const float threshold = OverscrollConfig::GetThreshold(
+ const float threshold =
overscroll_source_ == OverscrollSource::TOUCHPAD
- ? OverscrollConfig::Threshold::kCompleteTouchpad
- : OverscrollConfig::Threshold::kCompleteTouchscreen);
+ ? OverscrollConfig::kCompleteTouchpadThresholdPercent
+ : OverscrollConfig::kCompleteTouchscreenThresholdPercent;
return ratio >= threshold;
}
@@ -358,9 +359,10 @@ bool OverscrollController::ProcessEventForOverscroll(
// when the scrolling is in inertial state.
const blink::WebGestureEvent gesture_event =
static_cast<const blink::WebGestureEvent&>(event);
- bool reset_scroll_state = !IsGestureEventFromTouchpad(event) ||
- (gesture_event.data.scroll_end.inertial_phase ==
- blink::WebGestureEvent::kMomentumPhase);
+ bool reset_scroll_state =
+ !IsGestureEventFromTouchpad(event) ||
+ (gesture_event.data.scroll_end.inertial_phase ==
+ blink::WebGestureEvent::InertialPhaseState::kMomentum);
if (reset_scroll_state)
ResetScrollState();
@@ -457,9 +459,9 @@ bool OverscrollController::ProcessOverscroll(float delta_x,
overscroll_delta_x_ += delta_x;
overscroll_delta_y_ += delta_y;
- const float start_threshold = OverscrollConfig::GetThreshold(
- is_touchpad ? OverscrollConfig::Threshold::kStartTouchpad
- : OverscrollConfig::Threshold::kStartTouchscreen);
+ const float start_threshold =
+ is_touchpad ? OverscrollConfig::kStartTouchpadThresholdDips
+ : OverscrollConfig::kStartTouchscreenThresholdDips;
if (fabs(overscroll_delta_x_) <= start_threshold &&
fabs(overscroll_delta_y_) <= start_threshold) {
SetOverscrollMode(OVERSCROLL_NONE, OverscrollSource::NONE);
diff --git a/chromium/content/browser/renderer_host/overscroll_controller_unittest.cc b/chromium/content/browser/renderer_host/overscroll_controller_unittest.cc
index 25c2a238593..41407c7493c 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller_unittest.cc
@@ -73,7 +73,7 @@ class OverscrollControllerTest : public ::testing::Test {
event->SetTimeStamp(timestamp);
if (inertial_update) {
event->data.scroll_update.inertial_phase =
- blink::WebGestureEvent::kMomentumPhase;
+ blink::WebGestureEvent::InertialPhaseState::kMomentum;
}
current_event_ = std::move(event);
return controller_->WillHandleEvent(*current_event_);
diff --git a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
index e8060657ce3..f4e3923063a 100644
--- a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
+++ b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
@@ -21,6 +21,8 @@
#include "content/browser/renderer_host/pepper/pepper_printing_host.h"
#include "content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h"
#include "content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h"
+#include "content/browser/renderer_host/pepper/pepper_truetype_font_host.h"
+#include "content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h"
#include "content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h"
#include "ppapi/host/message_filter_host.h"
#include "ppapi/host/ppapi_host.h"
@@ -173,6 +175,25 @@ ContentBrowserPepperHostFactory::CreateResourceHost(
new PepperPrintingHost(host_->GetPpapiHost(), instance, resource,
std::move(manager)));
}
+ case PpapiHostMsg_TrueTypeFont_Create::ID: {
+ ppapi::proxy::SerializedTrueTypeFontDesc desc;
+ if (!ppapi::UnpackMessage<PpapiHostMsg_TrueTypeFont_Create>(message,
+ &desc)) {
+ NOTREACHED();
+ return std::unique_ptr<ppapi::host::ResourceHost>();
+ }
+ // Check that the family name is valid UTF-8 before passing it to the
+ // host OS.
+ if (!base::IsStringUTF8(desc.family))
+ return std::unique_ptr<ppapi::host::ResourceHost>();
+
+ return std::unique_ptr<ppapi::host::ResourceHost>(
+ new PepperTrueTypeFontHost(host_, instance, resource, desc));
+ }
+ case PpapiHostMsg_TrueTypeFontSingleton_Create::ID: {
+ return std::unique_ptr<ppapi::host::ResourceHost>(
+ new PepperTrueTypeFontListHost(host_, instance, resource));
+ }
#if defined(OS_CHROMEOS)
case PpapiHostMsg_VpnProvider_Create::ID: {
scoped_refptr<PepperVpnProviderMessageFilter> vpn_provider(
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font.h b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font.h
new file mode 100644
index 00000000000..7b31b7c38ac
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font.h
@@ -0,0 +1,57 @@
+// 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_PEPPER_PEPPER_TRUETYPE_FONT_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "ppapi/proxy/serialized_structs.h"
+
+namespace content {
+
+class PepperTrueTypeFont
+ : public base::RefCountedThreadSafe<PepperTrueTypeFont> {
+ public:
+ // Factory method to create a font for the current host.
+ static PepperTrueTypeFont* Create();
+
+ // Initializes the font. Updates the descriptor with the actual font's
+ // characteristics. The exact font will depend on the host platform's font
+ // matching and fallback algorithm. On failure, returns NULL and leaves desc
+ // unchanged.
+ // NOTE: This method may perform long blocking file IO.
+ virtual int32_t Initialize(
+ ppapi::proxy::SerializedTrueTypeFontDesc* desc) = 0;
+
+ // Retrieves an array of TrueType table tags contained in this font. Returns
+ // the number of tags on success, a Pepper error code on failure. 'tags' are
+ // written only on success.
+ // NOTE: This method may perform long blocking file IO. It may be called even
+ // though the call to Initialize failed. Implementors must check validity.
+ virtual int32_t GetTableTags(std::vector<uint32_t>* tags) = 0;
+
+ // Gets a TrueType font table corresponding to the given tag. The 'offset' and
+ // 'max_data_length' parameters determine what part of the table is returned.
+ // Returns the data size in bytes on success, a Pepper error code on failure.
+ // 'data' is written only on success.
+ // NOTE: This method may perform long blocking file IO. It may be called even
+ // though the call to Initialize failed. Implementors must check validity.
+ virtual int32_t GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) = 0;
+
+ protected:
+ friend class base::RefCountedThreadSafe<PepperTrueTypeFont>;
+ virtual ~PepperTrueTypeFont() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc
new file mode 100644
index 00000000000..42a03e777bd
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc
@@ -0,0 +1,153 @@
+// 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/renderer_host/pepper/pepper_truetype_font_host.h"
+
+#include "base/bind.h"
+#include "base/task/post_task.h"
+#include "base/task_runner_util.h"
+#include "content/browser/renderer_host/pepper/pepper_truetype_font.h"
+#include "content/public/browser/browser_ppapi_host.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+using ppapi::host::HostMessageContext;
+using ppapi::host::ReplyMessageContext;
+using ppapi::proxy::SerializedTrueTypeFontDesc;
+
+namespace content {
+
+PepperTrueTypeFontHost::PepperTrueTypeFontHost(
+ BrowserPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource,
+ const SerializedTrueTypeFontDesc& desc)
+ : ResourceHost(host->GetPpapiHost(), instance, resource),
+ initialize_completed_(false),
+ weak_factory_(this) {
+ font_ = PepperTrueTypeFont::Create();
+ // Initialize the font on a ThreadPool thread. This must complete before
+ // using |font_|.
+ task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+ SerializedTrueTypeFontDesc* actual_desc =
+ new SerializedTrueTypeFontDesc(desc);
+ base::PostTaskAndReplyWithResult(
+ task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&PepperTrueTypeFont::Initialize, font_, actual_desc),
+ base::Bind(&PepperTrueTypeFontHost::OnInitializeComplete,
+ weak_factory_.GetWeakPtr(),
+ base::Owned(actual_desc)));
+}
+
+PepperTrueTypeFontHost::~PepperTrueTypeFontHost() {
+ // Release the font on the task runner in case the implementation requires
+ // long blocking operations.
+ task_runner_->ReleaseSoon(FROM_HERE, std::move(font_));
+}
+
+int32_t PepperTrueTypeFontHost::OnResourceMessageReceived(
+ const IPC::Message& msg,
+ HostMessageContext* context) {
+ if (!host()->permissions().HasPermission(ppapi::PERMISSION_DEV))
+ return PP_ERROR_FAILED;
+
+ PPAPI_BEGIN_MESSAGE_MAP(PepperTrueTypeFontHost, msg)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TrueTypeFont_GetTableTags,
+ OnHostMsgGetTableTags)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TrueTypeFont_GetTable,
+ OnHostMsgGetTable)
+ PPAPI_END_MESSAGE_MAP()
+ return PP_ERROR_FAILED;
+}
+
+int32_t PepperTrueTypeFontHost::OnHostMsgGetTableTags(
+ HostMessageContext* context) {
+ if (!font_.get())
+ return PP_ERROR_FAILED;
+
+ // Get font data on a thread that allows slow blocking operations.
+ std::vector<uint32_t>* tags = new std::vector<uint32_t>();
+ base::PostTaskAndReplyWithResult(
+ task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&PepperTrueTypeFont::GetTableTags, font_, tags),
+ base::Bind(&PepperTrueTypeFontHost::OnGetTableTagsComplete,
+ weak_factory_.GetWeakPtr(),
+ base::Owned(tags),
+ context->MakeReplyMessageContext()));
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTrueTypeFontHost::OnHostMsgGetTable(HostMessageContext* context,
+ uint32_t table,
+ int32_t offset,
+ int32_t max_data_length) {
+ if (!font_.get())
+ return PP_ERROR_FAILED;
+ if (offset < 0 || max_data_length < 0)
+ return PP_ERROR_BADARGUMENT;
+
+ // Get font data on a thread that allows slow blocking operations.
+ std::string* data = new std::string();
+ base::PostTaskAndReplyWithResult(
+ task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&PepperTrueTypeFont::GetTable,
+ font_,
+ table,
+ offset,
+ max_data_length,
+ data),
+ base::Bind(&PepperTrueTypeFontHost::OnGetTableComplete,
+ weak_factory_.GetWeakPtr(),
+ base::Owned(data),
+ context->MakeReplyMessageContext()));
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void PepperTrueTypeFontHost::OnInitializeComplete(
+ SerializedTrueTypeFontDesc* desc,
+ int32_t result) {
+ DCHECK(!initialize_completed_);
+ initialize_completed_ = true;
+ // Release the font if there was an error, so future calls will fail.
+ if (result != PP_OK)
+ font_ = nullptr;
+ host()->SendUnsolicitedReply(
+ pp_resource(), PpapiPluginMsg_TrueTypeFont_CreateReply(*desc, result));
+}
+
+void PepperTrueTypeFontHost::OnGetTableTagsComplete(
+ std::vector<uint32_t>* tags,
+ ReplyMessageContext reply_context,
+ int32_t result) {
+ DCHECK(initialize_completed_);
+ // It's possible that Initialize failed and that |font_| is NULL. Check that
+ // the font implementation doesn't return PP_OK in that case.
+ DCHECK(font_.get() || result != PP_OK);
+ reply_context.params.set_result(result);
+ host()->SendReply(reply_context,
+ PpapiPluginMsg_TrueTypeFont_GetTableTagsReply(*tags));
+}
+
+void PepperTrueTypeFontHost::OnGetTableComplete(
+ std::string* data,
+ ReplyMessageContext reply_context,
+ int32_t result) {
+ DCHECK(initialize_completed_);
+ // It's possible that Initialize failed and that |font_| is NULL. Check that
+ // the font implementation doesn't return PP_OK in that case.
+ DCHECK(font_.get() || result != PP_OK);
+ reply_context.params.set_result(result);
+ host()->SendReply(reply_context,
+ PpapiPluginMsg_TrueTypeFont_GetTableReply(*data));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.h b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.h
new file mode 100644
index 00000000000..cd1e7013dcf
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.h
@@ -0,0 +1,72 @@
+// 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_PEPPER_PEPPER_TRUETYPE_FONT_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_HOST_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
+#include "content/browser/renderer_host/pepper/pepper_truetype_font.h"
+#include "content/common/content_export.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/resource_host.h"
+
+namespace content {
+
+class BrowserPpapiHost;
+
+class CONTENT_EXPORT PepperTrueTypeFontHost : public ppapi::host::ResourceHost {
+ public:
+ PepperTrueTypeFontHost(BrowserPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource,
+ const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
+
+ ~PepperTrueTypeFontHost() override;
+
+ int32_t OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) override;
+
+ private:
+ int32_t OnHostMsgGetTableTags(ppapi::host::HostMessageContext* context);
+ int32_t OnHostMsgGetTable(ppapi::host::HostMessageContext* context,
+ uint32_t table,
+ int32_t offset,
+ int32_t max_data_length);
+
+ void OnInitializeComplete(ppapi::proxy::SerializedTrueTypeFontDesc* desc,
+ int32_t result);
+ void OnGetTableTagsComplete(std::vector<uint32_t>* tags,
+ ppapi::host::ReplyMessageContext reply_context,
+ int32_t result);
+ void OnGetTableComplete(std::string* data,
+ ppapi::host::ReplyMessageContext reply_context,
+ int32_t result);
+
+ // We use a SequencedTaskRunner to run potentially slow font operations and
+ // ensure that Initialize completes before we make any calls to get font data.
+ // Even though we allow multiple pending GetTableTags and GetTable calls, this
+ // implies that they run serially.
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ scoped_refptr<PepperTrueTypeFont> font_;
+ bool initialize_completed_;
+
+ base::WeakPtrFactory<PepperTrueTypeFontHost> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_HOST_H_
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
new file mode 100644
index 00000000000..c71954e48c5
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc
@@ -0,0 +1,158 @@
+// 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/renderer_host/pepper/pepper_truetype_font.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/compiler_specific.h"
+#include "base/files/scoped_file.h"
+#include "base/macros.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/sys_byteorder.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"
+
+namespace content {
+
+namespace {
+
+class PepperTrueTypeFontLinux : public PepperTrueTypeFont {
+ public:
+ PepperTrueTypeFontLinux();
+
+ // PepperTrueTypeFont implementation.
+ int32_t Initialize(ppapi::proxy::SerializedTrueTypeFontDesc* desc) override;
+ int32_t GetTableTags(std::vector<uint32_t>* tags) override;
+ int32_t GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) override;
+
+ private:
+ ~PepperTrueTypeFontLinux() override;
+
+ base::ScopedFD fd_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontLinux);
+};
+
+PepperTrueTypeFontLinux::PepperTrueTypeFontLinux() {
+}
+
+PepperTrueTypeFontLinux::~PepperTrueTypeFontLinux() {
+}
+
+int32_t PepperTrueTypeFontLinux::Initialize(
+ ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
+ // If no face is provided, convert family to the platform defaults. These
+ // names should be mapped by FontConfig to an appropriate default font.
+ if (desc->family.empty()) {
+ switch (desc->generic_family) {
+ case PP_TRUETYPEFONTFAMILY_SERIF:
+ desc->family = "serif";
+ break;
+ case PP_TRUETYPEFONTFAMILY_SANSSERIF:
+ desc->family = "sans-serif";
+ break;
+ case PP_TRUETYPEFONTFAMILY_CURSIVE:
+ desc->family = "cursive";
+ break;
+ case PP_TRUETYPEFONTFAMILY_FANTASY:
+ desc->family = "fantasy";
+ break;
+ case PP_TRUETYPEFONTFAMILY_MONOSPACE:
+ desc->family = "monospace";
+ break;
+ }
+ }
+
+ 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;
+}
+
+int32_t PepperTrueTypeFontLinux::GetTableTags(std::vector<uint32_t>* tags) {
+ if (!fd_.is_valid())
+ return PP_ERROR_FAILED;
+ // Get the 2 byte numTables field at an offset of 4 in the font.
+ uint8_t num_tables_buf[2];
+ size_t output_length = sizeof(num_tables_buf);
+ if (!content::GetFontTable(fd_.get(), 0 /* tag */, 4 /* offset */,
+ reinterpret_cast<uint8_t*>(&num_tables_buf),
+ &output_length))
+ return PP_ERROR_FAILED;
+ DCHECK(output_length == sizeof(num_tables_buf));
+ // Font data is stored in big-endian order.
+ uint16_t num_tables = (num_tables_buf[0] << 8) | num_tables_buf[1];
+
+ // The font has a header, followed by n table entries in its directory.
+ static const size_t kFontHeaderSize = 12;
+ static const size_t kTableEntrySize = 16;
+ output_length = num_tables * kTableEntrySize;
+ std::unique_ptr<uint8_t[]> table_entries(new uint8_t[output_length]);
+ // Get the table directory entries, which follow the font header.
+ if (!content::GetFontTable(fd_.get(), 0 /* tag */,
+ kFontHeaderSize /* offset */, table_entries.get(),
+ &output_length))
+ return PP_ERROR_FAILED;
+ DCHECK(output_length == num_tables * kTableEntrySize);
+
+ tags->resize(num_tables);
+ for (uint16_t i = 0; i < num_tables; i++) {
+ uint8_t* entry = table_entries.get() + i * kTableEntrySize;
+ uint32_t tag = static_cast<uint32_t>(entry[0]) << 24 |
+ static_cast<uint32_t>(entry[1]) << 16 |
+ static_cast<uint32_t>(entry[2]) << 8 |
+ static_cast<uint32_t>(entry[3]);
+ (*tags)[i] = tag;
+ }
+
+ return num_tables;
+}
+
+int32_t PepperTrueTypeFontLinux::GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) {
+ if (!fd_.is_valid())
+ return PP_ERROR_FAILED;
+ // Get the size of the font data first.
+ size_t table_size = 0;
+ // Tags are byte swapped on Linux.
+ table_tag = base::ByteSwap(table_tag);
+ if (!content::GetFontTable(fd_.get(), table_tag, offset, nullptr,
+ &table_size))
+ return PP_ERROR_FAILED;
+ // Only retrieve as much as the caller requested.
+ table_size = std::min(table_size, static_cast<size_t>(max_data_length));
+ data->resize(table_size);
+ if (!content::GetFontTable(fd_.get(), table_tag, offset,
+ reinterpret_cast<uint8_t*>(&(*data)[0]),
+ &table_size))
+ return PP_ERROR_FAILED;
+
+ return base::checked_cast<int32_t>(table_size);
+}
+
+} // namespace
+
+// static
+PepperTrueTypeFont* PepperTrueTypeFont::Create() {
+ return new PepperTrueTypeFontLinux();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list.h b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list.h
new file mode 100644
index 00000000000..da944c50071
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_LIST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_LIST_H_
+
+#include <string>
+#include <vector>
+
+namespace ppapi {
+namespace proxy {
+struct SerializedTrueTypeFontDesc;
+}
+}
+
+namespace content {
+
+// Adds font family names on the host platform to the vector of strings.
+//
+// This function is potentially slow (the system may do a bunch of I/O) so be
+// sure not to call this on a time-critical thread like the UI or I/O threads.
+void GetFontFamilies_SlowBlocking(std::vector<std::string>* font_families);
+
+// Adds font descriptors for fonts on the host platform in the given family to
+// the vector of descriptors.
+//
+// This function is potentially slow (the system may do a bunch of I/O) so be
+// sure not to call this on a time-critical thread like the UI or I/O threads.
+void GetFontsInFamily_SlowBlocking(
+ const std::string& family,
+ std::vector<ppapi::proxy::SerializedTrueTypeFontDesc>* fonts_in_family);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_LIST_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc
new file mode 100644
index 00000000000..d5d0d24d8f4
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc
@@ -0,0 +1,113 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h"
+
+#include <stdint.h>
+
+#include <algorithm>
+
+#include "base/macros.h"
+#include "base/numerics/safe_conversions.h"
+#include "content/browser/renderer_host/pepper/pepper_truetype_font_list.h"
+#include "content/common/font_list.h"
+#include "content/public/browser/browser_ppapi_host.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/resource_message_filter.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace content {
+
+namespace {
+
+// Handles the font list request on the blocking pool.
+class TrueTypeFontMessageFilter : public ppapi::host::ResourceMessageFilter {
+ public:
+ TrueTypeFontMessageFilter();
+
+ // ppapi::host::ResourceMessageFilter implementation.
+ scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) override;
+ int32_t OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) override;
+
+ private:
+ ~TrueTypeFontMessageFilter() override;
+
+ // Message handlers.
+ int32_t OnHostMsgGetFontFamilies(ppapi::host::HostMessageContext* context);
+ int32_t OnHostMsgGetFontsInFamily(ppapi::host::HostMessageContext* context,
+ const std::string& family);
+
+ DISALLOW_COPY_AND_ASSIGN(TrueTypeFontMessageFilter);
+};
+
+TrueTypeFontMessageFilter::TrueTypeFontMessageFilter() {}
+
+TrueTypeFontMessageFilter::~TrueTypeFontMessageFilter() {}
+
+scoped_refptr<base::TaskRunner>
+TrueTypeFontMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) {
+ // Use the font list SequencedTaskRunner to get the font list (currently the
+ // only message) since getting the font list is non-threadsafe on Linux (for
+ // versions of Pango predating 2013).
+ return GetFontListTaskRunner();
+}
+
+int32_t TrueTypeFontMessageFilter::OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) {
+ PPAPI_BEGIN_MESSAGE_MAP(TrueTypeFontMessageFilter, msg)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
+ PpapiHostMsg_TrueTypeFontSingleton_GetFontFamilies,
+ OnHostMsgGetFontFamilies)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TrueTypeFontSingleton_GetFontsInFamily,
+ OnHostMsgGetFontsInFamily)
+ PPAPI_END_MESSAGE_MAP()
+ return PP_ERROR_FAILED;
+}
+
+int32_t TrueTypeFontMessageFilter::OnHostMsgGetFontFamilies(
+ ppapi::host::HostMessageContext* context) {
+ // OK to use "slow blocking" version since we're on the blocking pool.
+ std::vector<std::string> font_families;
+ GetFontFamilies_SlowBlocking(&font_families);
+ // Sort the names in case the host platform returns them out of order.
+ std::sort(font_families.begin(), font_families.end());
+
+ context->reply_msg =
+ PpapiPluginMsg_TrueTypeFontSingleton_GetFontFamiliesReply(font_families);
+ return base::checked_cast<int32_t>(font_families.size());
+}
+
+int32_t TrueTypeFontMessageFilter::OnHostMsgGetFontsInFamily(
+ ppapi::host::HostMessageContext* context,
+ const std::string& family) {
+ // OK to use "slow blocking" version since we're on the blocking pool.
+ std::vector<ppapi::proxy::SerializedTrueTypeFontDesc> fonts_in_family;
+ GetFontsInFamily_SlowBlocking(family, &fonts_in_family);
+
+ context->reply_msg =
+ PpapiPluginMsg_TrueTypeFontSingleton_GetFontsInFamilyReply(
+ fonts_in_family);
+ return base::checked_cast<int32_t>(fonts_in_family.size());
+}
+
+} // namespace
+
+PepperTrueTypeFontListHost::PepperTrueTypeFontListHost(BrowserPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource)
+ : ResourceHost(host->GetPpapiHost(), instance, resource) {
+ AddFilter(scoped_refptr<ppapi::host::ResourceMessageFilter>(
+ new TrueTypeFontMessageFilter()));
+}
+
+PepperTrueTypeFontListHost::~PepperTrueTypeFontListHost() {}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h
new file mode 100644
index 00000000000..46a975bfdab
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_LIST_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_LIST_HOST_H_
+
+#include "base/macros.h"
+#include "ppapi/host/resource_host.h"
+
+namespace content {
+
+class BrowserPpapiHost;
+
+class PepperTrueTypeFontListHost : public ppapi::host::ResourceHost {
+ public:
+ PepperTrueTypeFontListHost(BrowserPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource);
+ ~PepperTrueTypeFontListHost() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontListHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_LIST_HOST_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_mac.mm b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_mac.mm
new file mode 100644
index 00000000000..bfaf5babbb8
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_mac.mm
@@ -0,0 +1,83 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/pepper_truetype_font_list.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/stl_util.h"
+#include "base/strings/sys_string_conversions.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/proxy/serialized_structs.h"
+
+namespace content {
+
+namespace {
+
+// Table to map AppKit weights to Pepper ones.
+const PP_TrueTypeFontWeight_Dev kPepperFontWeights[] = {
+ PP_TRUETYPEFONTWEIGHT_THIN, // 0 is the minimum AppKit weight.
+ PP_TRUETYPEFONTWEIGHT_ULTRALIGHT,
+ PP_TRUETYPEFONTWEIGHT_ULTRALIGHT,
+ PP_TRUETYPEFONTWEIGHT_LIGHT,
+ PP_TRUETYPEFONTWEIGHT_LIGHT,
+ PP_TRUETYPEFONTWEIGHT_NORMAL, // 5 is a 'normal' AppKit weight.
+ PP_TRUETYPEFONTWEIGHT_MEDIUM,
+ PP_TRUETYPEFONTWEIGHT_MEDIUM,
+ PP_TRUETYPEFONTWEIGHT_SEMIBOLD,
+ PP_TRUETYPEFONTWEIGHT_BOLD, // 9 is a 'bold' AppKit weight.
+ PP_TRUETYPEFONTWEIGHT_ULTRABOLD,
+ PP_TRUETYPEFONTWEIGHT_HEAVY,
+};
+const NSInteger kPepperFontWeightsLength = base::size(kPepperFontWeights);
+
+} // namespace
+
+void GetFontFamilies_SlowBlocking(std::vector<std::string>* font_families) {
+ base::mac::ScopedNSAutoreleasePool autorelease_pool;
+ NSFontManager* fontManager = [[[NSFontManager alloc] init] autorelease];
+ NSArray* fonts = [fontManager availableFontFamilies];
+ font_families->reserve([fonts count]);
+ for (NSString* family_name in fonts)
+ font_families->push_back(base::SysNSStringToUTF8(family_name));
+}
+
+void GetFontsInFamily_SlowBlocking(
+ const std::string& family,
+ std::vector<ppapi::proxy::SerializedTrueTypeFontDesc>* fonts_in_family) {
+ base::mac::ScopedNSAutoreleasePool autorelease_pool;
+ NSFontManager* fontManager = [[[NSFontManager alloc] init] autorelease];
+ NSString* ns_family = base::SysUTF8ToNSString(family);
+ NSArray* ns_fonts_in_family =
+ [fontManager availableMembersOfFontFamily:ns_family];
+
+ for (NSArray* font_info in ns_fonts_in_family) {
+ ppapi::proxy::SerializedTrueTypeFontDesc desc;
+ desc.family = family;
+ NSInteger font_weight = [[font_info objectAtIndex:2] intValue];
+ font_weight = std::max(static_cast<NSInteger>(0), font_weight);
+ font_weight = std::min(kPepperFontWeightsLength - 1, font_weight);
+ desc.weight = kPepperFontWeights[font_weight];
+
+ NSFontTraitMask font_traits =
+ [[font_info objectAtIndex:3] unsignedIntValue];
+ desc.style = PP_TRUETYPEFONTSTYLE_NORMAL;
+ if (font_traits & NSItalicFontMask)
+ desc.style = PP_TRUETYPEFONTSTYLE_ITALIC;
+
+ desc.width = PP_TRUETYPEFONTWIDTH_NORMAL;
+ if (font_traits & NSCondensedFontMask)
+ desc.width = PP_TRUETYPEFONTWIDTH_CONDENSED;
+ else if (font_traits & NSExpandedFontMask)
+ desc.width = PP_TRUETYPEFONTWIDTH_EXPANDED;
+
+ // Mac doesn't support requesting non-default character sets.
+ desc.charset = PP_TRUETYPEFONTCHARSET_DEFAULT;
+
+ fonts_in_family->push_back(desc);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_ozone.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_ozone.cc
new file mode 100644
index 00000000000..12e2c61a8cf
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_ozone.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "content/browser/renderer_host/pepper/pepper_truetype_font_list.h"
+
+namespace content {
+
+void GetFontFamilies_SlowBlocking(std::vector<std::string>* font_families) {
+ NOTIMPLEMENTED();
+}
+
+void GetFontsInFamily_SlowBlocking(
+ const std::string& family,
+ std::vector<ppapi::proxy::SerializedTrueTypeFontDesc>* fonts_in_family) {
+ NOTIMPLEMENTED();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_pango.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_pango.cc
new file mode 100644
index 00000000000..05bd58ea43a
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_pango.cc
@@ -0,0 +1,65 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/pepper_truetype_font_list.h"
+
+#include <pango/pango.h>
+#include <pango/pangocairo.h>
+
+#include <string>
+
+#include "ppapi/proxy/serialized_structs.h"
+
+namespace content {
+
+void GetFontFamilies_SlowBlocking(std::vector<std::string>* font_families) {
+ PangoFontMap* font_map = ::pango_cairo_font_map_get_default();
+ PangoFontFamily** families = nullptr;
+ int num_families = 0;
+ ::pango_font_map_list_families(font_map, &families, &num_families);
+
+ for (int i = 0; i < num_families; ++i)
+ font_families->push_back(::pango_font_family_get_name(families[i]));
+ g_free(families);
+}
+
+void GetFontsInFamily_SlowBlocking(
+ const std::string& family,
+ std::vector<ppapi::proxy::SerializedTrueTypeFontDesc>* fonts_in_family) {
+ PangoFontMap* font_map = ::pango_cairo_font_map_get_default();
+ PangoFontFamily** font_families = nullptr;
+ int num_families = 0;
+ ::pango_font_map_list_families(font_map, &font_families, &num_families);
+
+ for (int i = 0; i < num_families; ++i) {
+ PangoFontFamily* font_family = font_families[i];
+ if (family.compare(::pango_font_family_get_name(font_family)) == 0) {
+ PangoFontFace** font_faces = nullptr;
+ int num_faces = 0;
+ ::pango_font_family_list_faces(font_family, &font_faces, &num_faces);
+
+ for (int j = 0; j < num_faces; ++j) {
+ PangoFontFace* font_face = font_faces[j];
+ PangoFontDescription* font_desc = ::pango_font_face_describe(font_face);
+ ppapi::proxy::SerializedTrueTypeFontDesc desc;
+ desc.family = family;
+ if (::pango_font_description_get_style(font_desc) == PANGO_STYLE_ITALIC)
+ desc.style = PP_TRUETYPEFONTSTYLE_ITALIC;
+ desc.weight = static_cast<PP_TrueTypeFontWeight_Dev>(
+ ::pango_font_description_get_weight(font_desc));
+ desc.width = static_cast<PP_TrueTypeFontWidth_Dev>(
+ ::pango_font_description_get_stretch(font_desc));
+ // Character set is not part of Pango font description.
+ desc.charset = PP_TRUETYPEFONTCHARSET_DEFAULT;
+
+ fonts_in_family->push_back(desc);
+ ::pango_font_description_free(font_desc);
+ }
+ g_free(font_faces);
+ }
+ }
+ g_free(font_families);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc
new file mode 100644
index 00000000000..231c8ca14f2
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc
@@ -0,0 +1,91 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/pepper_truetype_font_list.h"
+
+#include <windows.h>
+#include <string.h>
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/win/scoped_hdc.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/proxy/serialized_structs.h"
+
+namespace content {
+
+namespace {
+
+typedef std::vector<std::string> FontFamilyList;
+typedef std::vector<ppapi::proxy::SerializedTrueTypeFontDesc> FontDescList;
+
+static int CALLBACK EnumFontFamiliesProc(ENUMLOGFONTEXW* logical_font,
+ NEWTEXTMETRICEXW* physical_font,
+ DWORD font_type,
+ LPARAM lparam) {
+ FontFamilyList* font_families = reinterpret_cast<FontFamilyList*>(lparam);
+ if (font_families) {
+ const LOGFONTW& lf = logical_font->elfLogFont;
+ if (lf.lfFaceName[0] && lf.lfFaceName[0] != '@' &&
+ lf.lfOutPrecision == OUT_STROKE_PRECIS) { // Outline fonts only.
+ std::string face_name(base::UTF16ToUTF8(lf.lfFaceName));
+ font_families->push_back(face_name);
+ }
+ }
+ return 1;
+}
+
+static int CALLBACK EnumFontsInFamilyProc(ENUMLOGFONTEXW* logical_font,
+ NEWTEXTMETRICEXW* physical_font,
+ DWORD font_type,
+ LPARAM lparam) {
+ FontDescList* fonts_in_family = reinterpret_cast<FontDescList*>(lparam);
+ if (fonts_in_family) {
+ const LOGFONTW& lf = logical_font->elfLogFont;
+ if (lf.lfFaceName[0] && lf.lfFaceName[0] != '@' &&
+ lf.lfOutPrecision == OUT_STROKE_PRECIS) { // Outline fonts only.
+ ppapi::proxy::SerializedTrueTypeFontDesc desc;
+ desc.family = base::UTF16ToUTF8(lf.lfFaceName);
+ if (lf.lfItalic)
+ desc.style = PP_TRUETYPEFONTSTYLE_ITALIC;
+ desc.weight = static_cast<PP_TrueTypeFontWeight_Dev>(lf.lfWeight);
+ desc.width = PP_TRUETYPEFONTWIDTH_NORMAL; // TODO(bbudge) support widths.
+ desc.charset = static_cast<PP_TrueTypeFontCharset_Dev>(lf.lfCharSet);
+ fonts_in_family->push_back(desc);
+ }
+ }
+ return 1;
+}
+
+} // namespace
+
+void GetFontFamilies_SlowBlocking(FontFamilyList* font_families) {
+ LOGFONTW logfont;
+ memset(&logfont, 0, sizeof(logfont));
+ logfont.lfCharSet = DEFAULT_CHARSET;
+ base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+ ::EnumFontFamiliesExW(hdc.Get(),
+ &logfont,
+ (FONTENUMPROCW) & EnumFontFamiliesProc,
+ (LPARAM)font_families,
+ 0);
+}
+
+void GetFontsInFamily_SlowBlocking(const std::string& family,
+ FontDescList* fonts_in_family) {
+ LOGFONTW logfont;
+ memset(&logfont, 0, sizeof(logfont));
+ logfont.lfCharSet = DEFAULT_CHARSET;
+ base::string16 family16 = base::UTF8ToUTF16(family);
+ // Copy the family name, leaving room for a terminating null (already set
+ // since we zeroed the whole struct above.)
+ family16.copy(logfont.lfFaceName, LF_FACESIZE - 1);
+ base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+ ::EnumFontFamiliesExW(hdc.Get(),
+ &logfont,
+ (FONTENUMPROCW) & EnumFontsInFamilyProc,
+ (LPARAM)fonts_in_family,
+ 0);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_mac.mm b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_mac.mm
new file mode 100644
index 00000000000..db8a8b51070
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_mac.mm
@@ -0,0 +1,415 @@
+// 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/renderer_host/pepper/pepper_truetype_font.h"
+
+#import <ApplicationServices/ApplicationServices.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <stdio.h>
+
+#include "base/compiler_specific.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/macros.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/sys_byteorder.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/c/pp_errors.h"
+
+namespace content {
+
+namespace {
+
+static bool FindFloat(CFDictionaryRef dict, CFStringRef name, float* value) {
+ CFNumberRef num;
+ return CFDictionaryGetValueIfPresent(
+ dict, name, reinterpret_cast<const void**>(&num)) &&
+ CFNumberIsFloatType(num) &&
+ CFNumberGetValue(num, kCFNumberFloatType, value);
+}
+
+float GetMacWeight(PP_TrueTypeFontWeight_Dev weight) {
+ // Map values from NORMAL (400) to HEAVY (900) to the range [0 .. 1], and
+ // values below NORMAL to the range [-0.6 .. 0]. NORMAL should map to 0.
+ float normal = PP_TRUETYPEFONTWEIGHT_NORMAL;
+ float heavy = PP_TRUETYPEFONTWEIGHT_HEAVY;
+ return (weight - normal) / (heavy - normal);
+}
+
+PP_TrueTypeFontWeight_Dev GetPepperWeight(float weight) {
+ // Perform the inverse mapping of GetMacWeight.
+ return static_cast<PP_TrueTypeFontWeight_Dev>(
+ weight * (PP_TRUETYPEFONTWEIGHT_HEAVY - PP_TRUETYPEFONTWEIGHT_NORMAL) +
+ PP_TRUETYPEFONTWEIGHT_NORMAL);
+}
+
+float GetMacWidth(PP_TrueTypeFontWidth_Dev width) {
+ // Map values from NORMAL (4) to ULTRA_EXPANDED (8) to the range [0 .. 1],
+ // and values below NORMAL to the range [-1 .. 0]. Normal should map to 0.
+ float normal = PP_TRUETYPEFONTWIDTH_NORMAL;
+ float ultra_expanded = PP_TRUETYPEFONTWIDTH_ULTRAEXPANDED;
+ return (width - normal) / (ultra_expanded - normal);
+}
+
+PP_TrueTypeFontWidth_Dev GetPepperWidth(float width) {
+ // Perform the inverse mapping of GetMacWeight.
+ return static_cast<PP_TrueTypeFontWidth_Dev>(
+ width *
+ (PP_TRUETYPEFONTWIDTH_ULTRAEXPANDED - PP_TRUETYPEFONTWIDTH_NORMAL) +
+ PP_TRUETYPEFONTWIDTH_NORMAL);
+}
+
+#define MAKE_TABLE_TAG(a, b, c, d) ((a) << 24) + ((b) << 16) + ((c) << 8) + (d)
+
+// TrueType font header and table entry structs. See
+// https://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html
+struct FontHeader {
+ int32_t font_type;
+ uint16_t num_tables;
+ uint16_t search_range;
+ uint16_t entry_selector;
+ uint16_t range_shift;
+};
+static_assert(sizeof(FontHeader) == 12, "FontHeader wrong size");
+
+struct FontDirectoryEntry {
+ uint32_t tag;
+ uint32_t checksum;
+ uint32_t offset;
+ uint32_t logical_length;
+};
+static_assert(sizeof(FontDirectoryEntry) == 16,
+ "FontDirectoryEntry wrong size");
+
+uint32_t CalculateChecksum(char* table, int32_t table_length) {
+ uint32_t sum = 0;
+ uint32_t* current = reinterpret_cast<uint32_t*>(table);
+ uint32_t length = (table_length + 3) / 4;
+ // Raw font data is big-endian.
+ while (length-- > 0)
+ sum += base::NetToHost32(*current++);
+ return sum;
+}
+
+class PepperTrueTypeFontMac : public PepperTrueTypeFont {
+ public:
+ PepperTrueTypeFontMac();
+
+ // PepperTrueTypeFont implementation.
+ int32_t Initialize(ppapi::proxy::SerializedTrueTypeFontDesc* desc) override;
+ int32_t GetTableTags(std::vector<uint32_t>* tags) override;
+ int32_t GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) override;
+
+ private:
+ ~PepperTrueTypeFontMac() override;
+
+ virtual int32_t GetEntireFont(int32_t offset,
+ int32_t max_data_length,
+ std::string* data);
+
+ base::ScopedCFTypeRef<CTFontRef> font_ref_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontMac);
+};
+
+PepperTrueTypeFontMac::PepperTrueTypeFontMac() {
+}
+
+PepperTrueTypeFontMac::~PepperTrueTypeFontMac() {
+}
+
+int32_t PepperTrueTypeFontMac::Initialize(
+ ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
+ // Create the font in a nested scope, so we can use the same variable names
+ // when we get the actual font characteristics.
+ {
+ // Create attributes and traits dictionaries.
+ base::ScopedCFTypeRef<CFMutableDictionaryRef> attributes_ref(
+ CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ base::ScopedCFTypeRef<CFMutableDictionaryRef> traits_ref(
+ CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ if (!attributes_ref || !traits_ref)
+ return PP_ERROR_FAILED;
+
+ CFDictionaryAddValue(attributes_ref, kCTFontTraitsAttribute, traits_ref);
+
+ // Use symbolic traits to specify traits when possible.
+ CTFontSymbolicTraits symbolic_traits = 0;
+ if (desc->style & PP_TRUETYPEFONTSTYLE_ITALIC)
+ symbolic_traits |= kCTFontItalicTrait;
+ if (desc->weight == PP_TRUETYPEFONTWEIGHT_BOLD)
+ symbolic_traits |= kCTFontBoldTrait;
+ if (desc->width == PP_TRUETYPEFONTWIDTH_CONDENSED)
+ symbolic_traits |= kCTFontCondensedTrait;
+ else if (desc->width == PP_TRUETYPEFONTWIDTH_EXPANDED)
+ symbolic_traits |= kCTFontExpandedTrait;
+
+ base::ScopedCFTypeRef<CFNumberRef> symbolic_traits_ref(CFNumberCreate(
+ kCFAllocatorDefault, kCFNumberSInt32Type, &symbolic_traits));
+ if (!symbolic_traits_ref)
+ return PP_ERROR_FAILED;
+ CFDictionaryAddValue(traits_ref, kCTFontSymbolicTrait, symbolic_traits_ref);
+
+ // Font family matching doesn't work using family classes in symbolic
+ // traits. Instead, map generic_family to font families that are always
+ // available.
+ std::string family(desc->family);
+ if (family.empty()) {
+ switch (desc->generic_family) {
+ case PP_TRUETYPEFONTFAMILY_SERIF:
+ family = "Times";
+ break;
+ case PP_TRUETYPEFONTFAMILY_SANSSERIF:
+ family = "Helvetica";
+ break;
+ case PP_TRUETYPEFONTFAMILY_CURSIVE:
+ family = "Apple Chancery";
+ break;
+ case PP_TRUETYPEFONTFAMILY_FANTASY:
+ family = "Papyrus";
+ break;
+ case PP_TRUETYPEFONTFAMILY_MONOSPACE:
+ family = "Courier";
+ break;
+ }
+ }
+
+ base::ScopedCFTypeRef<CFStringRef> name_ref(
+ base::SysUTF8ToCFStringRef(family));
+ if (name_ref)
+ CFDictionaryAddValue(
+ attributes_ref, kCTFontFamilyNameAttribute, name_ref);
+
+ if (desc->weight != PP_TRUETYPEFONTWEIGHT_NORMAL &&
+ desc->weight != PP_TRUETYPEFONTWEIGHT_BOLD) {
+ float weight = GetMacWeight(desc->weight);
+ base::ScopedCFTypeRef<CFNumberRef> weight_trait_ref(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat32Type, &weight));
+ if (weight_trait_ref)
+ CFDictionaryAddValue(traits_ref, kCTFontWeightTrait, weight_trait_ref);
+ }
+
+ if (desc->width != PP_TRUETYPEFONTWIDTH_NORMAL &&
+ desc->width != PP_TRUETYPEFONTWIDTH_CONDENSED &&
+ desc->width != PP_TRUETYPEFONTWIDTH_EXPANDED) {
+ float width = GetMacWidth(desc->width);
+ base::ScopedCFTypeRef<CFNumberRef> width_trait_ref(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat32Type, &width));
+ if (width_trait_ref)
+ CFDictionaryAddValue(traits_ref, kCTFontWidthTrait, width_trait_ref);
+ }
+
+ base::ScopedCFTypeRef<CTFontDescriptorRef> desc_ref(
+ CTFontDescriptorCreateWithAttributes(attributes_ref));
+
+ if (desc_ref)
+ font_ref_.reset(CTFontCreateWithFontDescriptor(desc_ref, 0, NULL));
+
+ if (!font_ref_.get())
+ return PP_ERROR_FAILED;
+ }
+
+ // Now query to get the actual font characteristics.
+ base::ScopedCFTypeRef<CTFontDescriptorRef> desc_ref(
+ CTFontCopyFontDescriptor(font_ref_));
+
+ base::ScopedCFTypeRef<CFStringRef> family_name_ref(
+ base::mac::CFCast<CFStringRef>(
+ CTFontDescriptorCopyAttribute(desc_ref, kCTFontFamilyNameAttribute)));
+ desc->family = base::SysCFStringRefToUTF8(family_name_ref);
+
+ base::ScopedCFTypeRef<CFDictionaryRef> traits_ref(
+ base::mac::CFCast<CFDictionaryRef>(
+ CTFontDescriptorCopyAttribute(desc_ref, kCTFontTraitsAttribute)));
+
+ desc->style = PP_TRUETYPEFONTSTYLE_NORMAL;
+ CTFontSymbolicTraits symbolic_traits(CTFontGetSymbolicTraits(font_ref_));
+ if (symbolic_traits & kCTFontItalicTrait)
+ desc->style = static_cast<PP_TrueTypeFontStyle_Dev>(
+ desc->style | PP_TRUETYPEFONTSTYLE_ITALIC);
+ if (symbolic_traits & kCTFontBoldTrait) {
+ desc->weight = PP_TRUETYPEFONTWEIGHT_BOLD;
+ } else {
+ float weight;
+ if (FindFloat(traits_ref, kCTFontWeightTrait, &weight))
+ desc->weight = GetPepperWeight(weight);
+ }
+ if (symbolic_traits & kCTFontCondensedTrait) {
+ desc->width = PP_TRUETYPEFONTWIDTH_CONDENSED;
+ } else if (symbolic_traits & kCTFontExpandedTrait) {
+ desc->width = PP_TRUETYPEFONTWIDTH_EXPANDED;
+ } else {
+ float width;
+ if (FindFloat(traits_ref, kCTFontWidthTrait, &width))
+ desc->width = GetPepperWidth(width);
+ }
+
+ // Character set isn't supported on Mac.
+ desc->charset = PP_TRUETYPEFONTCHARSET_DEFAULT;
+ return PP_OK;
+}
+
+int32_t PepperTrueTypeFontMac::GetTableTags(std::vector<uint32_t>* tags) {
+ if (!font_ref_.get())
+ return PP_ERROR_FAILED;
+ base::ScopedCFTypeRef<CFArrayRef> tag_array(
+ CTFontCopyAvailableTables(font_ref_, kCTFontTableOptionNoOptions));
+ if (!tag_array)
+ return PP_ERROR_FAILED;
+
+ // Items returned by CTFontCopyAvailableTables are not boxed. Whose bright
+ // idea was this?
+ CFIndex length = CFArrayGetCount(tag_array);
+ tags->resize(length);
+ for (CFIndex i = 0; i < length; ++i) {
+ (*tags)[i] =
+ reinterpret_cast<uintptr_t>(CFArrayGetValueAtIndex(tag_array, i));
+ }
+ return length;
+}
+
+int32_t PepperTrueTypeFontMac::GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) {
+ if (!font_ref_.get())
+ return PP_ERROR_FAILED;
+
+ if (!table_tag)
+ return GetEntireFont(offset, max_data_length, data);
+
+ base::ScopedCFTypeRef<CFDataRef> table_ref(
+ CTFontCopyTable(font_ref_,
+ static_cast<CTFontTableTag>(table_tag),
+ kCTFontTableOptionNoOptions));
+ if (!table_ref)
+ return PP_ERROR_FAILED;
+
+ CFIndex table_size = CFDataGetLength(table_ref);
+ CFIndex safe_offset =
+ std::min(base::checked_cast<CFIndex>(offset), table_size);
+ CFIndex safe_length = std::min(table_size - safe_offset,
+ base::checked_cast<CFIndex>(max_data_length));
+ data->resize(safe_length);
+ CFDataGetBytes(table_ref,
+ CFRangeMake(safe_offset, safe_length),
+ reinterpret_cast<UInt8*>(&(*data)[0]));
+
+ return safe_length;
+}
+
+int32_t PepperTrueTypeFontMac::GetEntireFont(int32_t offset,
+ int32_t max_data_length,
+ std::string* data) {
+ // Reconstruct the font header, table directory, and tables.
+ std::vector<uint32_t> table_tags;
+ int32_t table_count = GetTableTags(&table_tags);
+ if (table_count < 0)
+ return table_count; // PPAPI error code.
+
+ // Allocate enough room for the header and the table directory entries.
+ std::string font(
+ sizeof(FontHeader) + sizeof(FontDirectoryEntry) * table_count, 0);
+ // Map the OS X font type value to a TrueType scalar type.
+ base::ScopedCFTypeRef<CFNumberRef> font_type_ref(
+ base::mac::CFCast<CFNumberRef>(
+ CTFontCopyAttribute(font_ref_, kCTFontFormatAttribute)));
+ int32_t font_type;
+ CFNumberGetValue(font_type_ref, kCFNumberSInt32Type, &font_type);
+ switch (font_type) {
+ case kCTFontFormatOpenTypePostScript:
+ font_type = MAKE_TABLE_TAG('O', 'T', 'T', 'O');
+ break;
+ case kCTFontFormatTrueType:
+ case kCTFontFormatBitmap:
+ font_type = MAKE_TABLE_TAG('t', 'r', 'u', 'e');
+ break;
+ case kCTFontFormatPostScript:
+ font_type = MAKE_TABLE_TAG('t', 'y', 'p', '1');
+ break;
+ case kCTFontFormatOpenTypeTrueType:
+ case kCTFontFormatUnrecognized:
+ default:
+ font_type = MAKE_TABLE_TAG(0, 1, 0, 0);
+ break;
+ }
+
+ // Calculate the rest of the header values.
+ uint16_t num_tables = base::checked_cast<uint16_t>(table_count);
+ uint16_t entry_selector = 0;
+ uint16_t search_range = 1;
+ while (search_range < (num_tables >> 1)) {
+ entry_selector++;
+ search_range <<= 1;
+ }
+ search_range <<= 4;
+ uint16_t range_shift = (num_tables << 4) - search_range;
+
+ // Write the header, with values in big-endian order.
+ FontHeader* font_header = reinterpret_cast<FontHeader*>(&font[0]);
+ font_header->font_type = base::HostToNet32(font_type);
+ font_header->num_tables = base::HostToNet16(num_tables);
+ font_header->search_range = base::HostToNet16(search_range);
+ font_header->entry_selector = base::HostToNet16(entry_selector);
+ font_header->range_shift = base::HostToNet16(range_shift);
+
+ for (int32_t i = 0; i < table_count; i++) {
+ // Get the table data.
+ std::string table;
+ int32_t table_size =
+ GetTable(table_tags[i], 0, std::numeric_limits<int32_t>::max(), &table);
+ if (table_size < 0)
+ return table_size; // PPAPI error code.
+
+ // Append it to the font data so far, and zero pad so tables stay aligned.
+ size_t table_offset = font.size();
+ font.append(table);
+ size_t padding = font.size() & 0x3;
+ font.append(padding, 0);
+
+ // Fill in the directory entry for this table.
+ FontDirectoryEntry* entry = reinterpret_cast<FontDirectoryEntry*>(
+ &font[0] + sizeof(FontHeader) + i * sizeof(FontDirectoryEntry));
+ entry->tag = base::HostToNet32(table_tags[i]);
+ entry->checksum =
+ base::HostToNet32(CalculateChecksum(&font[table_offset], table_size));
+ entry->offset = base::HostToNet32(table_offset);
+ entry->logical_length = base::HostToNet32(table_size);
+ // TODO(bbudge) set the 'head' table checksumAdjustment.
+ }
+
+ // Extract a substring if the caller specified an offset or max data length.
+ int32_t font_size = base::checked_cast<int32_t>(font.size());
+ int32_t safe_offset = std::min(offset, font_size);
+ int32_t safe_length = std::min(font_size - safe_offset, max_data_length);
+ if (safe_offset || safe_length != font_size)
+ font = font.substr(safe_offset, safe_length);
+
+ data->clear();
+ data->swap(font);
+ return safe_length;
+}
+
+} // namespace
+
+// static
+PepperTrueTypeFont* PepperTrueTypeFont::Create() {
+ return new PepperTrueTypeFontMac();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_win.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_win.cc
new file mode 100644
index 00000000000..aa6b837a450
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_win.cc
@@ -0,0 +1,241 @@
+// 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/renderer_host/pepper/pepper_truetype_font.h"
+
+#include <stdint.h>
+#include <windows.h>
+
+#include <algorithm>
+#include <memory>
+#include <set>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/sys_byteorder.h"
+#include "base/win/scoped_gdi_object.h"
+#include "base/win/scoped_hdc.h"
+#include "base/win/scoped_select_object.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/c/pp_errors.h"
+
+namespace content {
+
+namespace {
+
+class PepperTrueTypeFontWin : public PepperTrueTypeFont {
+ public:
+ PepperTrueTypeFontWin();
+
+ // PepperTrueTypeFont implementation.
+ int32_t Initialize(ppapi::proxy::SerializedTrueTypeFontDesc* desc) override;
+ int32_t GetTableTags(std::vector<uint32_t>* tags) override;
+ int32_t GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) override;
+
+ private:
+ ~PepperTrueTypeFontWin() override;
+
+ DWORD GetFontData(HDC hdc,
+ DWORD table,
+ DWORD offset,
+ LPVOID buffer,
+ DWORD length);
+
+ base::win::ScopedHFONT font_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontWin);
+};
+
+PepperTrueTypeFontWin::PepperTrueTypeFontWin() {
+}
+
+PepperTrueTypeFontWin::~PepperTrueTypeFontWin() {
+}
+
+int32_t PepperTrueTypeFontWin::Initialize(
+ ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
+ DWORD pitch_and_family = DEFAULT_PITCH;
+ switch (desc->generic_family) {
+ case PP_TRUETYPEFONTFAMILY_SERIF:
+ pitch_and_family |= FF_ROMAN;
+ break;
+ case PP_TRUETYPEFONTFAMILY_SANSSERIF:
+ pitch_and_family |= FF_SWISS;
+ break;
+ case PP_TRUETYPEFONTFAMILY_CURSIVE:
+ pitch_and_family |= FF_SCRIPT;
+ break;
+ case PP_TRUETYPEFONTFAMILY_FANTASY:
+ pitch_and_family |= FF_DECORATIVE;
+ break;
+ case PP_TRUETYPEFONTFAMILY_MONOSPACE:
+ pitch_and_family |= FF_MODERN;
+ break;
+ }
+ // TODO(bbudge) support widths (extended, condensed).
+
+ font_.reset(CreateFont(
+ 0 /* height */,
+ 0 /* width */,
+ 0 /* escapement */,
+ 0 /* orientation */,
+ desc->weight, // our weight enum matches Windows.
+ (desc->style & PP_TRUETYPEFONTSTYLE_ITALIC) ? 1 : 0,
+ 0 /* underline */,
+ 0 /* strikeout */,
+ desc->charset, // our charset enum matches Windows.
+ OUT_OUTLINE_PRECIS, // truetype and other outline fonts
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ pitch_and_family,
+ base::UTF8ToUTF16(desc->family).c_str()));
+ if (!font_.is_valid())
+ return PP_ERROR_FAILED;
+
+ LOGFONT font_desc;
+ if (!::GetObject(font_.get(), sizeof(LOGFONT), &font_desc))
+ return PP_ERROR_FAILED;
+
+ switch (font_desc.lfPitchAndFamily & 0xF0) { // Top 4 bits are family.
+ case FF_ROMAN:
+ desc->generic_family = PP_TRUETYPEFONTFAMILY_SERIF;
+ break;
+ case FF_SWISS:
+ desc->generic_family = PP_TRUETYPEFONTFAMILY_SANSSERIF;
+ break;
+ case FF_SCRIPT:
+ desc->generic_family = PP_TRUETYPEFONTFAMILY_CURSIVE;
+ break;
+ case FF_DECORATIVE:
+ desc->generic_family = PP_TRUETYPEFONTFAMILY_FANTASY;
+ break;
+ case FF_MODERN:
+ desc->generic_family = PP_TRUETYPEFONTFAMILY_MONOSPACE;
+ break;
+ }
+
+ desc->style = font_desc.lfItalic ? PP_TRUETYPEFONTSTYLE_ITALIC
+ : PP_TRUETYPEFONTSTYLE_NORMAL;
+ desc->weight = static_cast<PP_TrueTypeFontWeight_Dev>(font_desc.lfWeight);
+ desc->width = PP_TRUETYPEFONTWIDTH_NORMAL;
+ desc->charset = static_cast<PP_TrueTypeFontCharset_Dev>(font_desc.lfCharSet);
+
+ // To get the face name, select the font and query for the name. GetObject
+ // doesn't fill in the name field of the LOGFONT structure.
+ base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+ if (hdc.IsValid()) {
+ base::win::ScopedSelectObject select_object(hdc.Get(), font_.get());
+ WCHAR name[LF_FACESIZE];
+ GetTextFace(hdc.Get(), LF_FACESIZE, name);
+ desc->family = base::UTF16ToUTF8(name);
+ }
+
+ return PP_OK;
+}
+
+int32_t PepperTrueTypeFontWin::GetTableTags(std::vector<uint32_t>* tags) {
+ if (!font_.is_valid())
+ return PP_ERROR_FAILED;
+
+ base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+ if (!hdc.IsValid())
+ return PP_ERROR_FAILED;
+
+ base::win::ScopedSelectObject select_object(hdc.Get(), font_.get());
+
+ // Get the whole font header.
+ static const DWORD kFontHeaderSize = 12;
+ uint8_t header_buf[kFontHeaderSize];
+ if (GetFontData(hdc.Get(), 0, 0, header_buf, kFontHeaderSize) == GDI_ERROR)
+ return PP_ERROR_FAILED;
+
+ // The numTables follows a 4 byte scalerType tag. Font data is stored in
+ // big-endian order.
+ DWORD num_tables = (header_buf[4] << 8) | header_buf[5];
+
+ // The size in bytes of an entry in the table directory.
+ static const DWORD kDirectoryEntrySize = 16;
+ DWORD directory_size = num_tables * kDirectoryEntrySize;
+ std::unique_ptr<uint8_t[]> directory(new uint8_t[directory_size]);
+ // Get the table directory entries after the font header.
+ if (GetFontData(hdc.Get(), 0 /* tag */, kFontHeaderSize, directory.get(),
+ directory_size) ==
+ GDI_ERROR)
+ return PP_ERROR_FAILED;
+
+ tags->resize(num_tables);
+ for (DWORD i = 0; i < num_tables; i++) {
+ const uint8_t* entry = directory.get() + i * kDirectoryEntrySize;
+ uint32_t tag = static_cast<uint32_t>(entry[0]) << 24 |
+ static_cast<uint32_t>(entry[1]) << 16 |
+ static_cast<uint32_t>(entry[2]) << 8 |
+ static_cast<uint32_t>(entry[3]);
+ (*tags)[i] = tag;
+ }
+
+ return num_tables;
+}
+
+int32_t PepperTrueTypeFontWin::GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) {
+ if (!font_.is_valid())
+ return PP_ERROR_FAILED;
+
+ base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+ if (!hdc.IsValid())
+ return PP_ERROR_FAILED;
+
+ base::win::ScopedSelectObject select_object(hdc.Get(), font_.get());
+
+ // Tags are byte swapped on Windows.
+ table_tag = base::ByteSwap(table_tag);
+ // Get the size of the font table first.
+ DWORD table_size = GetFontData(hdc.Get(), table_tag, 0, NULL, 0);
+ if (table_size == GDI_ERROR)
+ return PP_ERROR_FAILED;
+
+ DWORD safe_offset = std::min(static_cast<DWORD>(offset), table_size);
+ DWORD safe_length =
+ std::min(table_size - safe_offset, static_cast<DWORD>(max_data_length));
+ data->resize(safe_length);
+ if (safe_length == 0) {
+ table_size = 0;
+ } else {
+ table_size = GetFontData(hdc.Get(),
+ table_tag,
+ safe_offset,
+ reinterpret_cast<uint8_t*>(&(*data)[0]),
+ safe_length);
+ if (table_size == GDI_ERROR)
+ return PP_ERROR_FAILED;
+ }
+ return static_cast<int32_t>(table_size);
+}
+
+DWORD PepperTrueTypeFontWin::GetFontData(HDC hdc,
+ DWORD table,
+ DWORD offset,
+ void* buffer,
+ DWORD length) {
+ // If this is a zero byte read, return a successful result.
+ if (buffer && !length)
+ return 0;
+
+ return ::GetFontData(hdc, table, offset, buffer, length);
+}
+
+} // namespace
+
+// static
+PepperTrueTypeFont* PepperTrueTypeFont::Create() {
+ return new PepperTrueTypeFontWin();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/plugin_registry_impl.cc b/chromium/content/browser/renderer_host/plugin_registry_impl.cc
index 427e1cb8946..8dd463f4165 100644
--- a/chromium/content/browser/renderer_host/plugin_registry_impl.cc
+++ b/chromium/content/browser/renderer_host/plugin_registry_impl.cc
@@ -58,7 +58,7 @@ void PluginRegistryImpl::GetPluginsComplete(
PluginServiceFilter* filter = PluginServiceImpl::GetInstance()->GetFilter();
std::vector<blink::mojom::PluginInfoPtr> plugins;
base::flat_set<std::string> mime_handler_view_mime_types =
- GetContentClient()->browser()->GetMimeHandlerViewMimeTypes(
+ GetContentClient()->browser()->GetPluginMimeTypesWithExternalHandlers(
resource_context_);
const int child_process_id = -1;
@@ -76,15 +76,15 @@ void PluginRegistryImpl::GetPluginsComplete(
plugin_blink->description = plugin.desc;
plugin_blink->filename = plugin.path.BaseName();
plugin_blink->background_color = plugin.background_color;
- plugin_blink->may_use_mime_handler_view = false;
+ plugin_blink->may_use_external_handler = false;
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));
- if (!plugin_blink->may_use_mime_handler_view) {
- plugin_blink->may_use_mime_handler_view = base::ContainsKey(
+ if (!plugin_blink->may_use_external_handler) {
+ plugin_blink->may_use_external_handler = base::ContainsKey(
mime_handler_view_mime_types, mime_type.mime_type);
}
}
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 760bb72a433..9b7c9908f12 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
@@ -35,16 +35,37 @@ void RenderFrameMetadataProviderImpl::Bind(
render_frame_metadata_observer_client_binding_.Bind(std::move(client_request),
task_runner_);
- if (pending_report_all_frame_submission_.has_value()) {
- ReportAllFrameSubmissionsForTesting(*pending_report_all_frame_submission_);
- pending_report_all_frame_submission_.reset();
+#if defined(OS_ANDROID)
+ if (pending_report_all_root_scrolls_for_accessibility_.has_value()) {
+ ReportAllRootScrollsForAccessibility(
+ *pending_report_all_root_scrolls_for_accessibility_);
+ pending_report_all_root_scrolls_for_accessibility_.reset();
}
+#endif
+ if (pending_report_all_frame_submission_for_testing_.has_value()) {
+ ReportAllFrameSubmissionsForTesting(
+ *pending_report_all_frame_submission_for_testing_);
+ pending_report_all_frame_submission_for_testing_.reset();
+ }
+}
+
+#if defined(OS_ANDROID)
+void RenderFrameMetadataProviderImpl::ReportAllRootScrollsForAccessibility(
+ bool enabled) {
+ if (!render_frame_metadata_observer_ptr_) {
+ pending_report_all_root_scrolls_for_accessibility_ = enabled;
+ return;
+ }
+
+ render_frame_metadata_observer_ptr_->ReportAllRootScrollsForAccessibility(
+ enabled);
}
+#endif
void RenderFrameMetadataProviderImpl::ReportAllFrameSubmissionsForTesting(
bool enabled) {
if (!render_frame_metadata_observer_ptr_) {
- pending_report_all_frame_submission_ = enabled;
+ pending_report_all_frame_submission_for_testing_ = enabled;
return;
}
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 2ec032d2486..6eeb0bcf648 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
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
+#include "build/build_config.h"
#include "content/common/render_frame_metadata.mojom.h"
#include "content/public/browser/render_frame_metadata_provider.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -38,6 +39,12 @@ class CONTENT_EXPORT RenderFrameMetadataProviderImpl
void Bind(mojom::RenderFrameMetadataObserverClientRequest client_request,
mojom::RenderFrameMetadataObserverPtr observer);
+#if defined(OS_ANDROID)
+ // Notifies the renderer to begin sending a notification on all root scroll
+ // changes, which is needed for accessibility on Android.
+ void ReportAllRootScrollsForAccessibility(bool enabled);
+#endif
+
// Notifies the renderer to begin sending a notification on all frame
// submissions.
void ReportAllFrameSubmissionsForTesting(bool enabled) override;
@@ -81,7 +88,10 @@ class CONTENT_EXPORT RenderFrameMetadataProviderImpl
render_frame_metadata_observer_client_binding_;
mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer_ptr_;
- base::Optional<bool> pending_report_all_frame_submission_;
+#if defined(OS_ANDROID)
+ base::Optional<bool> pending_report_all_root_scrolls_for_accessibility_;
+#endif
+ base::Optional<bool> pending_report_all_frame_submission_for_testing_;
base::WeakPtrFactory<RenderFrameMetadataProviderImpl> weak_factory_;
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 0866af8555c..67ec1115d92 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -85,7 +85,6 @@
#include "content/browser/browser_main_loop.h"
#include "content/browser/browser_plugin/browser_plugin_message_filter.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
-#include "content/browser/cache_storage/cache_storage_dispatcher_host.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/code_cache/generated_code_cache.h"
#include "content/browser/code_cache/generated_code_cache_context.h"
@@ -109,6 +108,8 @@
#include "content/browser/media/media_internals.h"
#include "content/browser/media/midi_host.h"
#include "content/browser/mime_registry_impl.h"
+#include "content/browser/navigation_subresource_loader_params.h"
+#include "content/browser/network_service_instance_impl.h"
#include "content/browser/payments/payment_manager.h"
#include "content/browser/permissions/permission_service_context.h"
#include "content/browser/permissions/permission_service_impl.h"
@@ -145,7 +146,6 @@
#include "content/common/in_process_child_thread_params.h"
#include "content/common/media/aec_dump_messages.h"
#include "content/common/media/peer_connection_tracker_messages.h"
-#include "content/common/navigation_subresource_loader_params.h"
#include "content/common/resource_messages.h"
#include "content/common/service_manager/child_connection.h"
#include "content/common/service_manager/service_manager_connection_impl.h"
@@ -191,7 +191,6 @@
#include "media/audio/audio_manager.h"
#include "media/base/media_switches.h"
#include "media/media_buildflags.h"
-#include "media/mojo/services/video_decode_perf_history.h"
#include "media/webrtc/webrtc_switches.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -216,7 +215,6 @@
#include "third_party/blink/public/public_buildflags.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/accessibility/accessibility_switches.h"
-#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/display/display_switches.h"
@@ -894,6 +892,28 @@ class SiteProcessCountTracker : public base::SupportsUserData::Data,
}
}
+ // Check whether |host| is associated with at least one URL for which
+ // SiteInstance does not assign site URLs. This is used to disqualify |host|
+ // from being reused if it has pending navigations to such URLs.
+ bool ContainsNonReusableSiteForHost(RenderProcessHost* host) {
+ for (auto iter : map_) {
+ // If SiteInstance doesn't assign a site URL for the current entry (and it
+ // isn't about:blank, which is allowed anywhere), check whether |host| is
+ // on the list of processes the entry is associated with.
+ //
+ // TODO(alexmos): ShouldAssignSiteForURL() expects a full URL, whereas we
+ // only have a site URL here. For now, this mismatch is ok since
+ // ShouldAssignSiteForURL() only cares about schemes in practice, but
+ // this should be cleaned up.
+ const std::map<ProcessID, Count>& counts_per_process = iter.second;
+ if (!SiteInstanceImpl::ShouldAssignSiteForURL(iter.first) &&
+ !iter.first.IsAboutBlank() &&
+ counts_per_process.find(host->GetID()) != counts_per_process.end())
+ return true;
+ }
+ return false;
+ }
+
private:
void RenderProcessHostDestroyed(RenderProcessHost* host) override {
#ifndef NDEBUG
@@ -1545,14 +1565,12 @@ RenderProcessHostImpl::RenderProcessHostImpl(
InitializeChannelProxy();
- if (!features::IsMultiProcessMash()) {
- const int id = GetID();
- const uint64_t tracing_id =
- ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(id);
- gpu_client_.reset(new viz::GpuClient(
- std::make_unique<BrowserGpuClientDelegate>(), id, tracing_id,
- base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})));
- }
+ const int id = GetID();
+ const uint64_t tracing_id =
+ ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(id);
+ gpu_client_.reset(new viz::GpuClient(
+ std::make_unique<BrowserGpuClientDelegate>(), id, tracing_id,
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})));
}
// static
@@ -1639,6 +1657,8 @@ bool RenderProcessHostImpl::Init() {
#if defined(OS_LINUX)
int flags = renderer_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF
: ChildProcessHost::CHILD_NORMAL;
+#elif defined(OS_MACOSX)
+ int flags = ChildProcessHost::CHILD_RENDERER;
#else
int flags = ChildProcessHost::CHILD_NORMAL;
#endif
@@ -1896,7 +1916,6 @@ void RenderProcessHostImpl::CreateMessageFilters() {
GetID(), storage_partition_impl_->GetAppCacheService(),
blob_storage_context.get(),
storage_partition_impl_->GetFileSystemContext(),
- storage_partition_impl_->GetServiceWorkerContext(),
storage_partition_impl_->GetPrefetchURLLoaderService(),
std::move(get_contexts_callback),
base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
@@ -1932,20 +1951,8 @@ void RenderProcessHostImpl::BindCacheStorage(
blink::mojom::CacheStorageRequest request,
const url::Origin& origin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- if (!cache_storage_dispatcher_host_) {
- cache_storage_dispatcher_host_ =
- base::MakeRefCounted<CacheStorageDispatcherHost>();
- cache_storage_dispatcher_host_->Init(
- storage_partition_impl_->GetCacheStorageContext());
- }
- // Send the binding to IO thread, because Cache Storage handles Mojo IPC on IO
- // thread entirely.
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&CacheStorageDispatcherHost::AddBinding,
- cache_storage_dispatcher_host_, std::move(request),
- origin));
+ storage_partition_impl_->GetCacheStorageContext()->AddBinding(
+ std::move(request), origin);
}
void RenderProcessHostImpl::BindIndexedDB(
@@ -2063,13 +2070,6 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
AddUIThreadInterface(registry.get(),
base::BindRepeating(&ClipboardHostImpl::Create));
- media::VideoDecodePerfHistory* video_perf_history =
- GetBrowserContext()->GetVideoDecodePerfHistory();
- AddUIThreadInterface(
- registry.get(),
- base::BindRepeating(&media::VideoDecodePerfHistory::BindRequest,
- base::Unretained(video_perf_history)));
-
registry->AddInterface(
base::BindRepeating(&MimeRegistryImpl::Create),
base::CreateSequencedTaskRunnerWithTraits(
@@ -2096,8 +2096,7 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
base::Unretained(push_messaging_manager_.get())));
file_system_manager_impl_.reset(new FileSystemManagerImpl(
- GetID(), MSG_ROUTING_NONE,
- storage_partition_impl_->GetFileSystemContext(),
+ GetID(), storage_partition_impl_->GetFileSystemContext(),
ChromeBlobStorageContext::GetFor(GetBrowserContext())));
// This interface is still exposed by the RenderProcessHost's registry so
// that it can be accessed by PepperFileSystemHost. Blink accesses this
@@ -2585,6 +2584,8 @@ void RenderProcessHostImpl::ShutdownForBadMessage(
site_isolation_mode += "spp ";
if (SiteIsolationPolicy::AreIsolatedOriginsEnabled())
site_isolation_mode += "io ";
+ if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled())
+ site_isolation_mode += "soi ";
if (site_isolation_mode.empty())
site_isolation_mode = "(none)";
@@ -2935,7 +2936,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDefaultTileWidth,
switches::kDefaultTileHeight,
switches::kDisable2dCanvasImageChromium,
- switches::kDisableAcceleratedJpegDecoding,
+ switches::kDisableYUVImageDecoding,
switches::kDisableAcceleratedVideoDecode,
switches::kDisableBackgroundTimerThrottling,
switches::kDisableBestEffortTasks,
@@ -3001,6 +3002,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableWebGL2ComputeContext,
switches::kEnableWebGLDraftExtensions,
switches::kEnableWebGLImageChromium,
+ switches::kEnableWebGLSwapChain,
switches::kEnableWebVR,
switches::kFileUrlPathAlias,
switches::kForceDisplayColorProfile,
@@ -3014,6 +3016,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kJavaScriptFlags,
switches::kLogFile,
switches::kLoggingLevel,
+ switches::kMaxActiveWebGLContexts,
switches::kMaxUntiledLayerWidth,
switches::kMaxUntiledLayerHeight,
switches::kMSEAudioBufferSizeLimitMb,
@@ -3026,11 +3029,10 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kProfilingAtStart,
switches::kProfilingFile,
switches::kProfilingFlush,
- switches::kReducedReferrerGranularity,
switches::kRegisterPepperPlugins,
switches::kRendererStartupDialog,
switches::kReportVp9AsAnUnsupportedMimeType,
- switches::kSamplingHeapProfiler,
+ switches::kShowLayoutShiftRegions,
switches::kShowPaintRects,
switches::kStatsCollectionController,
switches::kSkiaFontCacheLimitMb,
@@ -3050,6 +3052,8 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kVideoThreads,
switches::kVideoUnderflowThresholdMs,
switches::kVModule,
+ switches::kWebglAntialiasingMode,
+ switches::kWebglMSAASampleCount,
// Please keep these in alphabetical order. Compositor switches here should
// also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
cc::switches::kCCScrollAnimationDurationForTesting,
@@ -3067,7 +3071,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
cc::switches::kSlowDownRasterScaleFactor,
cc::switches::kBrowserControlsHideThreshold,
cc::switches::kBrowserControlsShowThreshold,
- switches::kEnableSurfaceSynchronization,
switches::kRunAllCompositorStagesBeforeDraw,
switches::kUseVizHitTestSurfaceLayer,
@@ -3087,7 +3090,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
#if defined(OS_ANDROID)
switches::kDisableMediaSessionAPI,
switches::kEnableReachedCodeProfiler,
- switches::kOrderfileMemoryOptimization,
switches::kRendererWaitForJavaDebugger,
#endif
#if defined(OS_WIN)
@@ -3740,7 +3742,33 @@ bool RenderProcessHostImpl::IsSuitableHost(
}
}
- return GetContentClient()->browser()->IsSuitableHost(host, site_url);
+ if (!GetContentClient()->browser()->IsSuitableHost(host, site_url))
+ return false;
+
+ // If this site_url is going to require a dedicated process, then check
+ // whether this process has a pending navigation to a URL for which
+ // SiteInstance does not assign site URLs. If this is the case, it is not
+ // safe to reuse this process for a navigation which itself assigns site URLs,
+ // since in that case the latter navigation could lock this process before
+ // the commit for the siteless URL arrives, resulting in a renderer kill.
+ // See https://crbug.com/970046.
+ if (SiteInstanceImpl::ShouldAssignSiteForURL(site_url) &&
+ SiteInstanceImpl::DoesSiteRequireDedicatedProcess(isolation_context,
+ site_url)) {
+ SiteProcessCountTracker* pending_tracker =
+ static_cast<SiteProcessCountTracker*>(
+ browser_context->GetUserData(kPendingSiteProcessCountTrackerKey));
+ bool has_disqualifying_pending_navigation =
+ pending_tracker &&
+ pending_tracker->ContainsNonReusableSiteForHost(host);
+ UMA_HISTOGRAM_BOOLEAN(
+ "SiteIsolation.PendingSitelessNavigationDisallowsProcessReuse",
+ has_disqualifying_pending_navigation);
+ if (has_disqualifying_pending_navigation)
+ return false;
+ }
+
+ return true;
}
// static
@@ -3889,8 +3917,7 @@ RenderProcessHost* RenderProcessHostImpl::GetSoleProcessHostForURL(
BrowserContext* browser_context,
const IsolationContext& isolation_context,
const GURL& url) {
- GURL site_url = SiteInstanceImpl::GetSiteForURL(
- isolation_context, url, true /* should_use_effective_urls */);
+ GURL site_url = SiteInstanceImpl::GetSiteForURL(isolation_context, url);
GURL lock_url =
SiteInstanceImpl::DetermineProcessLockURL(isolation_context, url);
return GetSoleProcessHostForSite(browser_context, isolation_context, site_url,
@@ -4130,9 +4157,8 @@ void RenderProcessHostImpl::ProcessDied(
// May be in case of IPC error, if it takes long time for renderer
// to exit. Child process will be killed in any case during
// child_process_launcher_.reset(). Make sure we will not broadcast
- // FrameHostMsg_RenderProcessGone with status
- // TERMINATION_STATUS_STILL_RUNNING, since this will break WebContentsImpl
- // logic.
+ // RenderProcessExited with status TERMINATION_STATUS_STILL_RUNNING, since
+ // this will break WebContentsImpl logic.
info.status = base::TERMINATION_STATUS_PROCESS_CRASHED;
// TODO(siggi): Remove this once https://crbug.com/806661 is resolved.
@@ -4152,7 +4178,7 @@ void RenderProcessHostImpl::ProcessDied(
UpdateProcessPriority();
- // RenderProcessGone relies on the exit code set during shutdown.
+ // RenderProcessExited relies on the exit code set during shutdown.
if (shutdown_exit_code_ != -1)
info.exit_code = shutdown_exit_code_;
@@ -4160,13 +4186,6 @@ void RenderProcessHostImpl::ProcessDied(
for (auto& observer : observers_)
observer.RenderProcessExited(this, info);
- base::IDMap<IPC::Listener*>::iterator iter(&listeners_);
- while (!iter.IsAtEnd()) {
- iter.GetCurrentValue()->OnMessageReceived(FrameHostMsg_RenderProcessGone(
- iter.GetCurrentKey(), static_cast<int>(info.status), info.exit_code));
- iter.Advance();
- }
-
NotificationService::current()->Notify(
NOTIFICATION_RENDERER_PROCESS_CLOSED, Source<RenderProcessHost>(this),
Details<ChildProcessTerminationInfo>(&info));
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 8ee98dfed01..e801cf52372 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -28,7 +28,6 @@
#include "base/synchronization/waitable_event.h"
#include "base/task/post_task.h"
#include "build/build_config.h"
-#include "content/browser/cache_storage/cache_storage_dispatcher_host.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/media/video_decoder_proxy.h"
@@ -869,8 +868,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
std::unique_ptr<IndexedDBDispatcherHost, base::OnTaskRunnerDeleter>
indexed_db_factory_;
- scoped_refptr<CacheStorageDispatcherHost> cache_storage_dispatcher_host_;
-
bool channel_connected_;
bool sent_render_process_ready_;
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 cc190205816..2cdae231e2d 100644
--- a/chromium/content/browser/renderer_host/render_process_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_unittest.cc
@@ -107,26 +107,23 @@ TEST_F(RenderProcessHostUnitTest, ReuseCommittedSite) {
// At first, trying to get a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
scoped_refptr<SiteInstanceImpl> site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateReusableInstanceForTesting(browser_context(),
+ kUrl1);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Have the main frame navigate to the first url. Getting a RenderProcessHost
// with the REUSE_PENDING_OR_COMMITTED_SITE policy should now return the
// process of the main RFH.
NavigateAndCommit(kUrl1);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl1);
EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Navigate away. Getting a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should again return a new process.
NavigateAndCommit(kUrl2);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl1);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Now add a subframe that navigates to kUrl1. Getting a RenderProcessHost
// with the REUSE_PENDING_OR_COMMITTED_SITE policy for kUrl1 should now
@@ -144,9 +141,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseCommittedSite) {
contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
subframe = static_cast<TestRenderFrameHost*>(
NavigationSimulator::NavigateAndCommitFromDocument(kUrl1, subframe));
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl1);
EXPECT_EQ(subframe->GetProcess(), site_instance->GetProcess());
}
@@ -185,16 +181,14 @@ TEST_F(RenderProcessHostUnitTest, ReuseUnmatchedServiceWorkerProcess) {
// Gets a RenderProcessHost for an unmatched service worker.
scoped_refptr<SiteInstanceImpl> sw_site_instance1 =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- sw_site_instance1->set_is_for_service_worker();
+ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl);
RenderProcessHost* sw_host1 = sw_site_instance1->GetProcess();
// Getting a RenderProcessHost for a service worker with DEFAULT reuse policy
// should not reuse the existing service worker's process. We create this
// second service worker to test the "find the newest process" logic later.
scoped_refptr<SiteInstanceImpl> sw_site_instance2 =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- sw_site_instance2->set_is_for_service_worker();
+ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl);
RenderProcessHost* sw_host2 = sw_site_instance2->GetProcess();
EXPECT_NE(sw_host1, sw_host2);
@@ -240,8 +234,7 @@ TEST_F(RenderProcessHostUnitTest,
// Gets a RenderProcessHost for an unmatched service worker.
scoped_refptr<SiteInstanceImpl> sw_site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- sw_site_instance->set_is_for_service_worker();
+ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl);
RenderProcessHost* sw_host = sw_site_instance->GetProcess();
// Simulate a situation where |sw_host| won't be considered suitable for
@@ -272,10 +265,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseServiceWorkerProcessForServiceWorker) {
// Gets a RenderProcessHost for a service worker.
scoped_refptr<SiteInstanceImpl> sw_site_instance1 =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- sw_site_instance1->set_is_for_service_worker();
- sw_site_instance1->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl,
+ /* can_reuse_process */ true);
RenderProcessHost* sw_host1 = sw_site_instance1->GetProcess();
// Getting a RenderProcessHost for a service worker with DEFAULT reuse policy
@@ -284,8 +275,7 @@ TEST_F(RenderProcessHostUnitTest, ReuseServiceWorkerProcessForServiceWorker) {
// start the service worker and want to use a new process. We create this
// second service worker to test the "find the newest process" logic later.
scoped_refptr<SiteInstanceImpl> sw_site_instance2 =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- sw_site_instance2->set_is_for_service_worker();
+ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl);
RenderProcessHost* sw_host2 = sw_site_instance2->GetProcess();
EXPECT_NE(sw_host1, sw_host2);
@@ -293,10 +283,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseServiceWorkerProcessForServiceWorker) {
// REUSE_PENDING_OR_COMMITTED_SITE reuse policy should reuse the newest
// unmatched service worker's process (i.e., sw_host2).
scoped_refptr<SiteInstanceImpl> sw_site_instance3 =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- sw_site_instance3->set_is_for_service_worker();
- sw_site_instance3->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl,
+ /* can_reuse_process */ true);
RenderProcessHost* sw_host3 = sw_site_instance3->GetProcess();
EXPECT_EQ(sw_host2, sw_host3);
@@ -306,10 +294,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseServiceWorkerProcessForServiceWorker) {
// sw_host2 to be considered matched, so we can keep putting more service
// workers in that process.
scoped_refptr<SiteInstanceImpl> sw_site_instance4 =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- sw_site_instance4->set_is_for_service_worker();
- sw_site_instance4->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl,
+ /* can_reuse_process */ true);
RenderProcessHost* sw_host4 = sw_site_instance4->GetProcess();
EXPECT_EQ(sw_host2, sw_host4);
@@ -336,15 +322,13 @@ TEST_F(RenderProcessHostUnitTest,
// Gets a RenderProcessHost for a service worker with process-per-site flag.
scoped_refptr<SiteInstanceImpl> sw_site_instance1 =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- sw_site_instance1->set_is_for_service_worker();
+ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl);
RenderProcessHost* sw_host1 = sw_site_instance1->GetProcess();
// Getting a RenderProcessHost for a service worker of the same site with
// process-per-site flag should reuse the unmatched service worker's process.
scoped_refptr<SiteInstanceImpl> sw_site_instance2 =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- sw_site_instance2->set_is_for_service_worker();
+ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl);
RenderProcessHost* sw_host2 = sw_site_instance2->GetProcess();
EXPECT_EQ(sw_host1, sw_host2);
@@ -369,8 +353,7 @@ TEST_F(RenderProcessHostUnitTest, DoNotReuseOtherSiteServiceWorkerProcess) {
// Gets a RenderProcessHost for a service worker.
scoped_refptr<SiteInstanceImpl> sw_site_instance1 =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
- sw_site_instance1->set_is_for_service_worker();
+ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl1);
RenderProcessHost* sw_host1 = sw_site_instance1->GetProcess();
// Getting a RenderProcessHost for a service worker of a different site should
@@ -389,34 +372,30 @@ TEST_F(RenderProcessHostUnitTest, DoNotReuseError) {
// At first, trying to get a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
scoped_refptr<SiteInstanceImpl> site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateReusableInstanceForTesting(browser_context(),
+ kUrl1);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Have the main frame navigate to the first url. Getting a RenderProcessHost
// with the REUSE_PENDING_OR_COMMITTED_SITE policy should now return the
// process of the main RFH.
NavigateAndCommit(kUrl1);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl1);
EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Navigate away. Getting a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should again return a new process.
NavigateAndCommit(kUrl2);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl1);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Navigate back and simulate an error. Getting a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
NavigationSimulator::GoBackAndFail(contents(), net::ERR_TIMED_OUT);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl1);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
}
@@ -427,9 +406,8 @@ TEST_F(RenderProcessHostUnitTest, DoNotReuseHostThatIsNeverSuitableForReuse) {
NavigateAndCommit(kUrl);
main_test_rfh()->GetProcess()->SetIsNeverSuitableForReuse();
scoped_refptr<SiteInstanceImpl> site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateReusableInstanceForTesting(browser_context(),
+ kUrl);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
}
@@ -442,9 +420,8 @@ TEST_F(RenderProcessHostUnitTest, DISABLED_ReuseNavigationProcess) {
// At first, trying to get a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
scoped_refptr<SiteInstanceImpl> site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateReusableInstanceForTesting(browser_context(),
+ kUrl1);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Start a navigation. Now Getting RenderProcessHost with the
@@ -452,9 +429,8 @@ TEST_F(RenderProcessHostUnitTest, DISABLED_ReuseNavigationProcess) {
auto navigation =
NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
navigation->Start();
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl1);
EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Finish the navigation and start a new cross-site one. Getting
@@ -463,9 +439,8 @@ TEST_F(RenderProcessHostUnitTest, DISABLED_ReuseNavigationProcess) {
navigation->Commit();
navigation = NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
navigation->Start();
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl2);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl2);
EXPECT_EQ(contents()->GetPendingMainFrame()->GetProcess(),
site_instance->GetProcess());
@@ -475,9 +450,8 @@ TEST_F(RenderProcessHostUnitTest, DISABLED_ReuseNavigationProcess) {
int speculative_process_host_id =
contents()->GetPendingMainFrame()->GetProcess()->GetID();
navigation->Fail(net::ERR_ABORTED);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl2);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl2);
EXPECT_NE(speculative_process_host_id, site_instance->GetProcess()->GetID());
}
@@ -494,9 +468,8 @@ TEST_F(RenderProcessHostUnitTest,
// At first, trying to get a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
scoped_refptr<SiteInstanceImpl> site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateReusableInstanceForTesting(browser_context(),
+ kUrl);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Start a navigation. Now getting RenderProcessHost with the
@@ -505,9 +478,8 @@ TEST_F(RenderProcessHostUnitTest,
NavigationSimulator::CreateRendererInitiated(kUrl, main_test_rfh());
simulator->Start();
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
// Note that with --site-per-process, the GetProcess() call on
// |site_instance| will also lock the current process to http://foo.com.
EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
@@ -515,9 +487,8 @@ TEST_F(RenderProcessHostUnitTest,
// Simulate a same-site redirect. Getting RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should return the current process.
simulator->Redirect(kRedirectUrl1);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Simulate a cross-site redirect. Getting a RenderProcessHost with the
@@ -526,14 +497,11 @@ TEST_F(RenderProcessHostUnitTest,
// the REUSE_PENDING_OR_COMMITTED_SITE policy for the new bar.com site should
// return the the original process, unless we're in --site-per-process mode.
simulator->Redirect(kRedirectUrl2);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
- site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kRedirectUrl2);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kRedirectUrl2);
if (AreAllSitesIsolatedForTesting()) {
// In --site-per-process, we should've recognized that we will need to swap
// to a new process; however, the new process won't be created until
@@ -555,15 +523,12 @@ TEST_F(RenderProcessHostUnitTest,
simulator->ReadyToCommit();
RenderProcessHost* post_redirect_process =
simulator->GetFinalRenderFrameHost()->GetProcess();
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
EXPECT_NE(post_redirect_process, site_instance->GetProcess());
- site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kRedirectUrl2);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kRedirectUrl2);
EXPECT_EQ(post_redirect_process, site_instance->GetProcess());
}
@@ -581,9 +546,8 @@ TEST_F(RenderProcessHostUnitTest,
// At first, trying to get a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
scoped_refptr<SiteInstanceImpl> site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateReusableInstanceForTesting(browser_context(),
+ kUrl);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Start a navigation. Now getting RenderProcessHost with the
@@ -594,18 +558,16 @@ TEST_F(RenderProcessHostUnitTest,
main_test_rfh()->SendBeforeUnloadACK(true);
int speculative_process_host_id =
contents()->GetPendingMainFrame()->GetProcess()->GetID();
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_EQ(speculative_process_host_id, site_instance->GetProcess()->GetID());
// Simulate a same-site redirect. Getting RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should return the speculative
// process.
main_test_rfh()->SimulateRedirect(kRedirectUrl1);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_EQ(speculative_process_host_id, site_instance->GetProcess()->GetID());
// Simulate a cross-site redirect. Getting a RenderProcessHost with the
@@ -613,15 +575,12 @@ TEST_F(RenderProcessHostUnitTest,
// speculative process: neither for the new site nor for the initial site we
// were trying to navigate to. It shouldn't return the current process either.
main_test_rfh()->SimulateRedirect(kRedirectUrl2);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
EXPECT_NE(speculative_process_host_id, site_instance->GetProcess()->GetID());
- site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kRedirectUrl2);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kRedirectUrl2);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
EXPECT_NE(speculative_process_host_id, site_instance->GetProcess()->GetID());
@@ -632,15 +591,12 @@ TEST_F(RenderProcessHostUnitTest,
main_test_rfh()->PrepareForCommit();
speculative_process_host_id =
contents()->GetPendingMainFrame()->GetProcess()->GetID();
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
EXPECT_NE(speculative_process_host_id, site_instance->GetProcess()->GetID());
- site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kRedirectUrl2);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kRedirectUrl2);
EXPECT_EQ(speculative_process_host_id, site_instance->GetProcess()->GetID());
}
@@ -653,18 +609,16 @@ TEST_F(RenderProcessHostUnitTest, ReuseSiteURLChanges) {
// At first, trying to get a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
scoped_refptr<SiteInstanceImpl> site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateReusableInstanceForTesting(browser_context(),
+ kUrl);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Have the main frame navigate to the first url. Getting a RenderProcessHost
// with the REUSE_PENDING_OR_COMMITTED_SITE policy should now return the
// process of the main RFH.
NavigateAndCommit(kUrl);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Install the custom ContentBrowserClient. Site URLs are now modified.
@@ -674,9 +628,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseSiteURLChanges) {
EffectiveURLContentBrowserClient modified_client(kUrl, kModifiedSiteUrl);
ContentBrowserClient* regular_client =
SetBrowserClientForTesting(&modified_client);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Reload. Getting a RenderProcessHost with the
@@ -690,9 +643,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseSiteURLChanges) {
rfh = contents()->GetPendingMainFrame();
rfh->PrepareForCommit();
rfh->SendNavigate(0, true, kUrl);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_EQ(rfh->GetProcess(), site_instance->GetProcess());
// Remove the custom ContentBrowserClient. Site URLs are back to normal.
@@ -700,9 +652,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseSiteURLChanges) {
// should no longer return the process of the main RFH, as it is registered
// with the modified site URL.
SetBrowserClientForTesting(regular_client);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_NE(rfh->GetProcess(), site_instance->GetProcess());
// Reload. Getting a RenderProcessHost with the
@@ -713,9 +664,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseSiteURLChanges) {
: main_test_rfh();
rfh->PrepareForCommit();
rfh->SendNavigate(0, true, kUrl);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_EQ(rfh->GetProcess(), site_instance->GetProcess());
}
@@ -731,9 +681,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseExpectedSiteURLChanges) {
// At first, trying to get a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
scoped_refptr<SiteInstanceImpl> site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateReusableInstanceForTesting(browser_context(),
+ kUrl);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Start a navigation. Getting a RenderProcessHost with the
@@ -742,9 +691,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseExpectedSiteURLChanges) {
auto navigation =
NavigationSimulator::CreateRendererInitiated(kUrl, main_test_rfh());
navigation->Start();
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Install the custom ContentBrowserClient. Site URLs are now modified.
@@ -754,27 +702,24 @@ TEST_F(RenderProcessHostUnitTest, ReuseExpectedSiteURLChanges) {
EffectiveURLContentBrowserClient modified_client(kUrl, kModifiedSiteUrl);
ContentBrowserClient* regular_client =
SetBrowserClientForTesting(&modified_client);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Have the navigation commit. Getting a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should now return the process of the
// main RFH, as it was registered with the modified site URL at commit time.
navigation->Commit();
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Start a reload. Getting a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should return the process of the
// main RFH.
contents()->GetController().Reload(ReloadType::NORMAL, false);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Remove the custom ContentBrowserClient. Site URLs are back to normal.
@@ -782,9 +727,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseExpectedSiteURLChanges) {
// should no longer return the process of the main RFH, as it is registered
// with the modified site URL.
SetBrowserClientForTesting(regular_client);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
// Finish the reload. Getting a RenderProcessHost with the
@@ -792,9 +736,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseExpectedSiteURLChanges) {
// main RFH, as it was registered with the regular site URL when it committed.
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigate(0, true, kUrl);
- site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
+ browser_context(), kUrl);
EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
}
@@ -849,9 +792,8 @@ TEST_F(RenderProcessHostUnitTest,
// reuse the foo process from the first navigation, since it's now in a
// different StoragePartition.
scoped_refptr<SiteInstanceImpl> site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateReusableInstanceForTesting(browser_context(),
+ kUrl);
RenderProcessHost* process = site_instance->GetProcess();
EXPECT_NE(main_test_rfh()->GetProcess(), process);
@@ -866,8 +808,7 @@ TEST_F(RenderProcessHostUnitTest,
// Create a RenderProcessHost for a service worker.
scoped_refptr<SiteInstanceImpl> sw_site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- sw_site_instance->set_is_for_service_worker();
+ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl);
RenderProcessHost* sw_process = sw_site_instance->GetProcess();
// Change foo.com SiteInstances to use a different StoragePartition.
@@ -880,9 +821,8 @@ TEST_F(RenderProcessHostUnitTest,
// the ServiceWorker foo.com process, since it's now in a different
// StoragePartition.
scoped_refptr<SiteInstanceImpl> site_instance =
- SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ SiteInstanceImpl::CreateReusableInstanceForTesting(browser_context(),
+ kUrl);
RenderProcessHost* process = site_instance->GetProcess();
EXPECT_NE(sw_process, process);
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 a7532fa393c..9daf7a59915 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.cc
@@ -53,9 +53,8 @@ RenderViewHost* RenderViewHostFactory::Create(
}
return new RenderViewHostImpl(
instance,
- base::WrapUnique(RenderWidgetHostFactory::Create(
- widget_delegate, instance->GetProcess(), widget_routing_id, nullptr,
- hidden)),
+ RenderWidgetHostFactory::Create(widget_delegate, instance->GetProcess(),
+ widget_routing_id, nullptr, hidden),
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_impl.cc b/chromium/content/browser/renderer_host/render_view_host_impl.cc
index 2c4182e518c..1f5d4329f6f 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -227,7 +227,6 @@ RenderViewHostImpl::RenderViewHostImpl(
main_frame_routing_id_(main_frame_routing_id),
is_waiting_for_close_ack_(false),
sudden_termination_allowed_(false),
- render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING),
updating_web_preferences_(false),
has_notified_about_creation_(false),
weak_factory_(this) {
@@ -502,9 +501,6 @@ const WebPreferences RenderViewHostImpl::ComputeWebPreferences() {
prefs.use_solid_color_scrollbars = false;
- prefs.history_entry_requires_user_gesture =
- command_line.HasSwitch(switches::kHistoryEntryRequiresUserGesture);
-
prefs.disable_ipc_flooding_protection =
command_line.HasSwitch(switches::kDisableIpcFloodingProtection) ||
command_line.HasSwitch(switches::kDisablePushStateThrottle);
@@ -731,7 +727,7 @@ void RenderViewHostImpl::RenderProcessExited(
if (!GetWidget()->renderer_initialized())
return;
- GetWidget()->RendererExited(info.status, info.exit_code);
+ GetWidget()->RendererExited();
delegate_->RenderViewTerminated(this, info.status, info.exit_code);
}
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 fcece6afe04..d508822bb4c 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.h
@@ -129,10 +129,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
const FrameReplicationState& replicated_frame_state,
bool window_was_created_with_opener);
- base::TerminationStatus render_view_termination_status() const {
- return render_view_termination_status_;
- }
-
// Tracks whether this RenderViewHost is in an active state (rather than
// pending swap out or swapped out), according to its main frame
// RenderFrameHost.
@@ -341,9 +337,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// True if the render view can be shut down suddenly.
bool sudden_termination_allowed_;
- // The termination status of the last render view that terminated.
- base::TerminationStatus render_view_termination_status_;
-
// This is updated every time UpdateWebkitPreferences is called. That method
// is in turn called when any of the settings change that the WebPreferences
// values depend on.
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 7a8e862b7c1..da15ec49db1 100644
--- a/chromium/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
@@ -26,6 +26,7 @@
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/navigation_simulator.h"
#include "content/test/mock_widget_impl.h"
+#include "content/test/navigation_simulator_impl.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
@@ -240,35 +241,27 @@ TEST_F(RenderViewHostTest, MessageWithBadHistoryItemFiles) {
EXPECT_EQ(1, process()->bad_msg_count());
}
-namespace {
-void SetBadFilePath(const GURL& url,
- const base::FilePath& file_path,
- FrameHostMsg_DidCommitProvisionalLoad_Params* params) {
- params->page_state =
- PageState::CreateForTesting(url, false, "data", &file_path);
-}
-}
-
TEST_F(RenderViewHostTest, NavigationWithBadHistoryItemFiles) {
GURL url("http://www.google.com");
base::FilePath file_path;
EXPECT_TRUE(base::PathService::Get(base::DIR_TEMP, &file_path));
file_path = file_path.AppendASCII("bar");
- auto set_bad_file_path_callback = base::Bind(SetBadFilePath, url, file_path);
EXPECT_EQ(0, process()->bad_msg_count());
- main_test_rfh()->SendRendererInitiatedNavigationRequest(url, false);
- main_test_rfh()->PrepareForCommit();
- contents()->GetMainFrame()->SendNavigateWithModificationCallback(
- 1, true, url, set_bad_file_path_callback);
+ auto navigation1 =
+ NavigationSimulatorImpl::CreateRendererInitiated(url, main_test_rfh());
+ navigation1->set_page_state(
+ PageState::CreateForTesting(url, false, "data", &file_path));
+ navigation1->Commit();
EXPECT_EQ(1, process()->bad_msg_count());
ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
process()->GetID(), file_path);
- main_test_rfh()->SendRendererInitiatedNavigationRequest(url, false);
- main_test_rfh()->PrepareForCommit();
- contents()->GetMainFrame()->SendNavigateWithModificationCallback(
- 2, true, url, std::move(set_bad_file_path_callback));
+ auto navigation2 =
+ NavigationSimulatorImpl::CreateRendererInitiated(url, main_test_rfh());
+ navigation2->set_page_state(
+ PageState::CreateForTesting(url, false, "data", &file_path));
+ navigation2->Commit();
EXPECT_EQ(1, process()->bad_msg_count());
}
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 050d74e5b77..00a6998d754 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
@@ -188,6 +188,12 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// warning shown to the user.
virtual void RendererResponsive(RenderWidgetHostImpl* render_widget_host) {}
+ // Notification that a cross-process subframe on this page has crashed, and a
+ // sad frame is shown if the subframe was visible. |frame_visibility|
+ // specifies whether the subframe is visible, scrolled out of view, or hidden
+ // (e.g., with "display: none").
+ virtual void SubframeCrashed(blink::mojom::FrameVisibility visibility) {}
+
// Requests to lock the mouse. Once the request is approved or rejected,
// GotResponseToLockMouseRequest() will be called on the requesting render
// widget host. |privileged| means that the request is always granted, used
diff --git a/chromium/content/browser/renderer_host/render_widget_host_factory.cc b/chromium/content/browser/renderer_host/render_widget_host_factory.cc
index 2a0c4f1bf2d..bae880134e2 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_factory.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_factory.cc
@@ -12,7 +12,7 @@ namespace content {
RenderWidgetHostFactory* RenderWidgetHostFactory::factory_ = nullptr;
// static
-RenderWidgetHostImpl* RenderWidgetHostFactory::Create(
+std::unique_ptr<RenderWidgetHostImpl> RenderWidgetHostFactory::Create(
RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int32_t routing_id,
@@ -22,8 +22,8 @@ RenderWidgetHostImpl* RenderWidgetHostFactory::Create(
return factory_->CreateRenderWidgetHost(
delegate, process, routing_id, std::move(widget_interface), hidden);
}
- return new RenderWidgetHostImpl(delegate, process, routing_id,
- std::move(widget_interface), hidden);
+ return std::make_unique<RenderWidgetHostImpl>(
+ delegate, process, routing_id, std::move(widget_interface), hidden);
}
// static
diff --git a/chromium/content/browser/renderer_host/render_widget_host_factory.h b/chromium/content/browser/renderer_host/render_widget_host_factory.h
index c691954c6a3..e197d53a927 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_factory.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_factory.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_FACTORY_H_
#include <stdint.h>
+#include <memory>
#include "base/macros.h"
#include "content/common/content_export.h"
@@ -24,11 +25,12 @@ class RenderWidgetHostFactory {
// Creates a RenderWidgetHostImpl using the currently registered factory, or
// the default one if no factory is registered. Ownership of the returned
// pointer will be passed to the caller.
- static RenderWidgetHostImpl* Create(RenderWidgetHostDelegate* delegate,
- RenderProcessHost* process,
- int32_t routing_id,
- mojom::WidgetPtr widget_interface,
- bool hidden);
+ static std::unique_ptr<RenderWidgetHostImpl> Create(
+ RenderWidgetHostDelegate* delegate,
+ RenderProcessHost* process,
+ int32_t routing_id,
+ mojom::WidgetPtr widget_interface,
+ bool hidden);
// Returns true if there is currently a globally-registered factory.
static bool has_factory() { return !!factory_; }
@@ -39,7 +41,7 @@ class RenderWidgetHostFactory {
// You can derive from this class and specify an implementation for this
// function to create a different kind of RenderWidgetHostImpl for testing.
- virtual RenderWidgetHostImpl* CreateRenderWidgetHost(
+ virtual std::unique_ptr<RenderWidgetHostImpl> CreateRenderWidgetHost(
RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int32_t routing_id,
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 4ccf75d1c1f..d1cf894d19b 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -21,7 +21,6 @@
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
@@ -37,6 +36,7 @@
#include "cc/trees/render_frame_metadata.h"
#include "components/viz/common/features.h"
#include "components/viz/common/quads/compositor_frame.h"
+#include "components/viz/common/resources/bitmap_allocation.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
@@ -336,70 +336,6 @@ base::LazyInstance<UnboundWidgetInputHandler>::Leaky g_unbound_input_handler =
} // namespace
-// KeyEventResultTracker is used to update the status of the KeyEvent. If the
-// event is sent to the renderer, the status is updated asynchronously.
-// KeyEventResultTracker is owned by the callback supplied to
-// InputRouter::SendKeyboardEvent() and passed to the callback function
-// (OnKeyboardEventAck()).
-class RenderWidgetHostImpl::KeyEventResultTracker {
- public:
- explicit KeyEventResultTracker(ui::KeyEvent* key_event)
- : key_event_(key_event) {
- DCHECK(key_event_);
- }
-
- ~KeyEventResultTracker() {
- if (is_async_ && async_callback_) {
- std::move(async_callback_)
- .Run(/* handled */ false,
- /* stopped_propagation */ false);
- }
- }
-
- base::WeakPtr<KeyEventResultTracker> GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
- }
-
- // Called if the event is being sent to the renderer.
- void PrepareForAsync() {
- DCHECK(!is_async_);
- is_async_ = true;
- async_callback_ = key_event_->WillHandleAsync();
- // Null out |key_event_| as KeyEvent is not owned by this, and generally
- // owned higher up the stack. Because the processing is async, |key_event_|
- // will be deleted *before* OnEventProcessingDone() or the destructor is
- // called.
- key_event_ = nullptr;
- }
-
- // Called when processing is complete. This may never be called, in which case
- // the destructor is responsible for updating the callback from the event.
- void OnEventProcessingDone(bool handled) {
- if (is_async_ && async_callback_) {
- // This supplies false for |stopped_propagation| so that InsertChar() gets
- // called. Content never calls StopPropagation().
- std::move(async_callback_).Run(handled, /* stopped_propagation */ false);
- } else if (!is_async_ && handled) {
- key_event_->SetHandled();
- }
- }
-
- private:
- // The event. This is set to null if the event is sent to the renderer.
- ui::KeyEvent* key_event_;
-
- // Set to true if the event is sent to the renderer.
- bool is_async_ = false;
-
- // Callback from the event. This is obtained from |key_event_| if the event is
- // handled async.
- base::OnceCallback<void(bool, bool)> async_callback_;
-
- base::WeakPtrFactory<KeyEventResultTracker> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(KeyEventResultTracker);
-};
-
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostImpl
@@ -439,7 +375,7 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
#endif
CHECK(delegate_);
CHECK_NE(MSG_ROUTING_NONE, routing_id_);
- DCHECK(base::ThreadPool::GetInstance())
+ DCHECK(base::ThreadPoolInstance::Get())
<< "Ref. Prerequisite section of post_task.h";
std::pair<RoutingIDWidgetMap::iterator, bool> result =
@@ -447,6 +383,7 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
RenderWidgetHostID(process->GetID(), routing_id_), this));
CHECK(result.second) << "Inserting a duplicate item!";
process_->AddRoute(routing_id_, this);
+ process_->AddObserver(this);
render_process_blocked_state_changed_subscription_ =
process_->RegisterBlockStateChangedCallback(base::BindRepeating(
&RenderWidgetHostImpl::RenderProcessBlockedStateChanged,
@@ -679,7 +616,6 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostImpl, msg)
- IPC_MESSAGE_HANDLER(FrameHostMsg_RenderProcessGone, OnRenderProcessGone)
IPC_MESSAGE_HANDLER(FrameHostMsg_HittestData, OnHittestData)
IPC_MESSAGE_HANDLER(WidgetHostMsg_Close, OnClose)
IPC_MESSAGE_HANDLER(WidgetHostMsg_UpdateScreenRects_ACK,
@@ -764,8 +700,9 @@ void RenderWidgetHostImpl::WasHidden() {
observer.RenderWidgetHostVisibilityChanged(this, false);
}
-void RenderWidgetHostImpl::WasShown(bool record_presentation_time,
- base::TimeTicks tab_switch_start_time) {
+void RenderWidgetHostImpl::WasShown(
+ const base::Optional<RecordTabSwitchTimeRequest>&
+ record_tab_switch_time_request) {
if (!is_hidden_)
return;
@@ -782,8 +719,9 @@ void RenderWidgetHostImpl::WasShown(bool record_presentation_time,
Send(new WidgetMsg_WasShown(
routing_id_,
- record_presentation_time ? base::TimeTicks::Now() : base::TimeTicks(),
- view_->is_evicted(), tab_switch_start_time));
+ record_tab_switch_time_request ? base::TimeTicks::Now()
+ : base::TimeTicks(),
+ view_->is_evicted(), record_tab_switch_time_request));
view_->reset_is_evicted();
process_->UpdateClientPriority(this);
@@ -1318,6 +1256,15 @@ void RenderWidgetHostImpl::WaitForInputProcessed(
SyntheticGestureParams::GestureType type,
SyntheticGestureParams::GestureSourceType source,
base::OnceClosure callback) {
+ // TODO(bokan): Input can be queued and delayed in InputRouterImpl based on
+ // the kind of events we're getting. To be truly robust, we should wait until
+ // those queues are flushed before issuing this message. This will be done in
+ // a follow-up and is the reason for the currently unused type and source
+ // params. https://crbug.com/902446.
+ WaitForInputProcessed(std::move(callback));
+}
+
+void RenderWidgetHostImpl::WaitForInputProcessed(base::OnceClosure callback) {
// TODO(bokan): The RequestPresentationCallback mechanism doesn't seem to
// work in OOPIFs. For now, just callback immediately. Remove when fixed.
// https://crbug.com/924646.
@@ -1326,11 +1273,6 @@ void RenderWidgetHostImpl::WaitForInputProcessed(
return;
}
- // TODO(bokan): Input can be queued and delayed in InputRouterImpl based on
- // the kind of events we're getting. To be truly robust, we should wait until
- // those queues are flushed before issuing this message. This will be done in
- // a follow-up and is the reason for the currently unused type and source
- // params. https://crbug.com/902446.
input_router_->WaitForInputProcessed(std::move(callback));
}
@@ -1497,15 +1439,13 @@ void RenderWidgetHostImpl::ForwardKeyboardEvent(
void RenderWidgetHostImpl::ForwardKeyboardEventWithLatencyInfo(
const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency) {
- ForwardKeyboardEventWithCommands(key_event, latency, nullptr, nullptr,
- nullptr);
+ ForwardKeyboardEventWithCommands(key_event, latency, nullptr, nullptr);
}
void RenderWidgetHostImpl::ForwardKeyboardEventWithCommands(
const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency,
const std::vector<EditCommand>* commands,
- ui::KeyEvent* original_key_event,
bool* update_event) {
TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardKeyboardEvent");
if (owner_delegate_ &&
@@ -1594,26 +1534,10 @@ void RenderWidgetHostImpl::ForwardKeyboardEventWithCommands(
if (commands && !commands->empty())
GetWidgetInputHandler()->SetEditCommandsForNextKeyEvent(*commands);
- std::unique_ptr<KeyEventResultTracker> result_tracker;
- base::WeakPtr<KeyEventResultTracker> result_tracker_weak_ptr;
- // Some tests and/or platforms supply null.
- if (original_key_event) {
- result_tracker =
- std::make_unique<KeyEventResultTracker>(original_key_event);
- result_tracker_weak_ptr = result_tracker->GetWeakPtr();
- }
- auto weak_ref = weak_factory_.GetWeakPtr();
input_router_->SendKeyboardEvent(
key_event_with_latency,
- base::BindOnce(&RenderWidgetHostImpl::OnKeyboardEventAck, weak_ref,
- std::move(result_tracker)));
-
- // Ownership of |result_tracker| is moved to the callback. If the callback was
- // run synchronously, |result_tracker| has been destroyed. OTOH, if the event
- // was sent to the renderer, then |result_tarcker| is still alive and needs
- // to be told the result will be obtained later on.
- if (result_tracker_weak_ptr)
- result_tracker_weak_ptr->PrepareForAsync();
+ base::BindOnce(&RenderWidgetHostImpl::OnKeyboardEventAck,
+ weak_factory_.GetWeakPtr()));
}
void RenderWidgetHostImpl::CreateSyntheticGestureControllerIfNecessary() {
@@ -1829,6 +1753,16 @@ RenderProcessHost::Priority RenderWidgetHostImpl::GetPriority() {
return priority;
}
+void RenderWidgetHostImpl::RenderProcessExited(
+ RenderProcessHost* host,
+ const ChildProcessTerminationInfo& info) {
+ // When the RenderViewHost or the RenderFrameHost own this instance, they
+ // manage its destruction. Otherwise it is owned by the renderer process and
+ // must self-destroy when it exits.
+ if (!owner_delegate_ && !owned_by_render_frame_host_)
+ Destroy(true);
+}
+
mojom::WidgetInputHandler* RenderWidgetHostImpl::GetWidgetInputHandler() {
if (associated_widget_input_handler_)
return associated_widget_input_handler_.get();
@@ -1994,8 +1928,7 @@ void RenderWidgetHostImpl::OnCommitAndDrawCompositorFrame() {
owner_delegate_->RenderWidgetDidCommitAndDrawCompositorFrame();
}
-void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
- int exit_code) {
+void RenderWidgetHostImpl::RendererExited() {
if (!renderer_initialized_)
return;
@@ -2034,7 +1967,7 @@ void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
StopInputEventAckTimeout();
if (view_) {
- view_->RenderProcessGone(status, exit_code);
+ view_->RenderProcessGone();
view_.reset(); // The View should be deleted by RenderProcessGone.
}
@@ -2178,6 +2111,7 @@ void RenderWidgetHostImpl::Destroy(bool also_delete) {
render_process_blocked_state_changed_subscription_.reset();
process_->RemovePriorityClient(this);
+ process_->RemoveObserver(this);
process_->RemoveRoute(routing_id_);
g_routing_id_widget_map.Get().erase(
RenderWidgetHostID(process_->GetID(), routing_id_));
@@ -2235,7 +2169,6 @@ void RenderWidgetHostImpl::ClearDisplayedGraphics() {
}
void RenderWidgetHostImpl::OnKeyboardEventAck(
- std::unique_ptr<KeyEventResultTracker> result_tracker,
const NativeWebKeyboardEventWithLatencyInfo& event,
InputEventAckSource ack_source,
InputEventAckState ack_result) {
@@ -2252,27 +2185,10 @@ void RenderWidgetHostImpl::OnKeyboardEventAck(
// because the user has moved away from us and no longer expect any effect
// of this key event.
if (delegate_ && !processed && !is_hidden() && !event.event.skip_in_browser)
- processed = delegate_->HandleKeyboardEvent(event.event);
+ delegate_->HandleKeyboardEvent(event.event);
// WARNING: This RenderWidgetHostImpl can be deallocated at this point
// (i.e. in the case of Ctrl+W, where the call to
// HandleKeyboardEvent destroys this RenderWidgetHostImpl).
-
- if (result_tracker)
- result_tracker->OnEventProcessingDone(processed ||
- event.event.skip_in_browser);
-}
-
-void RenderWidgetHostImpl::OnRenderProcessGone(int status, int exit_code) {
- // RenderFrameHost owns a RenderWidgetHost when it needs one, in which case
- // it handles destruction.
- if (!owned_by_render_frame_host_) {
- // TODO(evanm): This synchronously ends up calling "delete this".
- // Is that really what we want in response to this message? I'm matching
- // previous behavior of the code here.
- Destroy(true);
- } else {
- RendererExited(static_cast<base::TerminationStatus>(status), exit_code);
- }
}
void RenderWidgetHostImpl::OnHittestData(
@@ -2357,8 +2273,9 @@ void RenderWidgetHostImpl::DidNotProduceFrame(const viz::BeginFrameAck& ack) {
void RenderWidgetHostImpl::DidAllocateSharedBitmap(
mojo::ScopedSharedBufferHandle buffer,
const viz::SharedBitmapId& id) {
- if (!shared_bitmap_manager_->ChildAllocatedSharedBitmap(std::move(buffer),
- id)) {
+ if (!shared_bitmap_manager_->ChildAllocatedSharedBitmap(
+ viz::bitmap_allocation::FromMojoHandle(std::move(buffer)).Map(),
+ id)) {
bad_message::ReceivedBadMessage(GetProcess(),
bad_message::RWH_SHARED_BITMAP);
}
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 f9a68845dc4..654c60e7bde 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -50,6 +50,7 @@
#include "content/common/render_frame_metadata.mojom.h"
#include "content/common/render_widget_surface_properties.h"
#include "content/common/widget.mojom.h"
+#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/common/input_event_ack_state.h"
#include "content/public/common/page_zoom.h"
@@ -124,6 +125,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
public InputRouterImplClient,
public InputDispositionHandler,
public RenderProcessHostImpl::PriorityClient,
+ public RenderProcessHostObserver,
public TouchEmulatorClient,
public SyntheticGestureController::Delegate,
public viz::mojom::CompositorFrameSink,
@@ -246,6 +248,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// RenderProcessHostImpl::PriorityClient implementation.
RenderProcessHost::Priority GetPriority() override;
+ // RenderProcessHostObserver implementation.
+ void RenderProcessExited(RenderProcessHost* host,
+ const ChildProcessTerminationInfo& info) override;
+
// Notification that the screen info has changed.
void NotifyScreenInfoChanged();
@@ -307,8 +313,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// Called to notify the RenderWidget that it has been hidden or restored from
// having been hidden.
void WasHidden();
- void WasShown(bool record_presentation_time,
- base::TimeTicks tab_switch_start_time = base::TimeTicks());
+ void WasShown(const base::Optional<RecordTabSwitchTimeRequest>&
+ record_tab_switch_time_request);
// Send a WidgetMsg_WasHidden message to the RenderWidget, without caring
// about the visibility state of the RenderWidgetHostImpl. This is used to
@@ -397,7 +403,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency,
const std::vector<EditCommand>* commands,
- ui::KeyEvent* original_key_event,
bool* update_event = nullptr);
// Forwards the given message to the renderer. These are called by the view
@@ -423,6 +428,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl
SyntheticGestureParams::GestureSourceType source,
base::OnceClosure callback);
+ // Resolves the given callback once all effects of previously forwarded input
+ // have been fully realized (i.e. resulting compositor frame has been drawn,
+ // swapped, and presented).
+ void WaitForInputProcessed(base::OnceClosure callback);
+
// Retrieve an iterator over any RenderWidgetHosts that are immediately
// embedded within this one. This does not return hosts that are embedded
// indirectly (i.e. nested within embedded hosts).
@@ -588,7 +598,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// Called when we receive a notification indicating that the renderer process
// is gone. This will reset our state so that our state will be consistent if
// a new renderer is created.
- void RendererExited(base::TerminationStatus status, int exit_code);
+ void RendererExited();
// Called from a RenderFrameHost when the text selection has changed.
void SelectionChanged(const base::string16& text,
@@ -816,8 +826,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
RenderProcessHost*,
RenderWidgetHost*);
- class KeyEventResultTracker;
-
// Tell this object to destroy itself. If |also_delete| is specified, the
// destructor is called as well.
void Destroy(bool also_delete);
@@ -828,13 +836,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// InputRouter::SendKeyboardEvent() callbacks to this. This may be called
// synchronously.
- void OnKeyboardEventAck(std::unique_ptr<KeyEventResultTracker> result_tracker,
- const NativeWebKeyboardEventWithLatencyInfo& event,
+ void OnKeyboardEventAck(const NativeWebKeyboardEventWithLatencyInfo& event,
InputEventAckSource ack_source,
InputEventAckState ack_result);
// IPC message handlers
- void OnRenderProcessGone(int status, int error_code);
void OnClose();
void OnUpdateScreenRectsAck();
void OnRequestSetBounds(const gfx::Rect& bounds);
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 56a24a57097..e7dee4853c6 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
@@ -541,7 +541,7 @@ RenderWidgetHostInputEventRouter::FindMouseWheelEventTarget(
return {nullptr, false, base::nullopt, true, false};
}
-// TODO(riajiang): Get rid of |point_in_screen| since it's not used.
+// TODO(crbug.com/966952): Get rid of |point_in_screen| since it's not used.
RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
RenderWidgetHostViewBase* root_view,
const gfx::PointF& point,
@@ -1221,7 +1221,8 @@ void RenderWidgetHostInputEventRouter::SendGestureScrollBegin(
scroll_begin.data.scroll_begin.delta_x_hint = 0;
scroll_begin.data.scroll_begin.delta_y_hint = 0;
scroll_begin.data.scroll_begin.delta_hint_units =
- blink::WebGestureEvent::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
+ scroll_begin.data.scroll_begin.scrollable_area_element_id = 0;
view->ProcessGestureEvent(
scroll_begin,
ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(
@@ -1244,9 +1245,9 @@ void RenderWidgetHostInputEventRouter::SendGestureScrollEnd(
case blink::WebInputEvent::kGesturePinchEnd:
DCHECK_EQ(blink::WebGestureDevice::kTouchscreen, event.SourceDevice());
scroll_end.data.scroll_end.inertial_phase =
- blink::WebGestureEvent::kUnknownMomentumPhase;
+ blink::WebGestureEvent::InertialPhaseState::kUnknownMomentum;
scroll_end.data.scroll_end.delta_units =
- blink::WebGestureEvent::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
break;
default:
NOTREACHED();
@@ -1263,9 +1264,9 @@ void RenderWidgetHostInputEventRouter::SendGestureScrollEnd(
blink::WebInputEvent::kNoModifiers,
base::TimeTicks::Now(), source_device);
scroll_end.data.scroll_end.inertial_phase =
- blink::WebGestureEvent::kUnknownMomentumPhase;
+ blink::WebGestureEvent::InertialPhaseState::kUnknownMomentum;
scroll_end.data.scroll_end.delta_units =
- blink::WebGestureEvent::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
view->ProcessGestureEvent(
scroll_end,
ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(scroll_end));
@@ -1735,7 +1736,7 @@ RenderWidgetHostInputEventRouter::FindViewFromFrameSinkId(
bool RenderWidgetHostInputEventRouter::ShouldContinueHitTesting(
RenderWidgetHostViewBase* target_view) const {
- // TODO(kenrb, riajiang): It would be better if we could determine if the
+ // TODO(kenrb): It would be better if we could determine if the
// event's point has a chance of hitting an embedded child and returning
// false if not, but Viz hit testing does not easily support that. This
// currently assumes any embedded view could potentially be the event
diff --git a/chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
index 3643d081b98..d38f00f73f6 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
@@ -25,7 +25,6 @@
#include "content/test/test_render_view_host.h"
#include "services/viz/public/interfaces/hit_test/input_target_client.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/ui_base_features.h"
namespace content {
@@ -266,11 +265,8 @@ class RenderWidgetHostInputEventRouterTest : public testing::Test {
child.view.get(), parent_view, view_root_.get(),
false /* use_zoom_for_device_scale_factor */);
- // This check often fails in Mash. https://crbug.com/933876
- if (!features::IsMultiProcessMash()) {
- EXPECT_EQ(child.view.get(), rwhier()->FindViewFromFrameSinkId(
- child.view->GetFrameSinkId()));
- }
+ EXPECT_EQ(child.view.get(),
+ rwhier()->FindViewFromFrameSinkId(child.view->GetFrameSinkId()));
return child;
}
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 869dcdb2504..6ac81d693e1 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -15,7 +15,6 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.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"
#include "base/time/time.h"
@@ -275,6 +274,9 @@ class FakeRenderFrameMetadataObserver
mojom::RenderFrameMetadataObserverClientPtrInfo client_info);
~FakeRenderFrameMetadataObserver() override {}
+#if defined(OS_ANDROID)
+ void ReportAllRootScrollsForAccessibility(bool enabled) override {}
+#endif
void ReportAllFrameSubmissionsForTesting(bool enabled) override {}
private:
@@ -443,9 +445,7 @@ class RenderWidgetHostTest : public testing::Test {
: process_(nullptr),
handle_key_press_event_(false),
handle_mouse_event_(false),
- last_simulated_event_time_(ui::EventTimeForNow()) {
- feature_list_.Init();
- }
+ last_simulated_event_time_(ui::EventTimeForNow()) {}
~RenderWidgetHostTest() override {}
bool KeyPressEventCallback(const NativeWebKeyboardEvent& /* event */) {
@@ -716,7 +716,6 @@ class RenderWidgetHostTest : public testing::Test {
SyntheticWebTouchEvent touch_event_;
TestBrowserThreadBundle thread_bundle_;
- base::test::ScopedFeatureList feature_list_;
viz::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest);
@@ -925,7 +924,7 @@ TEST_F(RenderWidgetHostTest, ResizeScreenInfo) {
WidgetMsg_SynchronizeVisualProperties::ID));
}
-// Test for crbug.com/25097. If a renderer crashes between a resize and the
+// Test for crbug.com/25097. If a renderer crashes between a resize and the
// corresponding update message, we must be sure to clear the visual properties
// ACK logic.
TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
@@ -941,11 +940,11 @@ TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
WidgetMsg_SynchronizeVisualProperties::ID));
- // Simulate a renderer crash before the update message. Ensure all the
- // visual properties ACK logic is cleared. Must clear the view first so it
- // doesn't get deleted.
+ // Simulate a renderer crash before the update message. Ensure all the visual
+ // properties ACK logic is cleared. Must clear the view first so it doesn't
+ // get deleted.
host_->SetView(nullptr);
- host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
+ host_->RendererExited();
EXPECT_FALSE(host_->visual_properties_ack_pending_);
EXPECT_EQ(nullptr, host_->old_visual_properties_);
@@ -959,8 +958,7 @@ TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
TEST_F(RenderWidgetHostTest, Background) {
std::unique_ptr<RenderWidgetHostViewBase> view;
#if defined(USE_AURA)
- view.reset(new RenderWidgetHostViewAura(
- host_.get(), false, false /* is_mus_browser_plugin_guest */));
+ view.reset(new RenderWidgetHostViewAura(host_.get(), false));
// TODO(derat): Call this on all platforms: http://crbug.com/102450.
view->InitAsChild(nullptr);
#elif defined(OS_ANDROID)
@@ -1022,7 +1020,7 @@ TEST_F(RenderWidgetHostTest, HideShowMessages) {
// Now unhide.
process_->sink().ClearMessages();
- host_->WasShown(false /* record_presentation_time */);
+ host_->WasShown(base::nullopt /* record_tab_switch_time_request */);
EXPECT_FALSE(host_->is_hidden_);
// It should have sent out a restored message.
@@ -1327,7 +1325,7 @@ TEST_F(RenderWidgetHostTest, InputEventAckTimeoutDisabledForInputWhenHidden) {
// Showing the widget should restore the timeout, as the events have
// not yet been ack'ed.
- host_->WasShown(false /* record_presentation_time */);
+ host_->WasShown(base::nullopt /* record_tab_switch_time_request */);
RunLoopFor(TimeDelta::FromMicroseconds(2));
EXPECT_TRUE(delegate_->unresponsive_timer_fired());
}
@@ -1623,7 +1621,7 @@ TEST_F(RenderWidgetHostTest, InputEventRWHLatencyComponent) {
TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) {
// RendererExited will delete the view.
host_->SetView(new TestView(host_.get()));
- host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
+ host_->RendererExited();
// Make sure the input router is in a fresh state.
ASSERT_FALSE(host_->input_router()->HasPendingEvents());
@@ -1633,10 +1631,10 @@ TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) {
TEST_F(RenderWidgetHostTest, RendererExitedResetsIsHidden) {
// RendererExited will delete the view.
host_->SetView(new TestView(host_.get()));
- host_->WasShown(false /* record_presentation_time */);
+ host_->WasShown(base::nullopt /* record_tab_switch_time_request */);
ASSERT_FALSE(host_->is_hidden());
- host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
+ host_->RendererExited();
ASSERT_TRUE(host_->is_hidden());
// Make sure the input router is in a fresh state.
@@ -1658,8 +1656,7 @@ TEST_F(RenderWidgetHostTest, VisualProperties) {
}
// Make sure no dragging occurs after renderer exited. See crbug.com/704832.
-// DISABLED for crbug.com/908012
-TEST_F(RenderWidgetHostTest, DISABLED_RendererExitedNoDrag) {
+TEST_F(RenderWidgetHostTest, RendererExitedNoDrag) {
host_->SetView(new TestView(host_.get()));
EXPECT_EQ(delegate_->mock_delegate_view()->start_dragging_count(), 0);
@@ -1675,7 +1672,7 @@ TEST_F(RenderWidgetHostTest, DISABLED_RendererExitedNoDrag) {
EXPECT_EQ(delegate_->mock_delegate_view()->start_dragging_count(), 1);
// Simulate that renderer exited due navigation to the next page.
- host_->RendererExited(base::TERMINATION_STATUS_NORMAL_TERMINATION, 0);
+ host_->RendererExited();
EXPECT_FALSE(host_->GetView());
host_->OnStartDragging(drop_data, drag_operation, SkBitmap(), gfx::Vector2d(),
event_info);
@@ -1951,7 +1948,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_RendererCrash) {
EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
- host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
+ host_->RendererExited();
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
host_->Init();
@@ -1966,7 +1963,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_RendererCrash) {
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
- host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
+ host_->RendererExited();
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
host_->SetView(view_.get());
@@ -2044,20 +2041,20 @@ TEST_F(RenderWidgetHostTest, RenderWidgetSurfaceProperties) {
TEST_F(RenderWidgetHostTest, NavigateInBackgroundShowsBlank) {
// When visible, navigation does not immediately call into
// ClearDisplayedGraphics.
- host_->WasShown(false /* record_presentation_time */);
+ host_->WasShown(base::nullopt /* record_tab_switch_time_request */);
host_->DidNavigate(5);
EXPECT_FALSE(host_->new_content_rendering_timeout_fired());
// Hide then show. ClearDisplayedGraphics must be called.
host_->WasHidden();
- host_->WasShown(false /* record_presentation_time */);
+ host_->WasShown(base::nullopt /* record_tab_switch_time_request */);
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(false /* record_presentation_time */);
+ host_->WasShown(base::nullopt /* record_tab_switch_time_request */);
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 ae5aed0ba44..f83b5c00f90 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
@@ -9,6 +9,7 @@
#include <utility>
#include "base/android/build_info.h"
+#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
@@ -194,6 +195,12 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
// layer is managed by the DelegatedFrameHost.
view_.SetLayer(cc::Layer::Create());
view_.set_event_handler(this);
+
+ // If we're showing at creation time, we won't get a visibility change, so
+ // generate our initial LocalSurfaceId here.
+ if (is_showing_)
+ local_surface_id_allocator_.GenerateId();
+
if (using_browser_compositor_) {
delegated_frame_host_client_ =
std::make_unique<DelegatedFrameHostClientAndroid>(this);
@@ -202,7 +209,6 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
delegated_frame_host_client_.get(), host()->GetFrameSinkId(),
features::IsSurfaceSynchronizationEnabled());
if (is_showing_) {
- local_surface_id_allocator_.GenerateId();
delegated_frame_host_->WasShown(
local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
.local_surface_id(),
@@ -349,6 +355,16 @@ void RenderWidgetHostViewAndroid::OnRenderFrameMetadataChangedBeforeActivation(
if (!features::IsSurfaceSynchronizationEnabled())
return;
+ bool is_transparent = metadata.has_transparent_background;
+ SkColor root_background_color = metadata.root_background_color;
+
+ if (!using_browser_compositor_) {
+ // DevTools ScreenCast support for Android WebView.
+ last_devtools_frame_metadata_.emplace(metadata);
+ // Android WebView ignores transparent background.
+ is_transparent = false;
+ }
+
bool is_mobile_optimized = IsMobileOptimizedFrame(
metadata.page_scale_factor, metadata.min_page_scale_factor,
metadata.max_page_scale_factor, metadata.scrollable_viewport_size,
@@ -402,9 +418,8 @@ void RenderWidgetHostViewAndroid::OnRenderFrameMetadataChangedBeforeActivation(
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);
+ SetContentBackgroundColor(is_transparent ? SK_ColorTRANSPARENT
+ : root_background_color);
if (overscroll_controller_) {
overscroll_controller_->OnFrameMetadataUpdated(
@@ -425,6 +440,11 @@ void RenderWidgetHostViewAndroid::OnRenderFrameMetadataChangedBeforeActivation(
min_page_scale_ = metadata.min_page_scale_factor;
max_page_scale_ = metadata.max_page_scale_factor;
current_surface_size_ = metadata.viewport_size_in_pixels;
+
+ // With SurfaceSync we no longer call EvictFrameIfNecessary on every metadata
+ // change. We must still call UpdateWebViewBackgroundColorIfNecessary to
+ // maintain the associated background color changes.
+ UpdateWebViewBackgroundColorIfNecessary();
}
void RenderWidgetHostViewAndroid::Focus() {
@@ -490,10 +510,6 @@ gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() {
return default_bounds_;
gfx::Size size(view_.GetSize());
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableOSKOverscroll)) {
- size.Enlarge(0, view_.GetSystemWindowInsetBottom() / view_.GetDipScale());
- }
return gfx::Rect(size);
}
@@ -832,8 +848,7 @@ void RenderWidgetHostViewAndroid::FocusedNodeChanged(
ime_adapter_android_->FocusedNodeChanged(is_editable_node);
}
-void RenderWidgetHostViewAndroid::RenderProcessGone(
- base::TerminationStatus status, int error_code) {
+void RenderWidgetHostViewAndroid::RenderProcessGone() {
Destroy();
}
@@ -983,6 +998,18 @@ void RenderWidgetHostViewAndroid::EvictFrameIfNecessary() {
}
}
+void RenderWidgetHostViewAndroid::UpdateWebViewBackgroundColorIfNecessary() {
+ // Before SurfaceSync, Android WebView had a bug the BG color was always set
+ // to black when fullscreen (see https://crbug.com/961223#c5). As
+ // applications came to rely on this behavior, preserve it here.
+ if (!features::IsSurfaceSynchronizationEnabled())
+ return;
+ if (!using_browser_compositor_ &&
+ host()->delegate()->IsFullscreenForCurrentTab()) {
+ SetContentBackgroundColor(SK_ColorBLACK);
+ }
+}
+
void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
@@ -1036,30 +1063,53 @@ bool RenderWidgetHostViewAndroid::RequestRepaintForTesting() {
void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
viz::CompositorFrameMetadata metadata) {
- if (!view_.parent())
+ // TODO(ericrk): Remove this function once surface synchronization feature is
+ // no longer optional.
+ 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);
-
- if (host() && host()->input_router()) {
- host()->input_router()->NotifySiteIsMobileOptimized(is_mobile_optimized);
- }
-
- if (host() && metadata.frame_token)
- host()->DidProcessFrame(metadata.frame_token);
-
- // This is a subset of OnSwapCompositorFrame() used in the synchronous
- // compositor flow.
- OnFrameMetadataUpdated(metadata.Clone(), false);
+ if (!view_.parent())
+ return;
- // DevTools ScreenCast support for Android WebView.
- RenderFrameHost* frame_host = RenderViewHost::From(host())->GetMainFrame();
- if (frame_host) {
- RenderFrameDevToolsAgentHost::SignalSynchronousSwapCompositorFrame(
- frame_host, std::move(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);
+
+ // This is a subset of OnSwapCompositorFrame() used in the synchronous
+ // compositor flow.
+ OnFrameMetadataUpdated(metadata.Clone(), false);
+
+ // DevTools ScreenCast support for Android WebView.
+ last_devtools_frame_metadata_.emplace(metadata);
+}
+
+void RenderWidgetHostViewAndroid::FrameTokenChangedForSynchronousCompositor(
+ uint32_t frame_token,
+ const gfx::ScrollOffset& root_scroll_offset) {
+ if (host() && frame_token) {
+ host()->DidProcessFrame(frame_token);
+
+ // DevTools ScreenCast support for Android WebView. Don't call this if
+ // we're currently in SynchronousCopyContents, as this can lead to
+ // redundant copies.
+ if (!in_sync_copy_contents_) {
+ RenderFrameHost* frame_host =
+ RenderViewHost::From(host())->GetMainFrame();
+ if (frame_host && last_devtools_frame_metadata_) {
+ // Update our |root_scroll_offset|, as changes to this value do not
+ // trigger a new RenderFrameMetadata, and it may be out of date. This
+ // is needed for devtools DOM node selection.
+ DevToolsFrameMetadata updated_metadata = *last_devtools_frame_metadata_;
+ updated_metadata.root_scroll_offset =
+ gfx::ScrollOffsetToVector2dF(root_scroll_offset);
+ RenderFrameDevToolsAgentHost::SignalSynchronousSwapCompositorFrame(
+ frame_host, updated_metadata);
+ }
+ }
}
}
@@ -1162,6 +1212,10 @@ void RenderWidgetHostViewAndroid::SynchronousCopyContents(
const gfx::Rect& src_subrect_dip,
const gfx::Size& dst_size_in_pixel,
base::OnceCallback<void(const SkBitmap&)> callback) {
+ // Track that we're in this function to avoid repeatedly calling DevTools
+ // capture logic.
+ base::AutoReset<bool> in_sync_copy_contents(&in_sync_copy_contents_, true);
+
// Note: When |src_subrect| is empty, a conversion from the view size must
// be made instead of using |current_frame_size_|. The latter sometimes also
// includes extra height for the toolbar UI, which is not intended for
@@ -1298,6 +1352,7 @@ void RenderWidgetHostViewAndroid::UpdateTouchSelectionController(
DCHECK(touch_selection_controller_client_manager_);
touch_selection_controller_client_manager_->UpdateClientSelectionBounds(
selection.start, selection.end, this, nullptr);
+ OnUpdateScopedSelectionHandles();
// Set parameters for adaptive handle orientation.
gfx::SizeF viewport_size(scrollable_viewport_size_dip);
@@ -1384,7 +1439,7 @@ void RenderWidgetHostViewAndroid::ShowInternal() {
}
}
- host()->WasShown(false /* record_presentation_time */);
+ host()->WasShown(base::nullopt /* record_tab_switch_time_request */);
if (delegated_frame_host_) {
delegated_frame_host_->WasShown(
@@ -1489,6 +1544,8 @@ void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
if (compositor) {
delegated_frame_host_->AttachToCompositor(compositor);
}
+
+ OnUpdateScopedSelectionHandles();
}
void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
@@ -1504,6 +1561,7 @@ void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
is_window_activity_started_ = true;
is_window_visible_ = true;
observing_root_window_ = false;
+ OnUpdateScopedSelectionHandles();
SendBeginFramePaused();
view_.GetWindowAndroid()->RemoveObserver(this);
if (!using_browser_compositor_)
@@ -1638,7 +1696,7 @@ InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
if (gesture_event.GetType() ==
blink::WebInputEvent::kGestureScrollUpdate &&
gesture_event.data.scroll_update.inertial_phase ==
- blink::WebGestureEvent::kMomentumPhase) {
+ blink::WebGestureEvent::InertialPhaseState::kMomentum) {
host_->StopFling();
}
@@ -1656,7 +1714,7 @@ InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
if (input_event.GetType() == blink::WebInputEvent::kGestureTapDown ||
input_event.GetType() == blink::WebInputEvent::kTouchStart) {
- GpuProcessHost::CallOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED,
false /* force_create */, base::Bind(&WakeUpGpu));
}
@@ -2025,9 +2083,13 @@ RenderWidgetHostViewAndroid::GetTouchSelectionControllerClientManager() {
const viz::LocalSurfaceIdAllocation&
RenderWidgetHostViewAndroid::GetLocalSurfaceIdAllocation() const {
- if (!delegated_frame_host_)
+ // Don't return an local surface ID for webview unless we're using
+ // SurfaceSynchronization.
+ if (!using_browser_compositor_ &&
+ !features::IsSurfaceSynchronizationEnabled()) {
return viz::ParentLocalSurfaceIdAllocator::
InvalidLocalSurfaceIdAllocation();
+ }
return local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation();
}
@@ -2082,6 +2144,9 @@ void RenderWidgetHostViewAndroid::OnSizeChanged() {
void RenderWidgetHostViewAndroid::OnPhysicalBackingSizeChanged() {
EvictFrameIfNecessary();
+ // We may need to update the background color to match pre-surface-sync
+ // behavior of EvictFrameIfNecessary.
+ UpdateWebViewBackgroundColorIfNecessary();
SynchronizeVisualProperties(
cc::DeadlinePolicy::UseSpecifiedDeadline(
ui::DelegatedFrameHostAndroid::ResizeTimeoutFrames()),
@@ -2316,6 +2381,9 @@ void RenderWidgetHostViewAndroid::ComputeEventLatencyOSTouchHistograms(
}
void RenderWidgetHostViewAndroid::CreateOverscrollControllerIfPossible() {
+#if defined(DISABLE_OVERSCROLL)
+ return;
+#else
// an OverscrollController is already set
if (overscroll_controller_)
return;
@@ -2351,6 +2419,7 @@ void RenderWidgetHostViewAndroid::CreateOverscrollControllerIfPossible() {
overscroll_controller_ = std::make_unique<OverscrollControllerAndroid>(
overscroll_refresh_handler, compositor, view_.GetDipScale());
+#endif
}
void RenderWidgetHostViewAndroid::SetOverscrollControllerForTesting(
@@ -2458,4 +2527,29 @@ void RenderWidgetHostViewAndroid::WasEvicted() {
}
}
+void RenderWidgetHostViewAndroid::OnUpdateScopedSelectionHandles() {
+ if (!observing_root_window_ ||
+ !touch_selection_controller_client_manager_->has_active_selection()) {
+ scoped_selection_handles_.reset();
+ return;
+ }
+
+ if (!scoped_selection_handles_) {
+ scoped_selection_handles_ =
+ std::make_unique<ui::WindowAndroid::ScopedSelectionHandles>(
+ view_.GetWindowAndroid());
+ }
+}
+
+void RenderWidgetHostViewAndroid::SetWebContentsAccessibility(
+ WebContentsAccessibilityAndroid* web_contents_accessibility) {
+ web_contents_accessibility_ = web_contents_accessibility;
+
+ if (host()) {
+ host()
+ ->render_frame_metadata_provider()
+ ->ReportAllRootScrollsForAccessibility(!!web_contents_accessibility_);
+ }
+}
+
} // 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 4f755503c34..45bef1f2ae3 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
@@ -24,6 +24,7 @@
#include "components/viz/common/presentation_feedback_map.h"
#include "components/viz/common/quads/selection.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
+#include "content/browser/devtools/devtools_frame_metadata.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"
@@ -33,6 +34,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "ui/android/delegated_frame_host_android.h"
#include "ui/android/view_android.h"
+#include "ui/android/window_android.h"
#include "ui/android/window_android_observer.h"
#include "ui/base/ui_base_types.h"
#include "ui/events/android/event_handler_android.h"
@@ -125,8 +127,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void SetIsLoading(bool is_loading) override;
void FocusedNodeChanged(bool is_editable_node,
const gfx::Rect& node_bounds_in_screen) override;
- void RenderProcessGone(base::TerminationStatus status,
- int error_code) override;
+ void RenderProcessGone() override;
void Destroy() override;
void SetTooltipText(const base::string16& tooltip_text) override;
void TransformPointToRootSurface(gfx::PointF* point) override;
@@ -304,6 +305,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
int end_adjust);
void SynchronousFrameMetadata(viz::CompositorFrameMetadata frame_metadata);
+ // TODO(ericrk): Ideally we'd reemove |root_scroll_offset| from this function
+ // once we have a reliable way to get it through RenderFrameMetadata.
+ void FrameTokenChangedForSynchronousCompositor(
+ uint32_t frame_token,
+ const gfx::ScrollOffset& root_scroll_offset);
void SetSynchronousCompositorClient(SynchronousCompositorClient* client);
@@ -344,6 +350,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void WasEvicted();
+ void SetWebContentsAccessibility(
+ WebContentsAccessibilityAndroid* web_contents_accessibility);
+
ui::DelegatedFrameHostAndroid* delegated_frame_host_for_testing() {
return delegated_frame_host_.get();
}
@@ -387,6 +396,10 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void EvictFrameIfNecessary();
+ // Helper function to update background color for WebView on fullscreen
+ // changes. See https://crbug.com/961223.
+ void UpdateWebViewBackgroundColorIfNecessary();
+
// DevTools ScreenCast support for Android WebView.
void SynchronousCopyContents(
const gfx::Rect& src_subrect_dip,
@@ -425,6 +438,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void SetTextHandlesHiddenForStylus(bool hide_handles);
void SetTextHandlesHiddenInternal();
+ void OnUpdateScopedSelectionHandles();
+
// The begin frame source being observed. Null if none.
viz::BeginFrameSource* begin_frame_source_;
viz::BeginFrameArgs last_begin_frame_args_;
@@ -486,6 +501,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// may be representing out-of-process iframes).
std::unique_ptr<TouchSelectionControllerClientManagerAndroid>
touch_selection_controller_client_manager_;
+ // Notifies the WindowAndroid when the page has active selection handles.
+ std::unique_ptr<ui::WindowAndroid::ScopedSelectionHandles>
+ scoped_selection_handles_;
// Bounds to use if we have no backing WebContents.
gfx::Rect default_bounds_;
@@ -528,6 +546,17 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
viz::PresentationFeedbackMap presentation_feedbacks_;
+ // Tracks whether we are in SynchronousCopyContents to avoid repeated calls
+ // into DevTools capture logic.
+ // TODO(ericrk): Make this more robust.
+ bool in_sync_copy_contents_ = false;
+
+ // A cached copy of the most up to date DevToolsFrameMetadata, computed from
+ // either RenderFrameMetadata or CompositorFrameMetadata.
+ base::Optional<DevToolsFrameMetadata> last_devtools_frame_metadata_;
+
+ WebContentsAccessibilityAndroid* web_contents_accessibility_ = nullptr;
+
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 8ab45cb1bb3..b54aedcb428 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
@@ -23,7 +23,6 @@
#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/local_surface_id_allocation.h"
-#include "components/viz/host/host_frame_sink_manager.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/bad_message.h"
@@ -47,7 +46,6 @@
#include "content/browser/renderer_host/render_widget_host_view_event_handler.h"
#include "content/browser/renderer_host/ui_events_helper.h"
#include "content/common/input_messages.h"
-#include "content/common/render_widget_window_tree_client_factory.mojom.h"
#include "content/common/text_input_state.h"
#include "content/common/view_messages.h"
#include "content/public/browser/content_browser_client.h"
@@ -56,8 +54,6 @@
#include "content/public/common/use_zoom_for_dsf_policy.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "services/service_manager/public/cpp/interface_provider.h"
-#include "services/ws/common/switches.h"
-#include "services/ws/public/mojom/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/accessibility_switches.h"
@@ -71,7 +67,6 @@
#include "ui/aura/client/transient_window_client.h"
#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/env.h"
-#include "ui/aura/mus/window_port_mus.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_observer.h"
@@ -79,11 +74,9 @@
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/hit_test.h"
#include "ui/base/ime/input_method.h"
-#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/base/ui_base_types.h"
-#include "ui/compositor/compositor_vsync_manager.h"
#include "ui/compositor/dip_util.h"
#include "ui/display/screen.h"
#include "ui/events/blink/blink_event_util.h"
@@ -146,16 +139,6 @@ using blink::WebTouchEvent;
namespace content {
-namespace {
-
-// Callback from embedding the renderer.
-void EmbedCallback(bool result) {
- if (!result)
- DVLOG(1) << "embed failed";
-}
-
-} // namespace
-
#if defined(OS_WIN)
// This class implements the ui::InputMethodKeyboardControllerObserver interface
@@ -347,10 +330,8 @@ class RenderWidgetHostViewAura::WindowAncestorObserver
RenderWidgetHostViewAura::RenderWidgetHostViewAura(
RenderWidgetHost* widget_host,
- bool is_guest_view_hack,
- bool is_mus_browser_plugin_guest)
+ bool is_guest_view_hack)
: RenderWidgetHostViewBase(widget_host),
- is_mus_browser_plugin_guest_(is_mus_browser_plugin_guest),
window_(nullptr),
in_shutdown_(false),
in_bounds_changed_(false),
@@ -370,14 +351,10 @@ 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_(features::IsMultiProcessMash()
- ? viz::FrameSinkId()
- : is_guest_view_hack_
- ? AllocateFrameSinkIdForGuestViewHack()
- : host()->GetFrameSinkId()),
+ frame_sink_id_(is_guest_view_hack_ ? AllocateFrameSinkIdForGuestViewHack()
+ : host()->GetFrameSinkId()),
weak_ptr_factory_(this) {
- if (!is_mus_browser_plugin_guest_)
- CreateDelegatedFrameHostClient();
+ CreateDelegatedFrameHostClient();
if (!is_guest_view_hack_)
host()->SetView(this);
@@ -411,8 +388,6 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(
void RenderWidgetHostViewAura::InitAsChild(gfx::NativeView parent_view) {
DCHECK_EQ(widget_type_, WidgetType::kFrame);
- if (is_mus_browser_plugin_guest_)
- return;
CreateAuraWindow(aura::client::WINDOW_TYPE_CONTROL);
if (parent_view)
@@ -425,8 +400,6 @@ void RenderWidgetHostViewAura::InitAsPopup(
RenderWidgetHostView* parent_host_view,
const gfx::Rect& bounds_in_screen) {
DCHECK_EQ(widget_type_, WidgetType::kPopup);
- // Popups never have |is_mus_browser_plugin_guest_| set to true.
- DCHECK(!is_mus_browser_plugin_guest_);
popup_parent_host_view_ =
static_cast<RenderWidgetHostViewAura*>(parent_host_view);
@@ -476,9 +449,6 @@ void RenderWidgetHostViewAura::InitAsPopup(
void RenderWidgetHostViewAura::InitAsFullscreen(
RenderWidgetHostView* reference_host_view) {
DCHECK_EQ(widget_type_, WidgetType::kFrame);
- // Webview Fullscreen doesn't go through InitAsFullscreen(), so
- // |is_mus_browser_plugin_guest_| is always false.
- DCHECK(!is_mus_browser_plugin_guest_);
is_fullscreen_ = true;
CreateAuraWindow(aura::client::WINDOW_TYPE_NORMAL);
window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
@@ -502,9 +472,6 @@ void RenderWidgetHostViewAura::InitAsFullscreen(
}
void RenderWidgetHostViewAura::Show() {
- if (is_mus_browser_plugin_guest_)
- return;
-
// If the viz::LocalSurfaceIdAllocation is invalid, we may have been evicted,
// and no other visual properties have since been changed. Allocate a new id
// and start synchronizing.
@@ -519,15 +486,11 @@ void RenderWidgetHostViewAura::Show() {
}
void RenderWidgetHostViewAura::Hide() {
- if (is_mus_browser_plugin_guest_)
- return;
-
window_->Hide();
WasOccluded();
}
void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
- DCHECK(!is_mus_browser_plugin_guest_);
// For a SetSize operation, we don't care what coordinate system the origin
// of the window is in, it's only important to make sure that the origin
// remains constant after the operation.
@@ -535,7 +498,6 @@ void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
}
void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
- DCHECK(!is_mus_browser_plugin_guest_);
gfx::Point relative_origin(rect.origin());
// RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
@@ -554,7 +516,6 @@ void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
}
gfx::NativeView RenderWidgetHostViewAura::GetNativeView() {
- DCHECK(!is_mus_browser_plugin_guest_);
return window_;
}
@@ -677,13 +638,11 @@ void RenderWidgetHostViewAura::WasUnOccluded() {
if (!host_->is_hidden())
return;
- auto tab_switch_start_time = GetAndResetLastTabChangeStartTime();
+ auto tab_switch_start_state = TakeRecordTabSwitchTimeRequest();
bool has_saved_frame =
delegated_frame_host_ ? delegated_frame_host_->HasSavedFrame() : false;
- const bool renderer_should_record_presentation_time = !has_saved_frame;
- host()->WasShown(renderer_should_record_presentation_time,
- tab_switch_start_time);
+ host()->WasShown(has_saved_frame ? base::nullopt : tab_switch_start_state);
aura::Window* root = window_->GetRootWindow();
if (root) {
@@ -696,11 +655,10 @@ 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(
GetLocalSurfaceIdAllocation().local_surface_id(),
- window_->bounds().size(), record_presentation_time,
- tab_switch_start_time);
+ window_->bounds().size(),
+ has_saved_frame ? tab_switch_start_state : base::nullopt);
}
#if defined(OS_WIN)
@@ -822,8 +780,7 @@ void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
UpdateCursorIfOverSelf();
}
-void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
- int error_code) {
+void RenderWidgetHostViewAura::RenderProcessGone() {
UpdateCursorIfOverSelf();
Destroy();
}
@@ -958,20 +915,6 @@ void RenderWidgetHostViewAura::TransformPointToRootSurface(gfx::PointF* point) {
aura::Window* root = window_->GetRootWindow();
aura::Window::ConvertPointToTarget(window_, root, point);
root->GetRootWindow()->transform().TransformPoint(point);
-
-// On ChromeOS, the root surface is the whole desktop. When using the
-// window-service converting to screen coordinates gives us that.
-#if defined(OS_CHROMEOS)
- if (features::IsUsingWindowService()) {
- aura::client::ScreenPositionClient* screen_client =
- aura::client::GetScreenPositionClient(root);
- if (screen_client) {
- gfx::Point rounded_point(point->x(), point->y());
- screen_client->ConvertPointToScreen(root, &rounded_point);
- *point = gfx::PointF(rounded_point);
- }
- }
-#endif
}
gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
@@ -1055,7 +998,7 @@ void RenderWidgetHostViewAura::GestureEventAck(
// https://crbug.com/797855
if (event_type == blink::WebInputEvent::kGestureScrollUpdate &&
event.data.scroll_update.inertial_phase ==
- blink::WebGestureEvent::kMomentumPhase &&
+ blink::WebGestureEvent::InertialPhaseState::kMomentum &&
overscroll_controller_->overscroll_mode() != OVERSCROLL_NONE) {
StopFling();
}
@@ -1316,7 +1259,7 @@ void RenderWidgetHostViewAura::InsertChar(const ui::KeyEvent& event) {
// Send a blink::WebInputEvent::Char event to |host_|.
ForwardKeyboardEventWithLatencyInfo(
NativeWebKeyboardEvent(event, event.GetCharacter()), *event.latency(),
- nullptr, nullptr);
+ nullptr);
}
}
@@ -1578,8 +1521,8 @@ bool RenderWidgetHostViewAura::ShouldDoLearning() {
return GetTextInputManager() && GetTextInputManager()->should_do_learning();
}
-#if defined(OS_WIN)
-void RenderWidgetHostViewAura::SetCompositionFromExistingText(
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
+bool RenderWidgetHostViewAura::SetCompositionFromExistingText(
const gfx::Range& range,
const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
RenderFrameHostImpl* frame = GetFocusedFrame();
@@ -1588,8 +1531,12 @@ void RenderWidgetHostViewAura::SetCompositionFromExistingText(
range.start(), range.end(), ui_ime_text_spans);
has_composition_text_ = true;
}
+ return true;
}
+#endif
+
+#if defined(OS_WIN)
void RenderWidgetHostViewAura::SetActiveCompositionForAccessibility(
const gfx::Range& range,
const base::string16& active_composition_text,
@@ -1821,14 +1768,6 @@ viz::FrameSinkId RenderWidgetHostViewAura::GetRootFrameSinkId() {
if (!window_ || !window_->GetHost() || !window_->GetHost()->compositor())
return viz::FrameSinkId();
- // In single-process mash the root is provided by Ash. Have
- // HostFrameSinkManager walk the tree to find the right root.
- if (features::IsSingleProcessMash()) {
- base::Optional<viz::FrameSinkId> root =
- GetHostFrameSinkManager()->FindRootFrameSinkId(frame_sink_id_);
- return root ? *root : viz::FrameSinkId();
- }
-
return window_->GetHost()->compositor()->frame_sink_id();
}
@@ -1870,14 +1809,6 @@ void RenderWidgetHostViewAura::FocusedNodeChanged(
#endif
}
-void RenderWidgetHostViewAura::ScheduleEmbed(
- ws::mojom::WindowTreeClientPtr client,
- base::OnceCallback<void(const base::UnguessableToken&)> callback) {
- DCHECK(features::IsMultiProcessMash());
- aura::Env::GetInstance()->ScheduleEmbed(std::move(client),
- std::move(callback));
-}
-
void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
event_handler_->OnScrollEvent(event);
}
@@ -2088,7 +2019,6 @@ RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
DCHECK(!window_);
- DCHECK(!is_mus_browser_plugin_guest_);
window_ = new aura::Window(this);
window_->SetName("RenderWidgetHostViewAura");
event_handler_->set_window(window_);
@@ -2107,18 +2037,6 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
// Init(), because it needs to have the layer.
if (frame_sink_id_.is_valid())
window_->SetEmbedFrameSinkId(frame_sink_id_);
-
- if (!features::IsMultiProcessMash())
- return;
-
- // Embed the renderer into the Window.
- // Use kEmbedFlagEmbedderControlsVisibility so that the renderer can't change
- // the visibility of |window_|.
- aura::WindowPortMus::Get(window_)->Embed(
- GetWindowTreeClientFromRenderer(),
- ws::mojom::kEmbedFlagEmbedderInterceptsEvents |
- ws::mojom::kEmbedFlagEmbedderControlsVisibility,
- base::BindOnce(&EmbedCallback));
}
void RenderWidgetHostViewAura::CreateDelegatedFrameHostClient() {
@@ -2140,9 +2058,6 @@ void RenderWidgetHostViewAura::CreateDelegatedFrameHostClient() {
}
void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
- if (is_mus_browser_plugin_guest_)
- return;
-
if (host()->GetProcess()->FastShutdownStarted())
return;
@@ -2239,8 +2154,6 @@ void RenderWidgetHostViewAura::OnDidUpdateVisualPropertiesComplete(
// viz::LocalSurfaceId. However we do not want to embed surfaces while
// hidden. Nor do we want to embed invalid ids when we are evicted. Becoming
// visible will generate a new id, if necessary, and begin embedding.
- // TODO(ejoe): Change the LocalSurfaceIdAllocation so that it can pause the
- // elpased time for surface embedding. crbug/949967.
window_->UpdateLocalSurfaceIdFromEmbeddedClient(
metadata.local_surface_id_allocation);
} else {
@@ -2474,7 +2387,6 @@ void RenderWidgetHostViewAura::DetachFromInputMethod() {
void RenderWidgetHostViewAura::ForwardKeyboardEventWithLatencyInfo(
const NativeWebKeyboardEvent& event,
const ui::LatencyInfo& latency,
- ui::KeyEvent* original_key_event,
bool* update_event) {
RenderWidgetHostImpl* target_host = host();
@@ -2501,14 +2413,14 @@ void RenderWidgetHostViewAura::ForwardKeyboardEventWithLatencyInfo(
it->argument()));
}
- target_host->ForwardKeyboardEventWithCommands(
- event, latency, &edit_commands, original_key_event, update_event);
+ target_host->ForwardKeyboardEventWithCommands(event, latency,
+ &edit_commands, update_event);
return;
}
#endif
- target_host->ForwardKeyboardEventWithCommands(
- event, latency, nullptr, original_key_event, update_event);
+ target_host->ForwardKeyboardEventWithCommands(event, latency, nullptr,
+ update_event);
}
void RenderWidgetHostViewAura::CreateSelectionController() {
@@ -2523,7 +2435,7 @@ void RenderWidgetHostViewAura::CreateSelectionController() {
}
void RenderWidgetHostViewAura::OnDidNavigateMainFrameToNewPage() {
- window_->env()->gesture_recognizer()->CancelActiveTouches(window_);
+ aura::Env::GetInstance()->gesture_recognizer()->CancelActiveTouches(window_);
}
const viz::FrameSinkId& RenderWidgetHostViewAura::GetFrameSinkId() const {
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 1bcc62bf485..451a72ce0d9 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
@@ -94,10 +94,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
//
// TODO(lazyboy): Remove |is_guest_view_hack| once BrowserPlugin has migrated
// to use RWHVChildFrame (http://crbug.com/330264).
- // |is_mus_browser_plugin_guest| can be removed at the same time.
- RenderWidgetHostViewAura(RenderWidgetHost* host,
- bool is_guest_view_hack,
- bool is_mus_browser_plugin_guest);
+ RenderWidgetHostViewAura(RenderWidgetHost* host, bool is_guest_view_hack);
// RenderWidgetHostView implementation.
void InitAsChild(gfx::NativeView parent_view) override;
@@ -131,8 +128,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void DisplayCursor(const WebCursor& cursor) override;
CursorManager* GetCursorManager() override;
void SetIsLoading(bool is_loading) override;
- void RenderProcessGone(base::TerminationStatus status,
- int error_code) override;
+ void RenderProcessGone() override;
void Destroy() override;
void SetTooltipText(const base::string16& tooltip_text) override;
void DisplayTooltipText(const base::string16& tooltip_text) override;
@@ -195,12 +191,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
gfx::PointF* transformed_point) override;
viz::FrameSinkId GetRootFrameSinkId() override;
viz::SurfaceId GetCurrentSurfaceId() const override;
-
void FocusedNodeChanged(bool is_editable_node,
const gfx::Rect& node_bounds_in_screen) override;
- void ScheduleEmbed(ws::mojom::WindowTreeClientPtr client,
- base::OnceCallback<void(const base::UnguessableToken&)>
- callback) override;
void OnSynchronizedDisplayPropertiesChanged() override;
viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
const cc::RenderFrameMetadata& metadata) override;
@@ -241,11 +233,13 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
ukm::SourceId GetClientSourceForMetrics() const override;
bool ShouldDoLearning() override;
-#if defined(OS_WIN)
- // Overridden from ui::TextInputClient(Windows only):
- void SetCompositionFromExistingText(
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
+ bool SetCompositionFromExistingText(
const gfx::Range& range,
const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
+#endif
+
+#if defined(OS_WIN)
// API to notify accessibility whether there is an active composition
// from TSF or not.
// It notifies the composition range, composition text and whether the
@@ -343,7 +337,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
gfx::Rect ConvertRectToScreen(const gfx::Rect& rect) const override;
void ForwardKeyboardEventWithLatencyInfo(const NativeWebKeyboardEvent& event,
const ui::LatencyInfo& latency,
- ui::KeyEvent* original_key_event,
bool* update_event) override;
RenderFrameHostImpl* GetFocusedFrame() const;
bool NeedsMouseCapture() override;
@@ -589,8 +582,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Called to process a display metrics change.
void ProcessDisplayMetricsChanged();
- const bool is_mus_browser_plugin_guest_;
-
// NOTE: this is null if |is_mus_browser_plugin_guest_| is true.
aura::Window* window_;
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 1c6ec4995ba..1d12735edca 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
@@ -101,7 +101,6 @@
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/input_method_keyboard_controller.h"
#include "ui/base/ime/mock_input_method.h"
-#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/base/ui_base_types.h"
#include "ui/compositor/compositor.h"
@@ -263,9 +262,7 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
public:
FakeRenderWidgetHostViewAura(RenderWidgetHost* widget,
bool is_guest_view_hack)
- : RenderWidgetHostViewAura(widget,
- is_guest_view_hack,
- false /* is_mus_browser_plugin_guest */),
+ : RenderWidgetHostViewAura(widget, is_guest_view_hack),
is_guest_view_hack_(is_guest_view_hack),
delegated_frame_host_client_(
new FakeDelegatedFrameHostClientAura(this)) {
@@ -570,9 +567,8 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
parent_host_ = MockRenderWidgetHostImpl::Create(delegates_.back().get(),
process_host_, routing_id);
delegates_.back()->set_widget_host(parent_host_);
- const bool is_mus_browser_plugin_guest = false;
- parent_view_ = new RenderWidgetHostViewAura(
- parent_host_, is_guest_view_hack_, is_mus_browser_plugin_guest);
+ parent_view_ =
+ new RenderWidgetHostViewAura(parent_host_, is_guest_view_hack_);
parent_view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(parent_view_->GetNativeView(),
aura_test_helper_->root_window(),
@@ -3063,10 +3059,6 @@ 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 (features::IsMultiProcessMash())
- return;
-
gfx::Size view_size(100, 100);
gfx::Rect view_rect(view_size);
@@ -3097,10 +3089,8 @@ TEST_F(RenderWidgetHostViewAuraTest, ReturnedResources) {
TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) {
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
- if (features::IsVizDisplayCompositorEnabled() ||
- features::IsMultiProcessMash()) {
+ if (features::IsVizDisplayCompositorEnabled())
return;
- }
viz::FakeSurfaceObserver manager_observer;
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
@@ -3241,10 +3231,6 @@ TEST_F(RenderWidgetHostViewAuraTest, ZeroSizeStillGetsLocalSurfaceId) {
}
TEST_F(RenderWidgetHostViewAuraTest, BackgroundColorMatchesCompositorFrame) {
- // TODO: fix for mash.
- if (features::IsMultiProcessMash())
- return;
-
gfx::Size frame_size(100, 100);
parent_local_surface_id_allocator_.GenerateId();
viz::LocalSurfaceId local_surface_id =
@@ -3416,10 +3402,6 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_Resize) {
// This test verifies that the primary SurfaceId is populated on resize.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
- // Early out because DelegatedFrameHost is not used in mash.
- if (features::IsMultiProcessMash())
- return;
-
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
@@ -3438,10 +3420,6 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
// factor changes.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DeviceScaleFactorChanges) {
- // TODO: fix for mash.
- if (features::IsMultiProcessMash())
- return;
-
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
@@ -3466,10 +3444,8 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
CompositorFrameSinkChange) {
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
- if (features::IsVizDisplayCompositorEnabled() ||
- features::IsMultiProcessMash()) {
+ if (features::IsVizDisplayCompositorEnabled())
return;
- }
gfx::Rect view_rect(100, 100);
gfx::Size frame_size = view_rect.size();
@@ -3503,10 +3479,6 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// RenderWidgetHostViewAuraTest.DiscardDelegatedFrame.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DiscardDelegatedFrames) {
- // Early out because DelegatedFrameHost is not used in mash.
- if (features::IsMultiProcessMash())
- return;
-
// Make sure |parent_view_| is evicted to avoid interfering with the code
// below.
parent_view_->Hide();
@@ -3623,10 +3595,6 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// Test that changing the memory pressure should delete saved frames. This test
// only applies to ChromeOS.
TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithMemoryPressure) {
- // Early out because DelegatedFrameHost is not used in mash.
- if (features::IsMultiProcessMash())
- return;
-
// Make sure |parent_view_| is evicted to avoid interfering with the code
// below.
parent_view_->Hide();
@@ -3732,10 +3700,8 @@ TEST_F(RenderWidgetHostViewAuraTest, SourceEventTypeExistsInLatencyInfo) {
TEST_F(RenderWidgetHostViewAuraTest, ForwardsBeginFrameAcks) {
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
- if (features::IsVizDisplayCompositorEnabled() ||
- features::IsMultiProcessMash()) {
+ if (features::IsVizDisplayCompositorEnabled())
return;
- }
gfx::Rect view_rect(100, 100);
gfx::Size frame_size = view_rect.size();
@@ -4522,8 +4488,9 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
// Tests that the gesture debounce timer plays nice with the overscroll
// controller.
+// TODO(crbug.com/776424): Disabled due to flakiness on Fuchsia and Linux tsan.
TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- GestureScrollDebounceTimerOverscroll) {
+ DISABLED_GestureScrollDebounceTimerOverscroll) {
SetUpOverscrollEnvironmentWithDebounce(10);
PressAndSetTouchActionAuto();
@@ -4695,8 +4662,9 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) {
// Tests that touch-gesture end is dispatched to the renderer at the end of a
// touch-gesture initiated overscroll.
+// TODO(crbug.com/776424): Disabled due to flakiness on Fuchsia and Linux tsan.
TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- TouchGestureEndDispatchedAfterOverscrollComplete) {
+ DISABLED_TouchGestureEndDispatchedAfterOverscrollComplete) {
SetUpOverscrollEnvironmentWithDebounce(10);
widget_host_->OnMessageReceived(WidgetHostMsg_HasTouchEventHandlers(0, true));
@@ -5345,108 +5313,6 @@ TEST_F(RenderWidgetHostViewAuraTest, KeyEventsHandled) {
EXPECT_FALSE(key_event2.handled());
}
-TEST_F(RenderWidgetHostViewAuraTest, KeyEventAsyncHandled) {
- view_->InitAsChild(nullptr);
- view_->Show();
- bool async_callback_run = false;
- bool async_callback_handled_result = false;
- bool async_callback_stopped_propagation_result = false;
- ui::KeyEvent key_event1(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
- ui::KeyEvent::KeyDispatcherApi(&key_event1)
- .set_async_callback(base::BindLambdaForTesting(
- [&](bool handled, bool stopped_propagation) {
- async_callback_handled_result = handled;
- async_callback_stopped_propagation_result = stopped_propagation;
- async_callback_run = true;
- }));
- view_->OnKeyEvent(&key_event1);
- // Normally event should be handled.
- EXPECT_TRUE(key_event1.handled());
- // The async-callback should have been obtained, but not run yet.
- EXPECT_FALSE(key_event1.HasAsyncCallback());
- EXPECT_FALSE(async_callback_run);
- widget_host_->FlushForTesting();
-
- // Run the event callback, which should result in running the callback
- // attached to the event.
- MockWidgetInputHandler::MessageVector events =
- GetAndResetDispatchedMessages();
- ASSERT_EQ(1u, events.size());
- EXPECT_EQ("RawKeyDown", GetMessageNames(events));
- events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_TRUE(async_callback_run);
- EXPECT_TRUE(async_callback_handled_result);
- // |async_callback_stopped_propagation_result| should always be false.
- EXPECT_FALSE(async_callback_stopped_propagation_result);
-}
-
-TEST_F(RenderWidgetHostViewAuraTest, KeyEventAsyncUnhandled) {
- view_->InitAsChild(nullptr);
- view_->Show();
- bool async_callback_run = false;
- bool async_callback_handled_result = false;
- bool async_callback_stopped_propagation_result = false;
- ui::KeyEvent key_event1(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
- ui::KeyEvent::KeyDispatcherApi(&key_event1)
- .set_async_callback(base::BindLambdaForTesting(
- [&](bool handled, bool stopped_propagation) {
- async_callback_handled_result = handled;
- async_callback_stopped_propagation_result = stopped_propagation;
- async_callback_run = true;
- }));
- view_->OnKeyEvent(&key_event1);
- // Normally event should be handled.
- EXPECT_TRUE(key_event1.handled());
- // The async-callback should have been obtained, but not run yet.
- EXPECT_FALSE(key_event1.HasAsyncCallback());
- EXPECT_FALSE(async_callback_run);
- widget_host_->FlushForTesting();
-
- // Run the event callback, which should result in running the callback
- // attached to the event.
- MockWidgetInputHandler::MessageVector events =
- GetAndResetDispatchedMessages();
- ASSERT_EQ(1u, events.size());
- EXPECT_EQ("RawKeyDown", GetMessageNames(events));
- events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(async_callback_run);
- EXPECT_FALSE(async_callback_handled_result);
- // |async_callback_stopped_propagation_result| should always be false.
- EXPECT_FALSE(async_callback_stopped_propagation_result);
-}
-
-TEST_F(RenderWidgetHostViewAuraTest, KeyEventAsyncNotifiedWhenRouterChanges) {
- view_->InitAsChild(nullptr);
- view_->Show();
- bool async_callback_run = false;
- bool async_callback_handled_result = false;
- bool async_callback_stopped_propagation_result = false;
- ui::KeyEvent key_event1(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
- ui::KeyEvent::KeyDispatcherApi(&key_event1)
- .set_async_callback(base::BindLambdaForTesting(
- [&](bool handled, bool stopped_propagation) {
- async_callback_handled_result = handled;
- async_callback_stopped_propagation_result = stopped_propagation;
- async_callback_run = true;
- }));
- view_->OnKeyEvent(&key_event1);
- // Normally event should be handled.
- EXPECT_TRUE(key_event1.handled());
- // The async-callback should have been obtained, but not run yet.
- EXPECT_FALSE(key_event1.HasAsyncCallback());
- EXPECT_FALSE(async_callback_run);
-
- // RendererExited() should result in running the callback.
- widget_host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
- EXPECT_TRUE(async_callback_run);
- EXPECT_FALSE(async_callback_handled_result);
- // |async_callback_stopped_propagation_result| should always be false.
- EXPECT_FALSE(async_callback_stopped_propagation_result);
-
- // RendererExited() results in destroying the view.
- view_ = nullptr;
-}
-
TEST_F(RenderWidgetHostViewAuraTest, SetCanScrollForWebMouseWheelEvent) {
view_->InitAsChild(nullptr);
view_->Show();
@@ -5779,10 +5645,8 @@ TEST_F(RenderWidgetHostViewAuraTest, GestureTapFromStylusHasPointerType) {
TEST_F(RenderWidgetHostViewAuraTest, HitTestRegionListSubmitted) {
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
- if (features::IsVizDisplayCompositorEnabled() ||
- features::IsMultiProcessMash()) {
+ if (features::IsVizDisplayCompositorEnabled())
return;
- }
gfx::Rect view_rect(0, 0, 100, 100);
gfx::Size frame_size = view_rect.size();
@@ -5821,10 +5685,6 @@ TEST_F(RenderWidgetHostViewAuraTest, HitTestRegionListSubmitted) {
// time passes without receiving a new compositor frame.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
NewContentRenderingTimeout) {
- // TODO: fix for mash.
- if (features::IsMultiProcessMash())
- return;
-
constexpr base::TimeDelta kTimeout = base::TimeDelta::FromMicroseconds(10);
view_->InitAsChild(nullptr);
@@ -5879,11 +5739,9 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// If a tab is evicted, allocate a new LocalSurfaceId next time it's shown.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
AllocateLocalSurfaceIdOnEviction) {
- // TODO: fix for mash.
- if (features::IsMultiProcessMash())
- return;
-
view_->InitAsChild(nullptr);
+ // View has to not be empty in order for frame eviction to be invoked.
+ view_->SetSize(gfx::Size(54, 32));
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
gfx::Rect());
@@ -5910,10 +5768,6 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// visible we show blank.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DropFallbackIfResizedWhileHidden) {
- // Early out because DelegatedFrameHost is not used in mash.
- if (features::IsMultiProcessMash())
- return;
-
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
@@ -5931,10 +5785,6 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// fallback SurfaceId has to be preserved.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DontDropFallbackIfNotResizedWhileHidden) {
- // Early out because DelegatedFrameHost is not used in mash.
- if (features::IsMultiProcessMash())
- return;
-
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
@@ -5958,10 +5808,6 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// background color from the previous view to the new view.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
TakeFallbackContent) {
- // Early out because DelegatedFrameHost is not used in mash.
- if (features::IsMultiProcessMash())
- return;
-
// Initialize the first view.
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
@@ -6003,8 +5849,7 @@ class RenderWidgetHostViewAuraWithViewHarnessTest
delete contents()->GetRenderViewHost()->GetWidget()->GetView();
// This instance is destroyed in the TearDown method below.
view_ = new RenderWidgetHostViewAura(
- contents()->GetRenderViewHost()->GetWidget(), false,
- false /* is_mus_browser_plugin_guest */);
+ contents()->GetRenderViewHost()->GetWidget(), false);
}
void TearDown() override {
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 6986a9b5590..a2902adc59b 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
@@ -31,7 +31,6 @@
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/common/content_switches_internal.h"
#include "ui/base/layout.h"
-#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_types.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
@@ -41,11 +40,6 @@
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/size_f.h"
-#if defined(USE_AURA)
-#include "base/unguessable_token.h"
-#include "content/common/render_widget_window_tree_client_factory.mojom.h"
-#endif
-
namespace content {
RenderWidgetHostViewBase::RenderWidgetHostViewBase(RenderWidgetHost* host)
@@ -117,7 +111,7 @@ void RenderWidgetHostViewBase::StopFlingingIfNecessary(
if (!processed &&
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate &&
event.data.scroll_update.inertial_phase ==
- blink::WebGestureEvent::kMomentumPhase &&
+ blink::WebGestureEvent::InertialPhaseState::kMomentum &&
event.SourceDevice() != blink::WebGestureDevice::kSyntheticAutoscroll) {
StopFling();
view_stopped_flinging_for_test_ = true;
@@ -829,91 +823,26 @@ RenderWidgetHostViewBase::GetTouchSelectionControllerClientManager() {
return nullptr;
}
-void RenderWidgetHostViewBase::SetLastTabChangeStartTime(
- base::TimeTicks start_time) {
- last_tab_switch_start_time_ = start_time;
-}
-
-base::TimeTicks RenderWidgetHostViewBase::GetAndResetLastTabChangeStartTime() {
- auto stored_time = last_tab_switch_start_time_;
- last_tab_switch_start_time_ = base::TimeTicks();
- return stored_time;
-}
-
-#if defined(USE_AURA)
-void RenderWidgetHostViewBase::EmbedChildFrameRendererWindowTreeClient(
- RenderWidgetHostViewBase* root_view,
- int routing_id,
- ws::mojom::WindowTreeClientPtr renderer_window_tree_client) {
- RenderWidgetHost* render_widget_host = GetRenderWidgetHost();
- if (!render_widget_host)
- return;
- const int embed_id = ++next_embed_id_;
- pending_embeds_[routing_id] = embed_id;
- root_view->ScheduleEmbed(
- std::move(renderer_window_tree_client),
- base::BindOnce(&RenderWidgetHostViewBase::OnDidScheduleEmbed,
- GetWeakPtr(), routing_id, embed_id));
+void RenderWidgetHostViewBase::SetRecordTabSwitchTimeRequest(
+ base::TimeTicks start_time,
+ bool destination_is_loaded,
+ bool destination_is_frozen) {
+ last_record_tab_switch_time_request_.emplace(
+ start_time, destination_is_loaded, destination_is_frozen);
}
-void RenderWidgetHostViewBase::OnChildFrameDestroyed(int routing_id) {
- pending_embeds_.erase(routing_id);
- // Tests may not create |render_widget_window_tree_client_| (tests don't
- // necessarily create RenderWidgetHostViewAura).
- if (render_widget_window_tree_client_)
- render_widget_window_tree_client_->DestroyFrame(routing_id);
+base::Optional<RecordTabSwitchTimeRequest>
+RenderWidgetHostViewBase::TakeRecordTabSwitchTimeRequest() {
+ auto stored_state = std::move(last_record_tab_switch_time_request_);
+ last_record_tab_switch_time_request_.reset();
+ return stored_state;
}
-#endif
void RenderWidgetHostViewBase::SynchronizeVisualProperties() {
if (host())
host()->SynchronizeVisualProperties();
}
-#if defined(USE_AURA)
-void RenderWidgetHostViewBase::OnDidScheduleEmbed(
- int routing_id,
- int embed_id,
- const base::UnguessableToken& token) {
- auto iter = pending_embeds_.find(routing_id);
- if (iter == pending_embeds_.end() || iter->second != embed_id)
- return;
- pending_embeds_.erase(iter);
- // Tests may not create |render_widget_window_tree_client_| (tests don't
- // necessarily create RenderWidgetHostViewAura).
- if (render_widget_window_tree_client_)
- render_widget_window_tree_client_->Embed(routing_id, token);
-}
-
-void RenderWidgetHostViewBase::ScheduleEmbed(
- ws::mojom::WindowTreeClientPtr client,
- base::OnceCallback<void(const base::UnguessableToken&)> callback) {
- NOTREACHED();
-}
-
-ws::mojom::WindowTreeClientPtr
-RenderWidgetHostViewBase::GetWindowTreeClientFromRenderer() {
- // NOTE: this function may be called multiple times.
- RenderWidgetHost* render_widget_host = GetRenderWidgetHost();
- mojom::RenderWidgetWindowTreeClientFactoryPtr factory;
- BindInterface(render_widget_host->GetProcess(), &factory);
-
- ws::mojom::WindowTreeClientPtr window_tree_client;
- factory->CreateWindowTreeClientForRenderWidget(
- render_widget_host->GetRoutingID(),
- mojo::MakeRequest(&window_tree_client),
- mojo::MakeRequest(&render_widget_window_tree_client_));
- return window_tree_client;
-}
-
-#endif
-
-#if defined(OS_MACOSX)
-bool RenderWidgetHostViewBase::ShouldContinueToPauseForFrame() {
- return false;
-}
-#endif
-
void RenderWidgetHostViewBase::DidNavigate() {
if (host())
host()->SynchronizeVisualProperties();
@@ -940,36 +869,27 @@ bool RenderWidgetHostViewBase::TransformPointToTargetCoordSpace(
std::vector<viz::FrameSinkId> target_ancestors;
target_ancestors.push_back(target_view->GetFrameSinkId());
- // Optimization using |target_ancestors| does not work with Window Service
- // because the top-level window's ClientRoot registers a frame sink id that
- // could not be derived here. HisTestQuery::TransformLocationForTarget fails
- // because of the missed chain in |target_ancestors|. Passing only the target
- // if Window Service used and TransformLocationForTarget would fallback to
- // use GetTransformToTarget.
- // TODO(crbug.com/895029): Bring back |target_ancestors| optimization for WS.
- if (!features::IsUsingWindowService()) {
- RenderWidgetHostViewBase* cur_view = target_view;
- while (cur_view->IsRenderWidgetHostViewChildFrame()) {
- if (cur_view->IsRenderWidgetHostViewGuest()) {
- cur_view = static_cast<RenderWidgetHostViewGuest*>(cur_view)
- ->GetOwnerRenderWidgetHostView();
- } else {
- cur_view = static_cast<RenderWidgetHostViewChildFrame*>(cur_view)
- ->GetParentView();
- }
- if (!cur_view)
- return false;
- target_ancestors.push_back(cur_view->GetFrameSinkId());
+ RenderWidgetHostViewBase* cur_view = target_view;
+ while (cur_view->IsRenderWidgetHostViewChildFrame()) {
+ if (cur_view->IsRenderWidgetHostViewGuest()) {
+ cur_view = static_cast<RenderWidgetHostViewGuest*>(cur_view)
+ ->GetOwnerRenderWidgetHostView();
+ } else {
+ cur_view = static_cast<RenderWidgetHostViewChildFrame*>(cur_view)
+ ->GetParentView();
}
- target_ancestors.push_back(root_frame_sink_id);
+ if (!cur_view)
+ return false;
+ target_ancestors.push_back(cur_view->GetFrameSinkId());
}
+ target_ancestors.push_back(root_frame_sink_id);
float device_scale_factor = original_view->GetDeviceScaleFactor();
DCHECK_GT(device_scale_factor, 0.0f);
gfx::Point3F point_in_pixels(
gfx::ConvertPointToPixel(device_scale_factor, point));
- // TODO(riajiang): Optimize so that |point_in_pixels| doesn't need to be in
- // the coordinate space of the root surface in HitTestQuery.
+ // TODO(crbug.com/966995): Optimize so that |point_in_pixels| doesn't need to
+ // be in the coordinate space of the root surface in HitTestQuery.
gfx::Transform transform_root_to_original;
query->GetTransformToTarget(original_view->GetFrameSinkId(),
&transform_root_to_original);
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 11c2dcff17a..81bdc91eb35 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_base.h
@@ -14,6 +14,7 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/observer_list.h"
+#include "base/optional.h"
#include "base/process/kill.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
@@ -24,6 +25,7 @@
#include "components/viz/host/hit_test/hit_test_query.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/common/content_export.h"
+#include "content/common/tab_switch_time_recorder.h"
#include "content/public/browser/render_frame_metadata_provider.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/input_event_ack_state.h"
@@ -44,18 +46,8 @@
#include "ui/gfx/range/range.h"
#include "ui/surface/transport_dib.h"
-#if defined(USE_AURA)
-#include "base/containers/flat_map.h"
-#include "content/common/render_widget_window_tree_client_factory.mojom.h"
-#include "services/ws/public/mojom/window_tree.mojom.h"
-#endif
-
struct WidgetHostMsg_SelectionBounds_Params;
-namespace base {
-class UnguessableToken;
-}
-
namespace cc {
struct BeginFrameAck;
} // namespace cc
@@ -86,7 +78,6 @@ class RenderWidgetHostViewBaseObserver;
class SyntheticGestureTarget;
class TextInputManager;
class TouchSelectionControllerClientManager;
-class WebContentsAccessibility;
class WebCursor;
class DelegatedFrameHost;
struct TextInputState;
@@ -140,7 +131,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
float GetDeviceScaleFactor() final;
TouchSelectionControllerClientManager*
GetTouchSelectionControllerClientManager() override;
- void SetLastTabChangeStartTime(base::TimeTicks start_time) final;
+ void SetRecordTabSwitchTimeRequest(base::TimeTicks start_time,
+ bool destination_is_loaded,
+ bool destination_is_frozen) final;
// This only needs to be overridden by RenderWidgetHostViewBase subclasses
// that handle content embedded within other RenderWidgetHostViews.
@@ -200,10 +193,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
virtual viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
const cc::RenderFrameMetadata& metadata);
- // Returns the time set by SetLastTabChangeStartTime. If this was not
- // preceded by a call to SetLastTabChangeStartTime, this will return null.
- // Calling this will reset the stored time to null.
- base::TimeTicks GetAndResetLastTabChangeStartTime();
+ // Returns the time set by SetLastRecordTabSwitchTimeRequest. If this was not
+ // preceded by a call to SetLastRecordTabSwitchTimeRequest the
+ // |tab_switch_start_time| field of the returned struct will have a null
+ // timestamp. Calling this will reset
+ // |last_tab_switch_start_state_.tab_switch_start_time| to null.
+ base::Optional<RecordTabSwitchTimeRequest> TakeRecordTabSwitchTimeRequest();
base::WeakPtr<RenderWidgetHostViewBase> GetWeakPtr();
@@ -511,8 +506,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
virtual void SetIsLoading(bool is_loading) = 0;
// Notifies the View that the renderer has ceased to exist.
- virtual void RenderProcessGone(base::TerminationStatus status,
- int error_code) = 0;
+ virtual void RenderProcessGone() = 0;
// Tells the View to destroy itself.
virtual void Destroy();
@@ -570,10 +564,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
bool is_fullscreen() { return is_fullscreen_; }
- void set_web_contents_accessibility(WebContentsAccessibility* wcax) {
- web_contents_accessibility_ = wcax;
- }
-
void set_is_currently_scrolling_viewport(
bool is_currently_scrolling_viewport) {
is_currently_scrolling_viewport_ = is_currently_scrolling_viewport;
@@ -583,20 +573,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
return is_currently_scrolling_viewport_;
}
-#if defined(USE_AURA)
- void EmbedChildFrameRendererWindowTreeClient(
- RenderWidgetHostViewBase* root_view,
- int routing_id,
- ws::mojom::WindowTreeClientPtr renderer_window_tree_client);
- void OnChildFrameDestroyed(int routing_id);
-#endif
-
-#if defined(OS_MACOSX)
- // Use only for resize on macOS. Returns true if there is not currently a
- // frame of the view's size being displayed.
- virtual bool ShouldContinueToPauseForFrame();
-#endif
-
virtual void DidNavigate();
// Called when the RenderWidgetHostImpl has be initialized.
@@ -627,14 +603,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
virtual void StopFlingingIfNecessary(const blink::WebGestureEvent& event,
InputEventAckState ack_result);
-#if defined(USE_AURA)
- virtual void ScheduleEmbed(
- ws::mojom::WindowTreeClientPtr client,
- base::OnceCallback<void(const base::UnguessableToken&)> callback);
-
- ws::mojom::WindowTreeClientPtr GetWindowTreeClientFromRenderer();
-#endif
-
// If |event| is a touchpad pinch or double tap 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.
@@ -687,8 +655,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// |content_background_color|.
base::Optional<SkColor> default_background_color_;
- WebContentsAccessibility* web_contents_accessibility_ = nullptr;
-
bool is_currently_scrolling_viewport_ = false;
private:
@@ -701,12 +667,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
void SynchronizeVisualProperties();
-#if defined(USE_AURA)
- void OnDidScheduleEmbed(int routing_id,
- int embed_id,
- const base::UnguessableToken& token);
-#endif
-
// Called when display properties that need to be synchronized with the
// renderer process changes. This method is called before notifying
// RenderWidgetHostImpl in order to allow the view to allocate a new
@@ -738,24 +698,13 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
base::ObserverList<RenderWidgetHostViewBaseObserver>::Unchecked observers_;
-#if defined(USE_AURA)
- mojom::RenderWidgetWindowTreeClientPtr render_widget_window_tree_client_;
-
- int next_embed_id_ = 0;
- // Maps from routing_id to embed-id. The |routing_id| is the id supplied to
- // EmbedChildFrameRendererWindowTreeClient() and the embed-id a unique id
- // generate at the time EmbedChildFrameRendererWindowTreeClient() was called.
- // This is done to ensure when OnDidScheduleEmbed() is received another call
- // too EmbedChildFrameRendererWindowTreeClient() did not come in.
- base::flat_map<int, int> pending_embeds_;
-#endif
-
base::Optional<blink::WebGestureEvent> pending_touchpad_pinch_begin_;
- // The last tab switch processing start time. This should only be set and
- // retrieved using SetLastTabChangeStartTime and
- // GetAndResetLastTabChangeStartTime.
- base::TimeTicks last_tab_switch_start_time_;
+ // The last tab switch processing start request. This should only be set and
+ // retrieved using SetRecordTabSwitchTimeRequest and
+ // TakeRecordTabSwitchTimeRequest.
+ base::Optional<RecordTabSwitchTimeRequest>
+ last_record_tab_switch_time_request_;
// True when StopFlingingIfNecessary() calls StopFling().
bool view_stopped_flinging_for_test_ = false;
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 e098a526172..a04ca192662 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
@@ -43,17 +43,11 @@
#include "content/public/browser/render_process_host.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "third_party/blink/public/platform/web_touch_event.h"
-#include "ui/base/ui_base_features.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/touch_selection/touch_selection_controller.h"
-#if defined(USE_AURA)
-#include "services/ws/public/mojom/window_tree.mojom.h"
-#include "ui/aura/env.h"
-#endif
-
namespace content {
// static
@@ -76,20 +70,14 @@ RenderWidgetHostViewChildFrame::RenderWidgetHostViewChildFrame(
enable_surface_synchronization_(
features::IsSurfaceSynchronizationEnabled()),
weak_factory_(this) {
- if (features::IsMultiProcessMash()) {
- // 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();
- } else {
- GetHostFrameSinkManager()->RegisterFrameSinkId(
- frame_sink_id_, this,
- enable_surface_synchronization_
- ? viz::ReportFirstSurfaceActivation::kNo
- : viz::ReportFirstSurfaceActivation::kYes);
- GetHostFrameSinkManager()->SetFrameSinkDebugLabel(
- frame_sink_id_, "RenderWidgetHostViewChildFrame");
- CreateCompositorFrameSinkSupport();
- }
+ GetHostFrameSinkManager()->RegisterFrameSinkId(
+ frame_sink_id_, this,
+ enable_surface_synchronization_
+ ? viz::ReportFirstSurfaceActivation::kNo
+ : viz::ReportFirstSurfaceActivation::kYes);
+ GetHostFrameSinkManager()->SetFrameSinkDebugLabel(
+ frame_sink_id_, "RenderWidgetHostViewChildFrame");
+ CreateCompositorFrameSinkSupport();
}
RenderWidgetHostViewChildFrame::~RenderWidgetHostViewChildFrame() {
@@ -99,11 +87,9 @@ RenderWidgetHostViewChildFrame::~RenderWidgetHostViewChildFrame() {
if (frame_connector_)
DetachFromTouchSelectionClientManagerIfNecessary();
- if (!features::IsMultiProcessMash()) {
- ResetCompositorFrameSinkSupport();
- if (GetHostFrameSinkManager())
- GetHostFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
- }
+ ResetCompositorFrameSinkSupport();
+ if (GetHostFrameSinkManager())
+ GetHostFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
}
void RenderWidgetHostViewChildFrame::Init() {
@@ -152,8 +138,7 @@ void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
frame_connector_->GetParentRenderWidgetHostView();
if (parent_view) {
- DCHECK(parent_view->GetFrameSinkId().is_valid() ||
- features::IsMultiProcessMash());
+ DCHECK(parent_view->GetFrameSinkId().is_valid());
SetParentFrameSinkId(parent_view->GetFrameSinkId());
}
@@ -173,24 +158,9 @@ void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
}
}
-#if defined(USE_AURA)
- if (features::IsMultiProcessMash()) {
- frame_connector_->EmbedRendererWindowTreeClientInParent(
- GetWindowTreeClientFromRenderer());
- }
-#endif
-
SendSurfaceInfoToEmbedder();
}
-#if defined(USE_AURA)
-void RenderWidgetHostViewChildFrame::SetFrameSinkId(
- const viz::FrameSinkId& frame_sink_id) {
- if (features::IsMultiProcessMash())
- frame_sink_id_ = frame_sink_id;
-}
-#endif // defined(USE_AURA)
-
void RenderWidgetHostViewChildFrame::UpdateIntrinsicSizingInfo(
const blink::WebIntrinsicSizingInfo& sizing_info) {
if (frame_connector_)
@@ -259,7 +229,7 @@ void RenderWidgetHostViewChildFrame::Show() {
if (!CanBecomeVisible())
return;
- host()->WasShown(false /* record_presentation_time */);
+ host()->WasShown(base::nullopt /* record_tab_switch_time_request */);
if (frame_connector_)
frame_connector_->SetVisibilityForChildViews(true);
@@ -418,9 +388,7 @@ void RenderWidgetHostViewChildFrame::SetIsLoading(bool is_loading) {
// RenderWidgetHostViewChildFrame which do not get a SetIsLoading() call.
}
-void RenderWidgetHostViewChildFrame::RenderProcessGone(
- base::TerminationStatus status,
- int error_code) {
+void RenderWidgetHostViewChildFrame::RenderProcessGone() {
if (frame_connector_)
frame_connector_->RenderProcessGone();
Destroy();
@@ -603,8 +571,7 @@ void RenderWidgetHostViewChildFrame::DidCreateNewRendererCompositorFrameSink(
void RenderWidgetHostViewChildFrame::SetParentFrameSinkId(
const viz::FrameSinkId& parent_frame_sink_id) {
- if (parent_frame_sink_id_ == parent_frame_sink_id ||
- features::IsMultiProcessMash())
+ if (parent_frame_sink_id_ == parent_frame_sink_id)
return;
auto* host_frame_sink_manager = GetHostFrameSinkManager();
@@ -625,8 +592,6 @@ void RenderWidgetHostViewChildFrame::SetParentFrameSinkId(
}
void RenderWidgetHostViewChildFrame::SendSurfaceInfoToEmbedder() {
- if (features::IsMultiProcessMash())
- return;
if (enable_surface_synchronization_)
return;
if (!last_activated_surface_info_.is_valid())
@@ -1067,7 +1032,7 @@ RenderWidgetHostViewChildFrame::DidUpdateVisualProperties(
}
void RenderWidgetHostViewChildFrame::CreateCompositorFrameSinkSupport() {
- if (features::IsMultiProcessMash() || enable_viz_)
+ if (enable_viz_)
return;
DCHECK(!support_);
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 039bafd019b..6668af1aa5c 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
@@ -63,12 +63,6 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void SetFrameConnectorDelegate(FrameConnectorDelegate* frame_connector);
-#if defined(USE_AURA)
- // When the viz::FrameSinkId for this child frame is created and registered
- // remotely, it can be set here.
- void SetFrameSinkId(const viz::FrameSinkId& frame_sink_id);
-#endif // defined(USE_AURA)
-
// This functions registers single-use callbacks that want to be notified when
// the next frame is swapped. The callback is triggered by
// SubmitCompositorFrame, which is the appropriate time to request pixel
@@ -120,8 +114,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
void UpdateCursor(const WebCursor& cursor) override;
void SetIsLoading(bool is_loading) override;
- void RenderProcessGone(base::TerminationStatus status,
- int error_code) override;
+ void RenderProcessGone() override;
void Destroy() override;
void SetTooltipText(const base::string16& tooltip_text) override;
void GestureEventAck(const blink::WebGestureEvent& event,
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 fd0534a7109..4e5c2189a1a 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
@@ -24,7 +24,6 @@
#include "content/test/test_content_browser_client.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "ui/base/ui_base_features.h"
#include "ui/gfx/geometry/size.h"
namespace content {
@@ -157,41 +156,6 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest,
EXPECT_EQ(gfx::Size(75, 75), rwhv->GetVisibleViewportSize());
}
-// Tests that while in mus, the child frame receives an updated FrameSinkId
-// representing the frame sink used by the RenderFrameProxy.
-IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest, ChildFrameSinkId) {
- // Only when mus hosts viz do we expect a RenderFrameProxy to provide the
- // FrameSinkId.
- if (!features::IsMultiProcessMash())
- return;
-
- 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();
- auto message_filter =
- base::MakeRefCounted<SynchronizeVisualPropertiesMessageFilter>();
- root->current_frame_host()->GetProcess()->AddFilter(message_filter.get());
-
- // Load cross-site page into iframe.
- GURL cross_site_url(
- embedded_test_server()->GetURL("foo.com", "/title2.html"));
- // The child frame is created during this blocking call, on the UI thread.
- // This is racing the IPC we are testing for, which arrives on the IO thread.
- // Due to this we cannot get the pre-IPC value of the viz::FrameSinkId.
- NavigateFrameToURL(root->child_at(0), cross_site_url);
-
- // Ensure that the IPC providing the new viz::FrameSinkId. If it does not then
- // this test will timeout.
- set_expected_frame_sink_id(message_filter->GetOrWaitForId());
-
- shell()->web_contents()->ForEachFrame(
- base::BindRepeating(&RenderWidgetHostViewChildFrameTest::CheckFrameSinkId,
- base::Unretained(this)));
-}
-
// Validate that OOPIFs receive presentation feedbacks.
IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest,
PresentationFeedback) {
@@ -212,8 +176,9 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest,
// 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 */,
- base::TimeTicks::Now());
+ child_rwh_impl->WasShown(RecordTabSwitchTimeRequest{
+ base::TimeTicks::Now(), /* destination_is_loaded */ true,
+ /* destination_is_frozen */ false});
// Force the child to submit a new frame.
ASSERT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
"document.write('Force a new frame.');"));
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 468561b429f..4e2075be4cf 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
@@ -297,7 +297,7 @@ void RenderWidgetHostViewEventHandler::OnKeyEvent(ui::KeyEvent* event) {
webkit_event.skip_in_browser = true;
delegate_->ForwardKeyboardEventWithLatencyInfo(
- webkit_event, *event->latency(), event, &mark_event_as_handled);
+ webkit_event, *event->latency(), &mark_event_as_handled);
}
if (mark_event_as_handled)
event->SetHandled();
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 63f2fcb16cb..19c945bcc46 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
@@ -72,7 +72,6 @@ class CONTENT_EXPORT RenderWidgetHostViewEventHandler
virtual void ForwardKeyboardEventWithLatencyInfo(
const NativeWebKeyboardEvent& event,
const ui::LatencyInfo& latency,
- ui::KeyEvent* original_key_event,
bool* update_event) = 0;
// Returns whether the widget needs to grab mouse capture to work properly.
virtual bool NeedsMouseCapture() = 0;
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 84028e7cf2a..9194753f471 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
@@ -15,9 +15,9 @@
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "components/viz/common/surfaces/surface_id.h"
+#include "content/app_shim_remote_cocoa/render_widget_host_ns_view_client_helper.h"
#include "content/browser/renderer_host/browser_compositor_view_mac.h"
#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
-#include "content/browser/renderer_host/render_widget_host_ns_view_client_helper.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/common/content_export.h"
@@ -30,6 +30,12 @@
#include "ui/base/cocoa/remote_layer_api.h"
#include "ui/events/gesture_detection/filtered_gesture_provider.h"
+namespace remote_cocoa {
+namespace mojom {
+class BridgeFactory;
+} // namespace mojom
+} // namespace remote_cocoa
+
namespace ui {
enum class DomCode;
class Layer;
@@ -44,7 +50,6 @@ class ScopedPasswordInputEnabler;
namespace content {
class CursorManager;
-class NSViewBridgeFactoryHost;
class RenderWidgetHost;
class RenderWidgetHostNSViewBridgeLocal;
class RenderWidgetHostViewMac;
@@ -128,8 +133,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
CursorManager* GetCursorManager() override;
void OnDidNavigateMainFrameToNewPage() override;
void SetIsLoading(bool is_loading) override;
- void RenderProcessGone(base::TerminationStatus status,
- int error_code) override;
+ void RenderProcessGone() override;
void Destroy() override;
void SetTooltipText(const base::string16& tooltip_text) override;
void DisplayTooltipText(const base::string16& tooltip_text) override;
@@ -454,11 +458,12 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// https://crbug.com/831843
RenderWidgetHostImpl* GetWidgetForKeyboardEvent();
- // Migrate the NSView for this RenderWidgetHostView to be in the process
- // hosted by |bridge_factory_host|, and make it a child view of the NSView
- // referred to by |parent_ns_view_id|.
- void MigrateNSViewBridge(NSViewBridgeFactoryHost* bridge_factory_host,
- uint64_t parent_ns_view_id);
+ // Migrate the NSView for this RenderWidgetHostView to be in the process at
+ // the other end of |remote_cocoa_application|, and make it a child view of
+ // the NSView referred to by |parent_ns_view_id|.
+ void MigrateNSViewBridge(
+ remote_cocoa::mojom::BridgeFactory* remote_cocoa_application,
+ uint64_t parent_ns_view_id);
// Specify a ui::Layer into which the renderer's content should be
// composited. If nullptr is specified, then this layer will create a
@@ -494,9 +499,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Send updated vsync parameters to the top level display.
void UpdateDisplayVSyncParameters();
- // Adds/Removes frame observer based on state.
- void UpdateNeedsBeginFramesInternal();
-
void SendSyntheticWheelEventWithPhaseEnded(
blink::WebMouseWheelEvent wheel_event,
bool should_route_event);
@@ -576,9 +578,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Display link for getting vsync info.
scoped_refptr<ui::DisplayLinkMac> display_link_;
- // Whether a request for begin frames has been issued.
- bool needs_begin_frames_;
-
// Whether or not the background is opaque as determined by calls to
// SetBackgroundColor. The default value is opaque.
bool background_is_opaque_ = true;
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 4db5f275ff7..19b52c4e90d 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
@@ -16,11 +16,15 @@
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/macros.h"
+#include "base/optional.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
+#include "components/remote_cocoa/common/bridge_factory.mojom.h"
#include "components/viz/common/features.h"
#include "components/viz/common/switches.h"
+#import "content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge_local.h"
+#import "content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h"
#import "content/browser/accessibility/browser_accessibility_cocoa.h"
#import "content/browser/accessibility/browser_accessibility_mac.h"
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
@@ -32,8 +36,6 @@
#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_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"
#include "content/common/text_input_state.h"
@@ -41,7 +43,6 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/native_web_keyboard_event.h"
-#include "content/public/browser/ns_view_bridge_factory_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
#include "skia/ext/platform_canvas.h"
@@ -87,7 +88,6 @@ void RenderWidgetHostViewMac::BrowserCompositorMacOnBeginFrame(
// ProgressFling must get called for middle click autoscroll fling on Mac.
if (host())
host()->ProgressFlingIfNeeded(frame_time);
- UpdateNeedsBeginFramesInternal();
}
void RenderWidgetHostViewMac::OnFrameTokenChanged(uint32_t frame_token) {
@@ -212,8 +212,6 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
GetFrameSinkId(), this);
}
- bool needs_begin_frames = true;
-
RenderWidgetHostOwnerDelegate* owner_delegate = host()->owner_delegate();
if (owner_delegate) {
// TODO(mostynb): actually use prefs. Landing this as a separate CL
@@ -221,29 +219,12 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
// NOTE: This will not be run for child frame widgets, which do not have
// an owner delegate and won't get a RenderViewHost here.
ignore_result(owner_delegate->GetWebkitPreferencesForWidget());
- needs_begin_frames = !owner_delegate->IsNeverVisible();
}
cursor_manager_.reset(new CursorManager(this));
if (GetTextInputManager())
GetTextInputManager()->AddObserver(this);
-
- // When Viz Display Compositor is not active, RenderWidgetHostViewMac is
- // responsible for handling BeginFrames.
- //
- // Because of the way Mac pumps messages during resize, SetNeedsBeginFrame
- // messages are not delayed on Mac. This leads to creation-time raciness
- // where renderer sends a SetNeedsBeginFrame(true) before the renderer host is
- // created to receive it.
- //
- // Any renderer that will produce frames needs to have begin frames sent to
- // it. So unless it is never visible, start this value at true here to avoid
- // startup raciness and decrease latency.
- if (!features::IsVizDisplayCompositorEnabled()) {
- needs_begin_frames_ = needs_begin_frames;
- UpdateNeedsBeginFramesInternal();
- }
}
RenderWidgetHostViewMac::~RenderWidgetHostViewMac() {
@@ -260,7 +241,7 @@ RenderWidgetHostViewMac::~RenderWidgetHostViewMac() {
}
void RenderWidgetHostViewMac::MigrateNSViewBridge(
- NSViewBridgeFactoryHost* bridge_factory_host,
+ remote_cocoa::mojom::BridgeFactory* remote_cocoa_application,
uint64_t parent_ns_view_id) {
// Destroy the previous remote accessibility element.
remote_window_accessible_.reset();
@@ -272,10 +253,11 @@ void RenderWidgetHostViewMac::MigrateNSViewBridge(
ns_view_bridge_remote_.reset();
// Enable accessibility focus overriding for remote NSViews.
- accessibility_focus_overrider_.SetAppIsRemote(bridge_factory_host != nullptr);
+ accessibility_focus_overrider_.SetAppIsRemote(remote_cocoa_application !=
+ nullptr);
// If no host is specified, then use the locally hosted NSView.
- if (!bridge_factory_host) {
+ if (!remote_cocoa_application) {
ns_view_bridge_ = ns_view_bridge_local_.get();
return;
}
@@ -287,15 +269,15 @@ void RenderWidgetHostViewMac::MigrateNSViewBridge(
// Cast from mojom::RenderWidgetHostNSViewClientPtr and
// mojom::RenderWidgetHostNSViewBridgeRequest to the public interfaces
- // accepted by the factory.
+ // accepted by the application.
// TODO(ccameron): Remove the need for this cast.
// https://crbug.com/888290
- mojo::AssociatedInterfacePtrInfo<mojom::StubInterface> stub_client(
- client.PassInterface().PassHandle(), 0);
- mojom::StubInterfaceAssociatedRequest stub_bridge_request(
+ mojo::AssociatedInterfacePtrInfo<remote_cocoa::mojom::StubInterface>
+ stub_client(client.PassInterface().PassHandle(), 0);
+ remote_cocoa::mojom::StubInterfaceAssociatedRequest stub_bridge_request(
bridge_request.PassHandle());
- bridge_factory_host->GetFactory()->CreateRenderWidgetHostNSViewBridge(
+ remote_cocoa_application->CreateRenderWidgetHostNSView(
std::move(stub_client), std::move(stub_bridge_request));
ns_view_bridge_ = ns_view_bridge_remote_.get();
@@ -479,11 +461,12 @@ void RenderWidgetHostViewMac::WasUnOccluded() {
bool has_saved_frame =
browser_compositor_->has_saved_frame_before_state_transition();
- auto tab_switch_start_time = GetAndResetLastTabChangeStartTime();
+ auto tab_switch_start_state = TakeRecordTabSwitchTimeRequest();
const bool renderer_should_record_presentation_time = !has_saved_frame;
- host()->WasShown(renderer_should_record_presentation_time,
- tab_switch_start_time);
+ host()->WasShown(renderer_should_record_presentation_time
+ ? tab_switch_start_state
+ : base::nullopt);
if (delegated_frame_host) {
// If the frame for the renderer is already available, then the
@@ -492,8 +475,8 @@ void RenderWidgetHostViewMac::WasUnOccluded() {
delegated_frame_host->WasShown(
browser_compositor_->GetRendererLocalSurfaceIdAllocation()
.local_surface_id(),
- browser_compositor_->GetRendererSize(), record_presentation_time,
- tab_switch_start_time);
+ browser_compositor_->GetRendererSize(),
+ record_presentation_time ? tab_switch_start_state : base::nullopt);
}
}
@@ -695,8 +678,7 @@ void RenderWidgetHostViewMac::OnRenderFrameMetadataChangedAfterActivation() {
RenderWidgetHostViewBase::OnRenderFrameMetadataChangedAfterActivation();
}
-void RenderWidgetHostViewMac::RenderProcessGone(base::TerminationStatus status,
- int error_code) {
+void RenderWidgetHostViewMac::RenderProcessGone() {
Destroy();
}
@@ -870,12 +852,7 @@ void RenderWidgetHostViewMac::EnsureSurfaceSynchronizedForWebTest() {
}
void RenderWidgetHostViewMac::SetNeedsBeginFrames(bool needs_begin_frames) {
- needs_begin_frames_ = needs_begin_frames;
- UpdateNeedsBeginFramesInternal();
-}
-
-void RenderWidgetHostViewMac::UpdateNeedsBeginFramesInternal() {
- browser_compositor_->SetNeedsBeginFrames(needs_begin_frames_);
+ NOTREACHED();
}
void RenderWidgetHostViewMac::OnDidUpdateVisualPropertiesComplete(
@@ -1573,7 +1550,7 @@ void RenderWidgetHostViewMac::ForwardKeyboardEventWithCommands(
const std::vector<EditCommand>& commands) {
if (auto* widget_host = GetWidgetForKeyboardEvent()) {
widget_host->ForwardKeyboardEventWithCommands(key_event, latency_info,
- &commands, nullptr);
+ &commands);
}
}
@@ -1825,6 +1802,8 @@ bool RenderWidgetHostViewMac::SyncGetFirstRectForRange(
*success = true;
if (!GetCachedFirstRectForCharacterRange(requested_range, rect,
actual_range)) {
+ // https://crbug.com/121917
+ base::ScopedAllowBlocking allow_wait;
*rect = TextInputClientMac::GetInstance()->GetFirstRectForRange(
GetFocusedWidget(), requested_range);
// TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery.
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac_browsertest.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac_browsertest.mm
index a3a0186754d..4c511467819 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac_browsertest.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac_browsertest.mm
@@ -63,4 +63,24 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewMacTest, GetPageTextForSpeech) {
EXPECT_EQ(base::ASCIIToUTF16("Hello\nWorld"), waiter.text());
}
+// Test that -firstRectForCharacterRange:actualRange: works when the range
+// isn't in the active selection, which requres a sync IPC to the renderer.
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewMacTest,
+ GetFirstRectForCharacterRangeUncached) {
+ GURL url("data:text/html,Hello");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ RenderWidgetHostView* rwhv =
+ shell()->web_contents()->GetMainFrame()->GetView();
+ RenderWidgetHostViewMac* rwhv_mac =
+ static_cast<RenderWidgetHostViewMac*>(rwhv);
+
+ NSRect rect =
+ [rwhv_mac->cocoa_view() firstRectForCharacterRange:NSMakeRange(2, 1)
+ actualRange:nullptr];
+ EXPECT_GT(NSMinX(rect), 0);
+ EXPECT_GT(NSWidth(rect), 0);
+ EXPECT_GT(NSHeight(rect), 0);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h
index a1908702ae5..e48fbadb759 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h
@@ -9,7 +9,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
+#import "content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h"
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
namespace content {
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 c43d3c049f1..2ff0da1e287 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
@@ -24,11 +24,11 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/viz/common/surfaces/child_local_surface_id_allocator.h"
+#import "content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
-#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/common/input_messages.h"
#include "content/common/text_input_state.h"
@@ -568,9 +568,11 @@ TEST_F(RenderWidgetHostViewMacTest, AcceptsFirstResponder) {
// This test verifies that RenderWidgetHostViewCocoa's implementation of
// NSTextInputClientConformance conforms to requirements.
TEST_F(RenderWidgetHostViewMacTest, NSTextInputClientConformance) {
- NSRange selectedRange = [rwhv_cocoa_ selectedRange];
- EXPECT_EQ(0u, selectedRange.location);
- EXPECT_EQ(0u, selectedRange.length);
+ EXPECT_NSEQ(NSMakeRange(0, 0), [rwhv_cocoa_ selectedRange]);
+
+ rwhv_mac_->SelectionChanged(base::UTF8ToUTF16("llo, world!"), 2,
+ gfx::Range(5, 10));
+ EXPECT_NSEQ(NSMakeRange(5, 5), [rwhv_cocoa_ selectedRange]);
NSRange actualRange = NSMakeRange(1u, 2u);
NSAttributedString* actualString = [rwhv_cocoa_
@@ -2259,11 +2261,6 @@ TEST_F(RenderWidgetHostViewMacTest, TransformToRootWithParentLayer) {
EXPECT_EQ(point, gfx::PointF(105, 310));
}
-// This test uses deprecated NSObject accessibility APIs - see
-// https://crbug.com/921109.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-
TEST_F(RenderWidgetHostViewMacTest, AccessibilityParentTest) {
NSView* view = rwhv_mac_->cocoa_view();
@@ -2278,36 +2275,15 @@ TEST_F(RenderWidgetHostViewMacTest, AccessibilityParentTest) {
[[window contentView] addSubview:accessibility_parent];
[parent_view addSubview:view];
- EXPECT_NSEQ([view accessibilityAttributeValue:NSAccessibilityParentAttribute],
- parent_view);
+ EXPECT_NSEQ([view accessibilityParent], parent_view);
rwhv_mac_->SetParentAccessibilityElement(accessibility_parent);
- EXPECT_NSEQ([view accessibilityAttributeValue:NSAccessibilityParentAttribute],
+ EXPECT_NSEQ([view accessibilityParent],
NSAccessibilityUnignoredAncestor(accessibility_parent));
- EXPECT_NE([view accessibilityAttributeValue:NSAccessibilityParentAttribute],
- nil);
+ EXPECT_NSNE(nil, [view accessibilityParent]);
rwhv_mac_->SetParentAccessibilityElement(nil);
- EXPECT_NSEQ([view accessibilityAttributeValue:NSAccessibilityParentAttribute],
- parent_view);
-}
-#pragma clang diagnostic pop
-
-// Tests that when entering mouse lock, the cursor will lock to window center.
-TEST_F(RenderWidgetHostViewMacTest, PointerLockCenterPosition) {
- NSView* view = rwhv_mac_->cocoa_view();
-
- NSRect bound = NSMakeRect(123, 234, 456, 678);
- [view setFrame:bound];
-
- EXPECT_EQ(gfx::Rect([view bounds]), gfx::Rect(0, 0, 456, 678));
-
- rwhv_mac_->LockMouse();
- EXPECT_TRUE(rwhv_mac_->IsMouseLocked());
-
- gfx::Point mouse_pos =
- gfx::Point([window_ mouseLocationOutsideOfEventStream]);
- EXPECT_EQ(mouse_pos, gfx::Point(228, 339));
+ EXPECT_NSEQ([view accessibilityParent], parent_view);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_targeter.cc b/chromium/content/browser/renderer_host/render_widget_targeter.cc
index 0cc660c88dc..2f540fb2b6c 100644
--- a/chromium/content/browser/renderer_host/render_widget_targeter.cc
+++ b/chromium/content/browser/renderer_host/render_widget_targeter.cc
@@ -61,7 +61,7 @@ class TracingUmaTracker {
metric_name_(metric_name) {
TRACE_EVENT_ASYNC_BEGIN0(
kTracingCategory, metric_name_,
- TRACE_ID_WITH_SCOPE(metric_name_, TRACE_ID_LOCAL(id_)));
+ TRACE_ID_WITH_SCOPE("UmaTracker", TRACE_ID_LOCAL(id_)));
}
~TracingUmaTracker() = default;
TracingUmaTracker(TracingUmaTracker&& tracker) = default;
@@ -74,7 +74,7 @@ class TracingUmaTracker {
void Stop() {
TRACE_EVENT_ASYNC_END0(
kTracingCategory, metric_name_,
- TRACE_ID_WITH_SCOPE(metric_name_, TRACE_ID_LOCAL(id_)));
+ TRACE_ID_WITH_SCOPE("UmaTracker", TRACE_ID_LOCAL(id_)));
}
private:
diff --git a/chromium/content/browser/renderer_interface_binders.cc b/chromium/content/browser/renderer_interface_binders.cc
index 1bd1a3f7a15..a391b278948 100644
--- a/chromium/content/browser/renderer_interface_binders.cc
+++ b/chromium/content/browser/renderer_interface_binders.cc
@@ -7,11 +7,13 @@
#include <utility>
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/no_destructor.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/native_file_system/native_file_system_manager_impl.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/browser/payments/payment_manager.h"
#include "content/browser/permissions/permission_service_context.h"
@@ -24,7 +26,10 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
+#include "media/mojo/interfaces/video_decode_perf_history.mojom.h"
+#include "media/mojo/services/video_decode_perf_history.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/vibration_manager.mojom.h"
#include "services/network/restricted_cookie_manager.h"
@@ -34,8 +39,10 @@
#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"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h"
#include "third_party/blink/public/mojom/cookie_store/cookie_store.mojom.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom.h"
#include "third_party/blink/public/mojom/notifications/notification_service.mojom.h"
#include "url/origin.h"
@@ -163,6 +170,25 @@ void RendererInterfaceBinders::InitializeParameterizedBinderRegistry() {
static_cast<RenderProcessHostImpl*>(host)->BindFileSystemManager(
std::move(request));
}));
+ if (base::FeatureList::IsEnabled(blink::features::kNativeFileSystemAPI)) {
+ parameterized_binder_registry_.AddInterface(base::BindRepeating(
+ [](blink::mojom::NativeFileSystemManagerRequest request,
+ RenderProcessHost* host, const url::Origin& origin) {
+ auto* manager =
+ static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
+ ->GetNativeFileSystemManager();
+ // This code path is only for workers, hence always pass in
+ // MSG_ROUTING_NONE as frame ID. Frames themselves go through
+ // RenderFrameHostImpl instead.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&NativeFileSystemManagerImpl::BindRequest,
+ base::Unretained(manager),
+ NativeFileSystemManagerImpl::BindingContext(
+ origin, host->GetID(), MSG_ROUTING_NONE),
+ std::move(request)));
+ }));
+ }
parameterized_binder_registry_.AddInterface(
base::Bind([](blink::mojom::PermissionServiceRequest request,
RenderProcessHost* host, const url::Origin& origin) {
@@ -177,13 +203,7 @@ void RendererInterfaceBinders::InitializeParameterizedBinderRegistry() {
->GetLockManager()
->CreateService(std::move(request), origin);
}));
- parameterized_binder_registry_.AddInterface(base::BindRepeating(
- [](blink::mojom::IdleManagerRequest request, RenderProcessHost* host,
- const url::Origin& origin) {
- static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
- ->GetIdleManager()
- ->CreateService(std::move(request), origin);
- }));
+
parameterized_binder_registry_.AddInterface(
base::Bind([](blink::mojom::NotificationServiceRequest request,
RenderProcessHost* host, const url::Origin& origin) {
@@ -204,6 +224,12 @@ void RendererInterfaceBinders::InitializeParameterizedBinderRegistry() {
->GetCookieStoreContext()
->CreateService(std::move(request), origin);
}));
+ parameterized_binder_registry_.AddInterface(base::BindRepeating(
+ [](media::mojom::VideoDecodePerfHistoryRequest request,
+ RenderProcessHost* host, const url::Origin& origin) {
+ host->GetBrowserContext()->GetVideoDecodePerfHistory()->BindRequest(
+ std::move(request));
+ }));
}
RendererInterfaceBinders& GetRendererInterfaceBinders() {
diff --git a/chromium/content/browser/resources/process/.eslintrc.js b/chromium/content/browser/resources/.eslintrc.js
index 25e21f992eb..154df9a5d0a 100644
--- a/chromium/content/browser/resources/process/.eslintrc.js
+++ b/chromium/content/browser/resources/.eslintrc.js
@@ -1,13 +1,10 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module.exports = {
- 'env': {
- 'browser': true,
- 'es6': true,
- },
'rules': {
'no-var': 'error',
+ 'prefer-const': 'error',
},
};
diff --git a/chromium/content/browser/resources/appcache/appcache_internals.js b/chromium/content/browser/resources/appcache/appcache_internals.js
index 91bc543c415..66a81e7ad29 100644
--- a/chromium/content/browser/resources/appcache/appcache_internals.js
+++ b/chromium/content/browser/resources/appcache/appcache_internals.js
@@ -5,16 +5,16 @@
cr.define('appcache', function() {
'use strict';
- var VIEW_DETAILS_TEXT = 'View Details';
- var HIDE_DETAILS_TEXT = 'Hide Details';
- var GET_ALL_APPCACHE = 'getAllAppCache';
- var DELETE_APPCACHE = 'deleteAppCache';
- var GET_APPCACHE_DETAILS = 'getAppCacheDetails';
- var GET_FILE_DETAILS = 'getFileDetails';
+ const VIEW_DETAILS_TEXT = 'View Details';
+ const HIDE_DETAILS_TEXT = 'Hide Details';
+ const GET_ALL_APPCACHE = 'getAllAppCache';
+ const DELETE_APPCACHE = 'deleteAppCache';
+ const GET_APPCACHE_DETAILS = 'getAppCacheDetails';
+ const GET_FILE_DETAILS = 'getFileDetails';
- var manifestsToView = [];
- var manifestsToDelete = [];
- var fileDetailsRequests = [];
+ const manifestsToView = [];
+ const manifestsToDelete = [];
+ const fileDetailsRequests = [];
function Manifest(url, path, link) {
this.url = url;
@@ -50,9 +50,9 @@ cr.define('appcache', function() {
}
function removeFromList(list, item, properties) {
- var pos = 0;
+ let pos = 0;
while (pos < list.length) {
- var candidate = list[pos];
+ const candidate = list[pos];
if (properties.every(function(key) {
return candidate[key] == item[key];
})) {
@@ -69,8 +69,8 @@ cr.define('appcache', function() {
function onAllAppCacheInfoReady(partition_path, display_name, data) {
- var template = jstGetTemplate('appcache-list-template');
- var container = $('appcache-list');
+ const template = jstGetTemplate('appcache-list-template');
+ const container = $('appcache-list');
container.appendChild(template);
jstProcess(
new JsEvalContext({
@@ -79,28 +79,28 @@ cr.define('appcache', function() {
display_name: display_name
}),
template);
- var removeLinks = container.querySelectorAll('a.remove-manifest');
- for (var i = 0; i < removeLinks.length; ++i) {
+ const removeLinks = container.querySelectorAll('a.remove-manifest');
+ for (let i = 0; i < removeLinks.length; ++i) {
removeLinks[i].onclick = deleteAppCacheInfoEventHandler;
}
- var viewLinks = container.querySelectorAll('a.view-details');
- for (i = 0; i < viewLinks.length; ++i) {
+ const viewLinks = container.querySelectorAll('a.view-details');
+ for (let i = 0; i < viewLinks.length; ++i) {
viewLinks[i].onclick = getAppCacheInfoEventHandler;
}
}
function getAppCacheInfoEventHandler(event) {
- var link = event.target;
+ const link = event.target;
if (link.text.indexOf(VIEW_DETAILS_TEXT) === -1) {
hideAppCacheInfo(link);
} else {
- var manifestURL = getFirstAncestor(link, function(node) {
- return !!node.manifestURL;
- }).manifestURL;
- var partitionPath = getFirstAncestor(link, function(node) {
- return !!node.partitionPath;
- }).partitionPath;
- var manifest = new Manifest(manifestURL, partitionPath, link);
+ const manifestURL = getFirstAncestor(link, function(node) {
+ return !!node.manifestURL;
+ }).manifestURL;
+ const partitionPath = getFirstAncestor(link, function(node) {
+ return !!node.partitionPath;
+ }).partitionPath;
+ const manifest = new Manifest(manifestURL, partitionPath, link);
if (getItemByProperties(
manifestsToView, ['url', 'path'], [manifestURL, partitionPath])) {
return;
@@ -124,30 +124,30 @@ cr.define('appcache', function() {
'"' + partitionPath + '".');
return;
}
- var manifest = getItemByProperties(
+ const manifest = getItemByProperties(
manifestsToView, ['url', 'path'], [manifestURL, partitionPath]);
- var link = manifest.link;
+ const link = manifest.link;
removeFromList(manifestsToView, manifest, ['url', 'path']);
- var container = getFirstAncestor(link, function(node) {
- return node.className === 'appcache-info-item';
- }).querySelector('.appcache-details');
- var template = jstGetTemplate('appcache-info-template');
+ const container = getFirstAncestor(link, function(node) {
+ return node.className === 'appcache-info-item';
+ }).querySelector('.appcache-details');
+ const template = jstGetTemplate('appcache-info-template');
container.appendChild(template);
jstProcess(
new JsEvalContext({items: simplifyAppCacheInfo(details)}), template);
- var fileLinks =
+ const fileLinks =
container.querySelectorAll('a.appcache-info-template-file-url');
- for (var i = 0; i < fileLinks.length; ++i) {
+ for (let i = 0; i < fileLinks.length; ++i) {
fileLinks[i].onclick = getFileContentsEventHandler;
}
link.text = HIDE_DETAILS_TEXT;
}
function simplifyAppCacheInfo(detailsVector) {
- var simpleVector = [];
- for (var index = 0; index < detailsVector.length; ++index) {
- var details = detailsVector[index];
- var properties = [];
+ const simpleVector = [];
+ for (let index = 0; index < detailsVector.length; ++index) {
+ const details = detailsVector[index];
+ let properties = [];
if (details.isManifest) {
properties.push('Manifest');
}
@@ -180,27 +180,27 @@ cr.define('appcache', function() {
}
function deleteAppCacheInfoEventHandler(event) {
- var link = event.target;
- var manifestURL = getFirstAncestor(link, function(node) {
- return !!node.manifestURL;
- }).manifestURL;
- var partitionPath = getFirstAncestor(link, function(node) {
- return !!node.partitionPath;
- }).partitionPath;
- var manifest = new Manifest(manifestURL, partitionPath, link);
+ const link = event.target;
+ const manifestURL = getFirstAncestor(link, function(node) {
+ return !!node.manifestURL;
+ }).manifestURL;
+ const partitionPath = getFirstAncestor(link, function(node) {
+ return !!node.partitionPath;
+ }).partitionPath;
+ const manifest = new Manifest(manifestURL, partitionPath, link);
manifestsToDelete.push(manifest);
chrome.send(DELETE_APPCACHE, [partitionPath, manifestURL]);
}
function onAppCacheInfoDeleted(partitionPath, manifestURL, deleted) {
- var manifest = getItemByProperties(
+ const manifest = getItemByProperties(
manifestsToDelete, ['url', 'path'], [manifestURL, partitionPath]);
if (manifest && deleted) {
- var link = manifest.link;
- var appcacheItemNode = getFirstAncestor(link, function(node) {
+ const link = manifest.link;
+ const appcacheItemNode = getFirstAncestor(link, function(node) {
return node.className === 'appcache-info-item';
});
- var appcacheNode = getFirstAncestor(link, function(node) {
+ const appcacheNode = getFirstAncestor(link, function(node) {
return node.className === 'appcache-item';
});
appcacheItemNode.parentNode.removeChild(appcacheItemNode);
@@ -216,22 +216,22 @@ cr.define('appcache', function() {
}
function getFileContentsEventHandler(event) {
- var link = event.target;
- var partitionPath = getFirstAncestor(link, function(node) {
- return !!node.partitionPath;
- }).partitionPath;
- var manifestURL = getFirstAncestor(link, function(node) {
- return !!node.manifestURL;
- }).manifestURL;
- var groupId = getFirstAncestor(link, function(node) {
- return !!node.groupId;
- }).groupId;
- var responseId = link.responseId;
+ const link = event.target;
+ const partitionPath = getFirstAncestor(link, function(node) {
+ return !!node.partitionPath;
+ }).partitionPath;
+ const manifestURL = getFirstAncestor(link, function(node) {
+ return !!node.manifestURL;
+ }).manifestURL;
+ const groupId = getFirstAncestor(link, function(node) {
+ return !!node.groupId;
+ }).groupId;
+ const responseId = link.responseId;
if (!getItemByProperties(
fileDetailsRequests, ['manifestURL', 'groupId', 'responseId'],
[manifestURL, groupId, responseId])) {
- var fileRequest = new FileRequest(
+ const fileRequest = new FileRequest(
link.innerText, manifestURL, partitionPath, groupId, responseId);
fileDetailsRequests.push(fileRequest);
chrome.send(
@@ -240,7 +240,7 @@ cr.define('appcache', function() {
}
function onFileDetailsFailed(response, code) {
- var request = getItemByProperties(
+ const request = getItemByProperties(
fileDetailsRequests, ['manifestURL', 'groupId', 'responseId'],
[response.manifestURL, response.groupId, response.responseId]);
console.log(
@@ -252,20 +252,20 @@ cr.define('appcache', function() {
}
function onFileDetailsReady(response, headers, raw_data) {
- var request = getItemByProperties(
+ const request = getItemByProperties(
fileDetailsRequests, ['manifestURL', 'groupId', 'responseId'],
[response.manifestURL, response.groupId, response.responseId]);
removeFromList(
fileDetailsRequests, request, ['manifestURL', 'groupId', 'responseId']);
- var doc = window.open().document;
- var head = document.createElement('head');
+ const doc = window.open().document;
+ const head = document.createElement('head');
doc.title = 'File Details: '.concat(request.fileURL);
- var headersDiv = doc.createElement('div');
+ const headersDiv = doc.createElement('div');
headersDiv.innerHTML = headers;
doc.body.appendChild(headersDiv);
- var hexDumpDiv = doc.createElement('div');
+ const hexDumpDiv = doc.createElement('div');
hexDumpDiv.innerHTML = raw_data;
- var linkToManifest = doc.createElement('a');
+ const linkToManifest = doc.createElement('a');
linkToManifest.style.color = '#3C66DD';
linkToManifest.href = request.fileURL;
linkToManifest.target = '_blank';
@@ -279,13 +279,13 @@ cr.define('appcache', function() {
}
function copyStylesFrom(src, dest) {
- var styles = src.querySelector('style');
+ const styles = src.querySelector('style');
if (dest.getElementsByTagName('style').length < 1) {
dest.head.appendChild(dest.createElement('style'));
}
- var destStyle = dest.querySelector('style');
- var tmp = '';
- for (var i = 0; i < styles.length; ++i) {
+ const destStyle = dest.querySelector('style');
+ let tmp = '';
+ for (let i = 0; i < styles.length; ++i) {
tmp += styles[i].innerHTML;
}
destStyle.innerHTML = tmp;
diff --git a/chromium/content/browser/resources/gpu/browser_bridge.js b/chromium/content/browser/resources/gpu/browser_bridge.js
index 9fc1ec3ba8a..6b01029813e 100644
--- a/chromium/content/browser/resources/gpu/browser_bridge.js
+++ b/chromium/content/browser/resources/gpu/browser_bridge.js
@@ -14,7 +14,7 @@ cr.define('gpu', function() {
// to the console to help with quick-iteration debugging.
this.debugMode_ = (chrome.send === undefined && console.log);
if (this.debugMode_) {
- var browserBridgeTests = document.createElement('script');
+ const browserBridgeTests = document.createElement('script');
browserBridgeTests.src = './gpu_internals/browser_bridge_tests.js';
document.body.appendChild(browserBridgeTests);
}
@@ -54,13 +54,13 @@ cr.define('gpu', function() {
* browser will reply asynchronously via the provided callback.
*/
callAsync(submessage, args, callback) {
- var requestId = this.nextRequestId_;
+ const requestId = this.nextRequestId_;
this.nextRequestId_ += 1;
this.pendingCallbacks_[requestId] = callback;
if (!args) {
chrome.send('callAsync', [requestId.toString(), submessage]);
} else {
- var allArgs = [requestId.toString(), submessage].concat(args);
+ const allArgs = [requestId.toString(), submessage].concat(args);
chrome.send('callAsync', allArgs);
}
}
@@ -72,7 +72,7 @@ cr.define('gpu', function() {
if (this.pendingCallbacks_[requestId] === undefined) {
throw new Error('requestId ' + requestId + ' is not pending');
}
- var callback = this.pendingCallbacks_[requestId];
+ const callback = this.pendingCallbacks_[requestId];
callback(args);
delete this.pendingCallbacks_[requestId];
}
@@ -145,7 +145,7 @@ cr.define('gpu', function() {
*/
isSandboxedForTesting() {
for (i = 0; i < this.gpuInfo_.basicInfo.length; ++i) {
- var info = this.gpuInfo_.basicInfo[i];
+ const info = this.gpuInfo_.basicInfo[i];
if (info.description == 'Sandboxed') {
return info.value;
}
diff --git a/chromium/content/browser/resources/gpu/browser_bridge_tests.js b/chromium/content/browser/resources/gpu/browser_bridge_tests.js
index 21eb3af0c36..9cebfac74f5 100644
--- a/chromium/content/browser/resources/gpu/browser_bridge_tests.js
+++ b/chromium/content/browser/resources/gpu/browser_bridge_tests.js
@@ -1,13 +1,13 @@
// 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.
-var commandLineFlags = [
+const commandLineFlags = [
'--flag-switches-begin', '--show-composited-layer-borders',
'--flag-switches-end'
];
-var commandLineStr = './out/Debug/chrome ' + commandLineFlags.join(' ');
+const commandLineStr = './out/Debug/chrome ' + commandLineFlags.join(' ');
-var glValueArray = [
+const glValueArray = [
'GL_ARB_compatibility',
'GL_ARB_copy_buffer',
'GL_ARB_depth_buffer_float',
@@ -187,7 +187,7 @@ var glValueArray = [
'GL_SUN_slice_accum'
];
(function() {
-var dataSets = [
+const dataSets = [
{
name: 'full_data_linux',
gpuInfo: {
@@ -268,9 +268,9 @@ var dataSets = [
];
-var selectEl = document.createElement('select');
-for (var i = 0; i < dataSets.length; ++i) {
- var optionEl = document.createElement('option');
+const selectEl = document.createElement('select');
+for (let i = 0; i < dataSets.length; ++i) {
+ const optionEl = document.createElement('option');
optionEl.textContent = dataSets[i].name;
optionEl.dataSet = dataSets[i];
selectEl.add(optionEl);
@@ -284,8 +284,8 @@ selectEl.addEventListener('keydown', function() {
}, 0);
});
-var controlEl = document.createElement('div');
-var textEl = document.createElement('span');
+const controlEl = document.createElement('div');
+const textEl = document.createElement('span');
textEl.textContent = 'GPU Info:';
controlEl.appendChild(textEl);
controlEl.appendChild(selectEl);
diff --git a/chromium/content/browser/resources/gpu/gpu_internals.js b/chromium/content/browser/resources/gpu/gpu_internals.js
index 3968b2187df..855aa3e608d 100644
--- a/chromium/content/browser/resources/gpu/gpu_internals.js
+++ b/chromium/content/browser/resources/gpu/gpu_internals.js
@@ -5,7 +5,7 @@
// <include src="browser_bridge.js">
// <include src="info_view.js">
-var browserBridge;
+let browserBridge;
/**
* Main entry point. called once the page has loaded.
diff --git a/chromium/content/browser/resources/gpu/info_view.js b/chromium/content/browser/resources/gpu/info_view.js
index cabbf54f4ea..fdbeca06f8c 100644
--- a/chromium/content/browser/resources/gpu/info_view.js
+++ b/chromium/content/browser/resources/gpu/info_view.js
@@ -14,7 +14,7 @@ cr.define('gpu', function() {
* @constructor
* @extends {cr.ui.TabPanel}
*/
- var InfoView = cr.ui.define(cr.ui.TabPanel);
+ const InfoView = cr.ui.define(cr.ui.TabPanel);
InfoView.prototype = {
__proto__: cr.ui.TabPanel.prototype,
@@ -47,6 +47,7 @@ cr.define('gpu', function() {
* Updates the view based on its currently known data
*/
refresh: function(data) {
+ let clientInfo;
function createSourcePermalink(revisionIdentifier, filepath) {
if (revisionIdentifier.length !== 40) {
// If the revision id isn't a hash, just use the 0.0.0.0 version
@@ -59,7 +60,7 @@ cr.define('gpu', function() {
// Client info
if (browserBridge.clientInfo) {
- var clientInfo = browserBridge.clientInfo;
+ clientInfo = browserBridge.clientInfo;
this.setTable_('client-info', [
{description: 'Data exported', value: (new Date()).toISOString()},
@@ -89,31 +90,31 @@ cr.define('gpu', function() {
// GPU info, basic
- var diagnosticsDiv = this.querySelector('.diagnostics');
- var diagnosticsLoadingDiv = this.querySelector('.diagnostics-loading');
- var featureStatusList = this.querySelector('.feature-status-list');
- var problemsDiv = this.querySelector('.problems-div');
- var problemsList = this.querySelector('.problems-list');
- var workaroundsDiv = this.querySelector('.workarounds-div');
- var workaroundsList = this.querySelector('.workarounds-list');
-
- var basicInfoForHardwareGpuDiv =
+ const diagnosticsDiv = this.querySelector('.diagnostics');
+ const diagnosticsLoadingDiv = this.querySelector('.diagnostics-loading');
+ const featureStatusList = this.querySelector('.feature-status-list');
+ const problemsDiv = this.querySelector('.problems-div');
+ const problemsList = this.querySelector('.problems-list');
+ const workaroundsDiv = this.querySelector('.workarounds-div');
+ const workaroundsList = this.querySelector('.workarounds-list');
+
+ const basicInfoForHardwareGpuDiv =
this.querySelector('.basic-info-for-hardware-gpu-div');
- var featureStatusForHardwareGpuDiv =
+ const featureStatusForHardwareGpuDiv =
this.querySelector('.feature-status-for-hardware-gpu-div');
- var featureStatusForHardwareGpuList =
+ const featureStatusForHardwareGpuList =
this.querySelector('.feature-status-for-hardware-gpu-list');
- var problemsForHardwareGpuDiv =
+ const problemsForHardwareGpuDiv =
this.querySelector('.problems-for-hardware-gpu-div');
- var problemsForHardwareGpuList =
+ const problemsForHardwareGpuList =
this.querySelector('.problems-for-hardware-gpu-list');
- var workaroundsForHardwareGpuDiv =
+ const workaroundsForHardwareGpuDiv =
this.querySelector('.workarounds-for-hardware-gpu-div');
- var workaroundsForHardwareGpuList =
+ const workaroundsForHardwareGpuList =
this.querySelector('.workarounds-for-hardware-gpu-list');
- var gpuInfo = browserBridge.gpuInfo;
- var i;
+ const gpuInfo = browserBridge.gpuInfo;
+ let i;
if (gpuInfo) {
// Not using jstemplate here for blacklist status because we construct
// href from data, which jstemplate can't seem to do.
@@ -211,7 +212,7 @@ cr.define('gpu', function() {
featureInfo, featureStatusList, problemsDiv, problemsList,
workaroundsDiv, workaroundsList) {
// Feature map
- var featureLabelMap = {
+ const featureLabelMap = {
'2d_canvas': 'Canvas',
'gpu_compositing': 'Compositing',
'webgl': 'WebGL',
@@ -223,6 +224,7 @@ cr.define('gpu', function() {
'video_decode': 'Video Decode',
'rasterization': 'Rasterization',
'oop_rasterization': 'Out-of-process Rasterization',
+ 'metal': 'Metal',
'multiple_raster_threads': 'Multiple Raster Threads',
'native_gpu_memory_buffers': 'Native GpuMemoryBuffers',
'protected_video_decode': 'Hardware Protected Video Decode',
@@ -235,7 +237,7 @@ cr.define('gpu', function() {
'skia_renderer': 'Skia Renderer',
};
- var statusMap = {
+ const statusMap = {
'disabled_software': {
'label': 'Software only. Hardware acceleration disabled',
'class': 'feature-yellow'
@@ -265,19 +267,19 @@ cr.define('gpu', function() {
// feature status list
featureStatusList.textContent = '';
- for (var featureName in featureInfo.featureStatus) {
- var featureStatus = featureInfo.featureStatus[featureName];
- var featureEl = document.createElement('li');
+ for (const featureName in featureInfo.featureStatus) {
+ const featureStatus = featureInfo.featureStatus[featureName];
+ const featureEl = document.createElement('li');
- var nameEl = document.createElement('span');
+ const nameEl = document.createElement('span');
if (!featureLabelMap[featureName]) {
console.log('Missing featureLabel for', featureName);
}
nameEl.textContent = featureLabelMap[featureName] + ': ';
featureEl.appendChild(nameEl);
- var statusEl = document.createElement('span');
- var statusInfo = statusMap[featureStatus];
+ const statusEl = document.createElement('span');
+ const statusInfo = statusMap[featureStatus];
if (!statusInfo) {
console.log('Missing status for ', featureStatus);
statusEl.textContent = 'Unknown';
@@ -296,8 +298,8 @@ cr.define('gpu', function() {
problemsDiv.hidden = false;
problemsList.textContent = '';
for (i = 0; i < featureInfo.problems.length; i++) {
- var problem = featureInfo.problems[i];
- var problemEl = this.createProblemEl_(problem);
+ const problem = featureInfo.problems[i];
+ const problemEl = this.createProblemEl_(problem);
problemsList.appendChild(problemEl);
}
} else {
@@ -309,7 +311,7 @@ cr.define('gpu', function() {
workaroundsDiv.hidden = false;
workaroundsList.textContent = '';
for (i = 0; i < featureInfo.workarounds.length; i++) {
- var workaroundEl = document.createElement('li');
+ const workaroundEl = document.createElement('li');
workaroundEl.textContent = featureInfo.workarounds[i];
workaroundsList.appendChild(workaroundEl);
}
@@ -319,34 +321,33 @@ cr.define('gpu', function() {
},
createProblemEl_: function(problem) {
- var problemEl;
- problemEl = document.createElement('li');
+ const problemEl = document.createElement('li');
// Description of issue
- var desc = document.createElement('a');
+ const desc = document.createElement('a');
desc.textContent = problem.description;
problemEl.appendChild(desc);
// Spacing ':' element
if (problem.crBugs.length > 0) {
- var tmp = document.createElement('span');
+ const tmp = document.createElement('span');
tmp.textContent = ': ';
problemEl.appendChild(tmp);
}
- var nbugs = 0;
- var j;
+ let nbugs = 0;
+ let j;
// crBugs
for (j = 0; j < problem.crBugs.length; ++j) {
if (nbugs > 0) {
- var tmp = document.createElement('span');
+ const tmp = document.createElement('span');
tmp.textContent = ', ';
problemEl.appendChild(tmp);
}
- var link = document.createElement('a');
- var bugid = parseInt(problem.crBugs[j]);
+ const link = document.createElement('a');
+ const bugid = parseInt(problem.crBugs[j]);
link.textContent = bugid;
link.href = 'http://crbug.com/' + bugid;
problemEl.appendChild(link);
@@ -354,13 +355,13 @@ cr.define('gpu', function() {
}
if (problem.affectedGpuSettings.length > 0) {
- var brNode = document.createElement('br');
+ const brNode = document.createElement('br');
problemEl.appendChild(brNode);
- var iNode = document.createElement('i');
+ const iNode = document.createElement('i');
problemEl.appendChild(iNode);
- var headNode = document.createElement('span');
+ const headNode = document.createElement('span');
if (problem.tag == 'disabledFeatures') {
headNode.textContent = 'Disabled Features: ';
} else { // problem.tag == 'workarounds'
@@ -369,11 +370,11 @@ cr.define('gpu', function() {
iNode.appendChild(headNode);
for (j = 0; j < problem.affectedGpuSettings.length; ++j) {
if (j > 0) {
- var separateNode = document.createElement('span');
+ const separateNode = document.createElement('span');
separateNode.textContent = ', ';
iNode.appendChild(separateNode);
}
- var nameNode = document.createElement('span');
+ const nameNode = document.createElement('span');
if (problem.tag == 'disabledFeatures') {
nameNode.classList.add('feature-red');
} else { // problem.tag == 'workarounds'
@@ -388,15 +389,15 @@ cr.define('gpu', function() {
},
setText_: function(outputElementId, text) {
- var peg = $(outputElementId);
+ const peg = $(outputElementId);
peg.textContent = text;
},
setTable_: function(outputElementId, inputData) {
- var template = jstGetTemplate('info-view-table-template');
+ const template = jstGetTemplate('info-view-table-template');
jstProcess(new JsEvalContext({value: inputData}), template);
- var peg = $(outputElementId);
+ const peg = $(outputElementId);
if (!peg) {
throw new Error('Node ' + outputElementId + ' not found');
}
diff --git a/chromium/content/browser/resources/indexed_db/indexeddb_internals.js b/chromium/content/browser/resources/indexed_db/indexeddb_internals.js
index 1f3959d1ee8..98b0097578d 100644
--- a/chromium/content/browser/resources/indexed_db/indexeddb_internals.js
+++ b/chromium/content/browser/resources/indexed_db/indexeddb_internals.js
@@ -14,7 +14,7 @@ cr.define('indexeddb', function() {
}
function downloadOriginData(event) {
- var link = event.target;
+ const link = event.target;
progressNodeFor(link).style.display = 'inline';
chrome.send(
'downloadOriginData', [link.idb_partition_path, link.idb_origin_url]);
@@ -22,14 +22,14 @@ cr.define('indexeddb', function() {
}
function forceClose(event) {
- var link = event.target;
+ const link = event.target;
progressNodeFor(link).style.display = 'inline';
chrome.send('forceClose', [link.idb_partition_path, link.idb_origin_url]);
return false;
}
function forceSchemaDowngrade(event) {
- var link = event.target;
+ const link = event.target;
progressNodeFor(link).style.display = 'inline';
chrome.send(
'forceSchemaDowngrade', [link.idb_partition_path, link.idb_origin_url]);
@@ -37,9 +37,9 @@ cr.define('indexeddb', function() {
}
function withNode(selector, partition_path, origin_url, callback) {
- var links = document.querySelectorAll(selector);
- for (var i = 0; i < links.length; ++i) {
- var link = links[i];
+ const links = document.querySelectorAll(selector);
+ for (let i = 0; i < links.length; ++i) {
+ const link = links[i];
if (partition_path == link.idb_partition_path &&
origin_url == link.idb_origin_url) {
callback(link);
@@ -80,24 +80,24 @@ cr.define('indexeddb', function() {
// Fired from the backend with a single partition's worth of
// IndexedDB metadata.
function onOriginsReady(origins, partition_path) {
- var template = jstGetTemplate('indexeddb-list-template');
- var container = $('indexeddb-list');
+ const template = jstGetTemplate('indexeddb-list-template');
+ const container = $('indexeddb-list');
container.appendChild(template);
jstProcess(
new JsEvalContext({idbs: origins, partition_path: partition_path}),
template);
- var downloadLinks = container.querySelectorAll('a.download');
- for (var i = 0; i < downloadLinks.length; ++i) {
+ const downloadLinks = container.querySelectorAll('a.download');
+ for (let i = 0; i < downloadLinks.length; ++i) {
downloadLinks[i].addEventListener('click', downloadOriginData, false);
}
- var forceCloseLinks = container.querySelectorAll('a.force-close');
- for (i = 0; i < forceCloseLinks.length; ++i) {
+ const forceCloseLinks = container.querySelectorAll('a.force-close');
+ for (let i = 0; i < forceCloseLinks.length; ++i) {
forceCloseLinks[i].addEventListener('click', forceClose, false);
}
- var forceSchemaDowngradeLinks =
+ const forceSchemaDowngradeLinks =
container.querySelectorAll('a.force-schema-downgrade');
- for (i = 0; i < forceSchemaDowngradeLinks.length; ++i) {
+ for (let i = 0; i < forceSchemaDowngradeLinks.length; ++i) {
forceSchemaDowngradeLinks[i].addEventListener(
'click', forceSchemaDowngrade, false);
}
diff --git a/chromium/content/browser/resources/media/.eslintrc.js b/chromium/content/browser/resources/media/.eslintrc.js
new file mode 100644
index 00000000000..a1891fc72d1
--- /dev/null
+++ b/chromium/content/browser/resources/media/.eslintrc.js
@@ -0,0 +1,10 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+ 'rules': {
+ 'no-var': 'off',
+ 'prefer-const': 'off',
+ },
+};
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 ec5a5ed212e..7f9804a0b2c 100644
--- a/chromium/content/browser/resources/media/peer_connection_update_table.js
+++ b/chromium/content/browser/resources/media/peer_connection_update_table.js
@@ -89,7 +89,9 @@ var PeerConnectionUpdateTable = (function() {
onRenegotiationNeeded: 'negotiationneeded',
signalingStateChange: 'signalingstatechange',
iceGatheringStateChange: 'icegatheringstatechange',
+ legacyIceConnectionStateChange: 'iceconnectionstatechange (legacy)',
iceConnectionStateChange: 'iceconnectionstatechange',
+ connectionStateChange: 'connectionstatechange',
onIceCandidate: 'icecandidate',
stop: 'close'
}[update.type] ||
diff --git a/chromium/content/browser/resources/media/stats_graph_helper.js b/chromium/content/browser/resources/media/stats_graph_helper.js
index b8e0d3ad39b..46271ff3d68 100644
--- a/chromium/content/browser/resources/media/stats_graph_helper.js
+++ b/chromium/content/browser/resources/media/stats_graph_helper.js
@@ -168,9 +168,6 @@ function drawSingleReport(peerConnectionElement, report, isLegacyReport) {
if (!stats || !stats.values) {
return;
}
- if (!isLegacyReport && isStandardReportBlacklisted(report)) {
- return;
- }
const childrenBefore = peerConnectionElement.hasChildNodes() ?
Array.from(peerConnectionElement.childNodes) :
@@ -178,10 +175,6 @@ function drawSingleReport(peerConnectionElement, report, isLegacyReport) {
for (var i = 0; i < stats.values.length - 1; i = i + 2) {
var rawLabel = stats.values[i];
- if (!isLegacyReport && isStandardStatBlacklisted(report, rawLabel)) {
- continue;
- }
-
// Propagation deltas are handled separately.
if (rawLabel == RECEIVED_PROPAGATION_DELTA_LABEL) {
drawReceivedPropagationDelta(
@@ -198,7 +191,6 @@ function drawSingleReport(peerConnectionElement, report, isLegacyReport) {
[stats.values[i + 1]]);
continue;
}
-
var finalDataSeriesId = rawDataSeriesId;
var finalLabel = rawLabel;
var finalValue = rawValue;
@@ -223,6 +215,14 @@ function drawSingleReport(peerConnectionElement, report, isLegacyReport) {
peerConnectionElement, finalDataSeriesId, finalLabel, [stats.timestamp],
[finalValue]);
+ if (!isLegacyReport &&
+ (isStandardReportBlacklisted(report) ||
+ isStandardStatBlacklisted(report, rawLabel))) {
+ // We do not want to draw certain standard reports but still want to
+ // record them in the data series.
+ continue;
+ }
+
// Updates the graph.
var graphType =
bweCompoundGraphConfig[finalLabel] ? 'bweCompound' : finalLabel;
diff --git a/chromium/content/browser/resources/media/stats_rates_calculator.js b/chromium/content/browser/resources/media/stats_rates_calculator.js
index 2d85eee4139..36cff04e931 100644
--- a/chromium/content/browser/resources/media/stats_rates_calculator.js
+++ b/chromium/content/browser/resources/media/stats_rates_calculator.js
@@ -189,7 +189,37 @@ class StatsRatesCalculator {
names: [
['bytesSent', 'timestamp'],
['packetsSent', 'timestamp'],
+ [
+ 'totalPacketSendDelay',
+ 'packetsSent',
+ '[totalPacketSendDelay/packetsSent_in_ms]',
+ (value) => {
+ return value * 1000; // s -> ms
+ },
+ ],
['framesEncoded', 'timestamp'],
+ [
+ 'totalEncodedBytesTarget', 'framesEncoded',
+ '[targetEncodedBytes/s]',
+ (value, currentStats, previousStats) => {
+ if (!previousStats) {
+ return 0;
+ }
+ const deltaTime =
+ currentStats.timestamp - previousStats.timestamp;
+ const deltaFrames =
+ currentStats.framesEncoded - previousStats.framesEncoded;
+ const encodedFrameRate = deltaFrames / deltaTime;
+ return value * encodedFrameRate;
+ }
+ ],
+ [
+ 'totalEncodeTime', 'framesEncoded',
+ '[totalEncodeTime/framesEncoded_in_ms]',
+ (value) => {
+ return value * 1000; // s -> ms
+ }
+ ],
['qpSum', 'framesEncoded'],
],
},
@@ -252,7 +282,8 @@ class StatsRatesCalculator {
let result = this.calculateAccumulativeMetricOverSamples_(
stats.id, accumulativeMetric, samplesMetric);
if (result && transformation) {
- result = transformation(result);
+ const previousStats = this.previousReport.get(stats.id);
+ result = transformation(result, stats, previousStats);
}
this.currentReport.setCalculatedMetric(
stats.id, accumulativeMetric, resultName, result);
diff --git a/chromium/content/browser/resources/media/webrtc_internals.css b/chromium/content/browser/resources/media/webrtc_internals.css
index 349c8c2552c..e6c1a33992f 100644
--- a/chromium/content/browser/resources/media/webrtc_internals.css
+++ b/chromium/content/browser/resources/media/webrtc_internals.css
@@ -48,7 +48,6 @@
.stats-table-container {
float: left;
padding: 0 0 0 0;
- width: 50em;
overflow: auto;
}
diff --git a/chromium/content/browser/resources/media/webrtc_internals.html b/chromium/content/browser/resources/media/webrtc_internals.html
index 39434b9be38..76a818fe3c0 100644
--- a/chromium/content/browser/resources/media/webrtc_internals.html
+++ b/chromium/content/browser/resources/media/webrtc_internals.html
@@ -1,5 +1,5 @@
<!doctype html>
-<html i18n-values="dir:textdirection;lang:language">
+<html>
<head>
<meta charset="utf-8">
<title>WebRTC Internals</title>
@@ -8,7 +8,7 @@
<script src="webrtc_internals.js"></script>
</head>
<body>
- <p id='content-root'>
+ <p id="content-root">
</p>
</body>
</html>
diff --git a/chromium/content/browser/resources/net/network_errors_listing.js b/chromium/content/browser/resources/net/network_errors_listing.js
index 22fd7d64a87..31b994a488d 100644
--- a/chromium/content/browser/resources/net/network_errors_listing.js
+++ b/chromium/content/browser/resources/net/network_errors_listing.js
@@ -7,15 +7,15 @@ cr.define('errorCodes', function() {
/**
* Generate the page content.
- * @param {Array.<Object>} errorCodes Error codes array consisting of a
+ * @param {Array<Object>} errorCodes Error codes array consisting of a
* numerical error ID and error code string.
*/
function listErrorCodes(errorCodes) {
- var errorPageUrl = 'chrome://network-error/';
- var errorCodesList = document.createElement('ul');
- for (var i = 0; i < errorCodes.length; i++) {
- var listEl = document.createElement('li');
- var errorCodeLinkEl = document.createElement('a');
+ const errorPageUrl = 'chrome://network-error/';
+ const errorCodesList = document.createElement('ul');
+ for (let i = 0; i < errorCodes.length; i++) {
+ const listEl = document.createElement('li');
+ const errorCodeLinkEl = document.createElement('a');
errorCodeLinkEl.href = errorPageUrl + errorCodes[i].errorId;
errorCodeLinkEl.textContent =
errorCodes[i].errorCode + ' (' + errorCodes[i].errorId + ')';
@@ -26,12 +26,12 @@ cr.define('errorCodes', function() {
}
function initialize() {
- var xhr = new XMLHttpRequest();
+ const xhr = new XMLHttpRequest();
xhr.open('GET', 'network-error-data.json');
xhr.addEventListener('load', function(e) {
if (xhr.status === 200) {
try {
- var data = JSON.parse(xhr.responseText);
+ const data = JSON.parse(xhr.responseText);
listErrorCodes(data['errorCodes']);
} catch (e) {
$('pages').innerText = 'Could not parse the error codes data. ' +
@@ -45,4 +45,4 @@ cr.define('errorCodes', function() {
return {initialize: initialize};
});
-document.addEventListener('DOMContentLoaded', errorCodes.initialize); \ No newline at end of file
+document.addEventListener('DOMContentLoaded', errorCodes.initialize);
diff --git a/chromium/content/browser/resources/process/process_internals.html b/chromium/content/browser/resources/process/process_internals.html
index d5afec18d64..07d458c38a4 100644
--- a/chromium/content/browser/resources/process/process_internals.html
+++ b/chromium/content/browser/resources/process/process_internals.html
@@ -8,14 +8,15 @@
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<script src="chrome://resources/js/util.js"></script>
<script src="chrome://resources/js/cr.js"></script>
- <script src="chrome://resources/js/mojo_bindings_lite.js"></script>
+ <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js">
+ </script>
+ <script src="chrome://resources/mojo/url/mojom/url.mojom-lite.js"></script>
<link rel="stylesheet" href="chrome://resources/css/tree.css">
<script src="chrome://resources/js/cr/ui.js"></script>
<script src="chrome://resources/js/cr/ui/tree.js"></script>
<link rel="stylesheet" href="process_internals.css">
- <script src="url.mojom-lite.js"></script>
<script src="process_internals.mojom-lite.js"></script>
<script src='process_internals.js'></script>
<title>Process Model Internals</title>
diff --git a/chromium/content/browser/resources/service_worker/serviceworker_internals.js b/chromium/content/browser/resources/service_worker/serviceworker_internals.js
index 4f649329ba2..05eb06a5a1f 100644
--- a/chromium/content/browser/resources/service_worker/serviceworker_internals.js
+++ b/chromium/content/browser/resources/service_worker/serviceworker_internals.js
@@ -15,8 +15,8 @@ cr.define('serviceworker', function() {
}
function onOptions(options) {
- var template;
- var container = $('serviceworker-options');
+ let template;
+ const container = $('serviceworker-options');
if (container.childNodes) {
template = container.childNodes[0];
}
@@ -25,8 +25,8 @@ cr.define('serviceworker', function() {
container.appendChild(template);
}
jstProcess(new JsEvalContext(options), template);
- var inputs = container.querySelectorAll('input[type=\'checkbox\']');
- for (var i = 0; i < inputs.length; ++i) {
+ const inputs = container.querySelectorAll('input[type=\'checkbox\']');
+ for (let i = 0; i < inputs.length; ++i) {
if (!inputs[i].hasClickEvent) {
inputs[i].addEventListener(
'click',
@@ -45,10 +45,10 @@ cr.define('serviceworker', function() {
}
// All commands are completed with 'onOperationComplete'.
- var COMMANDS = ['stop', 'inspect', 'unregister', 'start'];
+ const COMMANDS = ['stop', 'inspect', 'unregister', 'start'];
function commandHandler(command) {
return function(event) {
- var link = event.target;
+ const link = event.target;
progressNodeFor(link).style.display = 'inline';
sendCommand(command, link.cmdArgs, (function(status) {
progressNodeFor(link).style.display =
@@ -58,9 +58,9 @@ cr.define('serviceworker', function() {
};
}
- var commandCallbacks = [];
+ const commandCallbacks = [];
function sendCommand(command, args, callback) {
- var callbackId = 0;
+ let callbackId = 0;
while (callbackId in commandCallbacks) {
callbackId++;
}
@@ -70,7 +70,7 @@ cr.define('serviceworker', function() {
// Fired from the backend after the command call has completed.
function onOperationComplete(status, callbackId) {
- var callback = commandCallbacks[callbackId];
+ const callback = commandCallbacks[callbackId];
delete commandCallbacks[callbackId];
if (callback) {
callback(status);
@@ -78,7 +78,7 @@ cr.define('serviceworker', function() {
update();
}
- var allLogMessages = {};
+ const allLogMessages = {};
// Set log for a worker version.
function fillLogForVersion(container, partition_id, version) {
if (!version) {
@@ -87,15 +87,15 @@ cr.define('serviceworker', function() {
if (!(partition_id in allLogMessages)) {
allLogMessages[partition_id] = {};
}
- var logMessages = allLogMessages[partition_id];
+ const logMessages = allLogMessages[partition_id];
if (version.version_id in logMessages) {
version.log = logMessages[version.version_id];
} else {
version.log = '';
}
- var logAreas = container.querySelectorAll('textarea.serviceworker-log');
- for (var i = 0; i < logAreas.length; ++i) {
- var logArea = logAreas[i];
+ const logAreas = container.querySelectorAll('textarea.serviceworker-log');
+ for (let i = 0; i < logAreas.length; ++i) {
+ const logArea = logAreas[i];
if (logArea.partition_id == partition_id &&
logArea.version_id == version.version_id) {
logArea.value = version.log;
@@ -112,8 +112,8 @@ cr.define('serviceworker', function() {
function getUnregisteredWorkers(
stored_registrations, live_registrations, live_versions,
unregistered_registrations, unregistered_versions) {
- var registrationIdSet = {};
- var versionIdSet = {};
+ const registrationIdSet = {};
+ const versionIdSet = {};
stored_registrations.forEach(function(registration) {
registrationIdSet[registration.registration_id] = true;
});
@@ -143,17 +143,17 @@ cr.define('serviceworker', function() {
function onPartitionData(
live_registrations, live_versions, stored_registrations, partition_id,
partition_path) {
- var unregisteredRegistrations = [];
- var unregisteredVersions = [];
+ const unregisteredRegistrations = [];
+ const unregisteredVersions = [];
getUnregisteredWorkers(
stored_registrations, live_registrations, live_versions,
unregisteredRegistrations, unregisteredVersions);
- var template;
- var container = $('serviceworker-list');
+ let template;
+ const container = $('serviceworker-list');
// Existing templates are keyed by partition_id. This allows
// the UI to be updated in-place rather than refreshing the
// whole page.
- for (var i = 0; i < container.childNodes.length; ++i) {
+ for (let i = 0; i < container.childNodes.length; ++i) {
if (container.childNodes[i].partition_id == partition_id) {
template = container.childNodes[i];
}
@@ -163,7 +163,7 @@ cr.define('serviceworker', function() {
template = jstGetTemplate('serviceworker-list-template');
container.appendChild(template);
}
- var fillLogFunc = fillLogForVersion.bind(this, container, partition_id);
+ const fillLogFunc = fillLogForVersion.bind(this, container, partition_id);
stored_registrations.forEach(function(registration) {
[registration.active, registration.waiting].forEach(fillLogFunc);
});
@@ -180,10 +180,10 @@ cr.define('serviceworker', function() {
partition_path: partition_path
}),
template);
- for (var i = 0; i < COMMANDS.length; ++i) {
- var handler = commandHandler(COMMANDS[i]);
- var links = container.querySelectorAll('button.' + COMMANDS[i]);
- for (var j = 0; j < links.length; ++j) {
+ for (let i = 0; i < COMMANDS.length; ++i) {
+ const handler = commandHandler(COMMANDS[i]);
+ const links = container.querySelectorAll('button.' + COMMANDS[i]);
+ for (let j = 0; j < links.length; ++j) {
if (!links[j].hasClickEvent) {
links[j].addEventListener('click', handler, false);
links[j].hasClickEvent = true;
@@ -223,16 +223,16 @@ cr.define('serviceworker', function() {
if (!(partition_id in allLogMessages)) {
allLogMessages[partition_id] = {};
}
- var logMessages = allLogMessages[partition_id];
+ const logMessages = allLogMessages[partition_id];
if (version_id in logMessages) {
logMessages[version_id] += message;
} else {
logMessages[version_id] = message;
}
- var logAreas = document.querySelectorAll('textarea.serviceworker-log');
- for (var i = 0; i < logAreas.length; ++i) {
- var logArea = logAreas[i];
+ const logAreas = document.querySelectorAll('textarea.serviceworker-log');
+ for (let i = 0; i < logAreas.length; ++i) {
+ const logArea = logAreas[i];
if (logArea.partition_id == partition_id &&
logArea.version_id == version_id) {
logArea.value += message;
diff --git a/chromium/content/browser/sandbox_mac_unittest.mm b/chromium/content/browser/sandbox_mac_unittest.mm
index 819b70cc8d5..251c53ac51c 100644
--- a/chromium/content/browser/sandbox_mac_unittest.mm
+++ b/chromium/content/browser/sandbox_mac_unittest.mm
@@ -25,15 +25,7 @@
#include "crypto/openssl_util.h"
#include "sandbox/mac/seatbelt.h"
#include "sandbox/mac/seatbelt_exec.h"
-#include "services/service_manager/sandbox/mac/audio.sb.h"
-#include "services/service_manager/sandbox/mac/cdm.sb.h"
-#include "services/service_manager/sandbox/mac/common.sb.h"
-#include "services/service_manager/sandbox/mac/gpu_v2.sb.h"
-#include "services/service_manager/sandbox/mac/nacl_loader.sb.h"
-#include "services/service_manager/sandbox/mac/pdf_compositor.sb.h"
-#include "services/service_manager/sandbox/mac/ppapi.sb.h"
-#include "services/service_manager/sandbox/mac/renderer.sb.h"
-#include "services/service_manager/sandbox/mac/utility.sb.h"
+#include "services/service_manager/sandbox/mac/sandbox_mac.h"
#include "services/service_manager/sandbox/switches.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
@@ -61,18 +53,15 @@ class SandboxMacTest : public base::MultiProcessTest {
return cl;
}
- std::string ProfileForSandbox(const std::string& sandbox_profile) {
- return std::string(service_manager::kSeatbeltPolicyString_common) +
- sandbox_profile + kTempDirSuffix;
- }
-
void ExecuteWithParams(const std::string& procname,
- const std::string& sub_profile,
- void (*setup)(sandbox::SeatbeltExecClient*)) {
- std::string profile = ProfileForSandbox(sub_profile);
+ service_manager::SandboxType sandbox_type) {
+ std::string profile =
+ service_manager::SandboxMac::GetSandboxProfile(sandbox_type) +
+ kTempDirSuffix;
sandbox::SeatbeltExecClient client;
client.SetProfile(profile);
- setup(&client);
+ SetupSandboxParameters(sandbox_type,
+ *base::CommandLine::ForCurrentProcess(), &client);
pipe_ = client.GetReadFD();
ASSERT_GE(pipe_, 0);
@@ -90,67 +79,21 @@ class SandboxMacTest : public base::MultiProcessTest {
EXPECT_EQ(0, rv);
}
- void ExecuteInAudioSandbox(const std::string& procname) {
- ExecuteWithParams(procname, service_manager::kSeatbeltPolicyString_audio,
- &content::SetupCommonSandboxParameters);
- }
-
- void ExecuteInCDMSandbox(const std::string& procname) {
- ExecuteWithParams(procname, service_manager::kSeatbeltPolicyString_cdm,
- &content::SetupCDMSandboxParameters);
- }
-
- void ExecuteInGPUSandbox(const std::string& procname) {
- ExecuteWithParams(procname, service_manager::kSeatbeltPolicyString_gpu_v2,
- &content::SetupCommonSandboxParameters);
- }
-
- void ExecuteInNaClSandbox(const std::string& procname) {
- ExecuteWithParams(procname,
- service_manager::kSeatbeltPolicyString_nacl_loader,
- &content::SetupCommonSandboxParameters);
- }
-
- void ExecuteInPDFSandbox(const std::string& procname) {
- ExecuteWithParams(procname,
- service_manager::kSeatbeltPolicyString_pdf_compositor,
- &content::SetupCommonSandboxParameters);
- }
-
- void ExecuteInPpapiSandbox(const std::string& procname) {
- ExecuteWithParams(procname, service_manager::kSeatbeltPolicyString_ppapi,
- &content::SetupPPAPISandboxParameters);
- }
-
- void ExecuteInRendererSandbox(const std::string& procname) {
- ExecuteWithParams(procname, service_manager::kSeatbeltPolicyString_renderer,
- &content::SetupCommonSandboxParameters);
- }
-
- void ExecuteInUtilitySandbox(const std::string& procname) {
- ExecuteWithParams(procname, service_manager::kSeatbeltPolicyString_utility,
- [](sandbox::SeatbeltExecClient* client) -> void {
- content::SetupUtilitySandboxParameters(
- client, *base::CommandLine::ForCurrentProcess());
- });
- }
-
void ExecuteInAllSandboxTypes(const std::string& multiprocess_main,
base::RepeatingClosure after_each) {
- using ExecuteFuncT = void (SandboxMacTest::*)(const std::string&);
- constexpr ExecuteFuncT kExecuteFuncs[] = {
- &SandboxMacTest::ExecuteInAudioSandbox,
- &SandboxMacTest::ExecuteInCDMSandbox,
- &SandboxMacTest::ExecuteInGPUSandbox,
- &SandboxMacTest::ExecuteInNaClSandbox,
- &SandboxMacTest::ExecuteInPDFSandbox,
- &SandboxMacTest::ExecuteInPpapiSandbox,
- &SandboxMacTest::ExecuteInRendererSandbox,
- &SandboxMacTest::ExecuteInUtilitySandbox,
+ constexpr service_manager::SandboxType kSandboxTypes[] = {
+ service_manager::SandboxType::SANDBOX_TYPE_AUDIO,
+ service_manager::SandboxType::SANDBOX_TYPE_CDM,
+ service_manager::SandboxType::SANDBOX_TYPE_GPU,
+ service_manager::SandboxType::SANDBOX_TYPE_NACL_LOADER,
+ service_manager::SandboxType::SANDBOX_TYPE_PDF_COMPOSITOR,
+ service_manager::SandboxType::SANDBOX_TYPE_PPAPI,
+ service_manager::SandboxType::SANDBOX_TYPE_RENDERER,
+ service_manager::SandboxType::SANDBOX_TYPE_UTILITY,
};
- for (ExecuteFuncT execute_func : kExecuteFuncs) {
- (this->*execute_func)(multiprocess_main);
+ for (const auto type : kSandboxTypes) {
+ ExecuteWithParams(multiprocess_main, type);
if (!after_each.is_null()) {
after_each.Run();
}
@@ -198,7 +141,8 @@ MULTIPROCESS_TEST_MAIN(RendererWriteProcess) {
}
TEST_F(SandboxMacTest, RendererCannotWriteHomeDir) {
- ExecuteInRendererSandbox("RendererWriteProcess");
+ ExecuteWithParams("RendererWriteProcess",
+ service_manager::SandboxType::SANDBOX_TYPE_RENDERER);
}
MULTIPROCESS_TEST_MAIN(ClipboardAccessProcess) {
@@ -307,7 +251,8 @@ TEST_F(SandboxMacTest, FontLoadingTest) {
font_data_size);
extra_data_ = temp_file_path.value();
- ExecuteInRendererSandbox("FontLoadingProcess");
+ ExecuteWithParams("FontLoadingProcess",
+ service_manager::SandboxType::SANDBOX_TYPE_RENDERER);
temp_file_closer.reset();
ASSERT_TRUE(base::DeleteFile(temp_file_path, false));
}
diff --git a/chromium/content/browser/sandbox_parameters_mac.h b/chromium/content/browser/sandbox_parameters_mac.h
index ac1c8f404ce..555fb9fe21c 100644
--- a/chromium/content/browser/sandbox_parameters_mac.h
+++ b/chromium/content/browser/sandbox_parameters_mac.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_SANDBOX_PARAMETERS_MAC_H_
#include "content/common/content_export.h"
+#include "services/service_manager/sandbox/sandbox_type.h"
namespace base {
class CommandLine;
@@ -17,25 +18,13 @@ class SeatbeltExecClient;
namespace content {
-// All of the below functions populate the |client| with the parameters that the
-// sandbox needs to resolve information that cannot be known at build time, such
-// as the user's home directory.
-CONTENT_EXPORT void SetupCommonSandboxParameters(
+// This populates the sandbox parameters in the client for the given
+// |sandbox_type|. Some parameters may be extracted from the |command_line|.
+CONTENT_EXPORT void SetupSandboxParameters(
+ service_manager::SandboxType sandbox_type,
+ const base::CommandLine& command_line,
sandbox::SeatbeltExecClient* client);
-CONTENT_EXPORT void SetupCDMSandboxParameters(
- sandbox::SeatbeltExecClient* client);
-
-CONTENT_EXPORT void SetupNetworkSandboxParameters(
- sandbox::SeatbeltExecClient* client);
-
-CONTENT_EXPORT void SetupPPAPISandboxParameters(
- sandbox::SeatbeltExecClient* client);
-
-CONTENT_EXPORT void SetupUtilitySandboxParameters(
- sandbox::SeatbeltExecClient* client,
- const base::CommandLine& command_line);
-
} // namespace content
#endif // CONTENT_BROWSER_SANDBOX_PARAMETERS_MAC_H_
diff --git a/chromium/content/browser/sandbox_parameters_mac.mm b/chromium/content/browser/sandbox_parameters_mac.mm
index c115a1c4084..b4d539bab49 100644
--- a/chromium/content/browser/sandbox_parameters_mac.mm
+++ b/chromium/content/browser/sandbox_parameters_mac.mm
@@ -24,6 +24,7 @@
#include "content/public/common/pepper_plugin_info.h"
#include "sandbox/mac/seatbelt_exec.h"
#include "services/service_manager/sandbox/mac/sandbox_mac.h"
+#include "services/service_manager/sandbox/sandbox_type.h"
#include "services/service_manager/sandbox/switches.h"
namespace content {
@@ -45,8 +46,9 @@ std::string GetOSVersion() {
return std::to_string(final_os_version);
}
-} // namespace
-
+// All of the below functions populate the |client| with the parameters that the
+// sandbox needs to resolve information that cannot be known at build time, such
+// as the user's home directory.
void SetupCommonSandboxParameters(sandbox::SeatbeltExecClient* client) {
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
@@ -165,4 +167,35 @@ void SetupUtilitySandboxParameters(sandbox::SeatbeltExecClient* client,
SetupCommonSandboxParameters(client);
}
+} // namespace
+
+void SetupSandboxParameters(service_manager::SandboxType sandbox_type,
+ const base::CommandLine& command_line,
+ sandbox::SeatbeltExecClient* client) {
+ switch (sandbox_type) {
+ case service_manager::SANDBOX_TYPE_AUDIO:
+ case service_manager::SANDBOX_TYPE_GPU:
+ case service_manager::SANDBOX_TYPE_NACL_LOADER:
+ case service_manager::SANDBOX_TYPE_PDF_COMPOSITOR:
+ case service_manager::SANDBOX_TYPE_RENDERER:
+ SetupCommonSandboxParameters(client);
+ break;
+ case service_manager::SANDBOX_TYPE_CDM:
+ SetupCDMSandboxParameters(client);
+ break;
+ case service_manager::SANDBOX_TYPE_NETWORK:
+ SetupNetworkSandboxParameters(client);
+ break;
+ case service_manager::SANDBOX_TYPE_PPAPI:
+ SetupPPAPISandboxParameters(client);
+ break;
+ case service_manager::SANDBOX_TYPE_PROFILING:
+ case service_manager::SANDBOX_TYPE_UTILITY:
+ SetupUtilitySandboxParameters(client, command_line);
+ break;
+ default:
+ CHECK(false) << "Unhandled parameters for sandbox_type " << sandbox_type;
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/scheduler/browser_io_task_environment.cc b/chromium/content/browser/scheduler/browser_io_task_environment.cc
new file mode 100644
index 00000000000..ef8542d1509
--- /dev/null
+++ b/chromium/content/browser/scheduler/browser_io_task_environment.cc
@@ -0,0 +1,57 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/scheduler/browser_io_task_environment.h"
+
+#include "base/task/sequence_manager/sequence_manager.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+using ::base::sequence_manager::CreateUnboundSequenceManager;
+using ::base::sequence_manager::SequenceManager;
+using ::base::sequence_manager::TaskQueue;
+
+BrowserIOTaskEnvironment::BrowserIOTaskEnvironment()
+ : sequence_manager_(CreateUnboundSequenceManager(
+ SequenceManager::Settings::Builder()
+ .SetMessagePumpType(base::MessageLoop::TYPE_IO)
+ .Build())) {
+ Init(sequence_manager_.get());
+}
+
+BrowserIOTaskEnvironment::BrowserIOTaskEnvironment(
+ SequenceManager* sequence_manager)
+ : sequence_manager_(nullptr) {
+ Init(sequence_manager);
+}
+
+void BrowserIOTaskEnvironment::Init(
+ base::sequence_manager::SequenceManager* sequence_manager) {
+ task_queues_ = std::make_unique<BrowserTaskQueues>(
+ BrowserThread::IO, sequence_manager,
+ sequence_manager->GetRealTimeDomain());
+ default_task_queue_ = sequence_manager->CreateTaskQueue(
+ TaskQueue::Spec("browser_io_task_environment_default_tq"));
+ default_task_runner_ = default_task_queue_->task_runner();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+BrowserIOTaskEnvironment::GetDefaultTaskRunner() {
+ return default_task_runner_;
+}
+
+BrowserIOTaskEnvironment::~BrowserIOTaskEnvironment() = default;
+
+void BrowserIOTaskEnvironment::BindToCurrentThread(
+ base::TimerSlack timer_slack) {
+ DCHECK(sequence_manager_);
+ sequence_manager_->BindToMessagePump(
+ base::MessagePump::Create(base::MessagePump::Type::IO));
+ sequence_manager_->SetTimerSlack(timer_slack);
+ sequence_manager_->SetDefaultTaskRunner(GetDefaultTaskRunner());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/scheduler/browser_io_task_environment.h b/chromium/content/browser/scheduler/browser_io_task_environment.h
new file mode 100644
index 00000000000..92251960196
--- /dev/null
+++ b/chromium/content/browser/scheduler/browser_io_task_environment.h
@@ -0,0 +1,73 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SCHEDULER_BROWSER_IO_TASK_ENVIRONMENT_H_
+#define CONTENT_BROWSER_SCHEDULER_BROWSER_IO_TASK_ENVIRONMENT_H_
+
+#include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "base/threading/thread.h"
+#include "content/browser/scheduler/browser_task_queues.h"
+#include "content/common/content_export.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+
+namespace sequence_manager {
+class SequenceManager;
+} // namespace sequence_manager
+
+} // namespace base
+
+namespace content {
+
+// TaskEnvironment for the IO thread.
+class CONTENT_EXPORT BrowserIOTaskEnvironment
+ : public base::Thread::TaskEnvironment {
+ public:
+ using Handle = BrowserTaskQueues::Handle;
+
+ static std::unique_ptr<BrowserIOTaskEnvironment> CreateForTesting(
+ base::sequence_manager::SequenceManager* sequence_manager) {
+ return base::WrapUnique(new BrowserIOTaskEnvironment(sequence_manager));
+ }
+
+ BrowserIOTaskEnvironment();
+ ~BrowserIOTaskEnvironment() override;
+
+ scoped_refptr<base::SingleThreadTaskRunner> GetDefaultTaskRunner() override;
+ void BindToCurrentThread(base::TimerSlack timer_slack) override;
+
+ bool allow_blocking_for_testing() const {
+ return allow_blocking_for_testing_;
+ }
+
+ // Call this before handing this over to a base::Thread to allow blocking in
+ // tests.
+ void SetAllowBlockingForTesting() { allow_blocking_for_testing_ = true; }
+
+ Handle CreateHandle() { return task_queues_->CreateHandle(); }
+
+ private:
+ explicit BrowserIOTaskEnvironment(
+ base::sequence_manager::SequenceManager* sequence_manager);
+
+ // Performs the actual initialization of all the members that require a
+ // SequenceManager. Just a convenience method to avoid code duplication as in
+ // testing |sequence_manager_| will be null;
+ void Init(base::sequence_manager::SequenceManager* sequence_manager);
+
+ bool allow_blocking_for_testing_ = false;
+ // Owned SequenceManager, null if instance created via CreateForTesting.
+ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager_;
+
+ std::unique_ptr<BrowserTaskQueues> task_queues_;
+ scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_;
+ scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCHEDULER_BROWSER_IO_TASK_ENVIRONMENT_H_
diff --git a/chromium/content/browser/scheduler/browser_io_task_environment_unittest.cc b/chromium/content/browser/scheduler/browser_io_task_environment_unittest.cc
new file mode 100644
index 00000000000..106a7c08fb0
--- /dev/null
+++ b/chromium/content/browser/scheduler/browser_io_task_environment_unittest.cc
@@ -0,0 +1,56 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/scheduler/browser_io_task_environment.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "content/browser/scheduler/browser_task_queues.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+TEST(BrowserIOTaskEnvironmentTest, CanPostTasksToThread) {
+ base::Thread thread("my_thread");
+
+ auto env = std::make_unique<BrowserIOTaskEnvironment>();
+ auto handle = env->CreateHandle();
+ handle.EnableAllQueues();
+
+ base::Thread::Options options;
+ options.task_environment = env.release();
+ thread.StartWithOptions(options);
+
+ auto runner =
+ handle.GetBrowserTaskRunner(BrowserTaskQueues::QueueType::kDefault);
+
+ base::WaitableEvent event;
+ runner->PostTask(FROM_HERE, base::BindOnce(&base::WaitableEvent::Signal,
+ base::Unretained(&event)));
+ event.Wait();
+}
+
+TEST(BrowserIOTaskEnvironmentTest, DefaultTaskRunnerIsAllwaysActive) {
+ base::Thread thread("my_thread");
+
+ auto env = std::make_unique<BrowserIOTaskEnvironment>();
+ auto task_runner = env->GetDefaultTaskRunner();
+
+ base::Thread::Options options;
+ options.task_environment = env.release();
+ thread.StartWithOptions(options);
+
+ base::WaitableEvent event;
+ task_runner->PostTask(FROM_HERE, base::BindOnce(&base::WaitableEvent::Signal,
+ base::Unretained(&event)));
+ event.Wait();
+}
+
+} // namespace
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/scheduler/browser_task_executor.cc b/chromium/content/browser/scheduler/browser_task_executor.cc
index 81131371f5a..d8739b1f311 100644
--- a/chromium/content/browser/scheduler/browser_task_executor.cc
+++ b/chromium/content/browser/scheduler/browser_task_executor.cc
@@ -11,10 +11,10 @@
#include "base/no_destructor.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
+#include "content/browser/browser_process_sub_thread.h"
#include "content/browser/browser_thread_impl.h"
-#include "content/browser/scheduler/browser_ui_thread_scheduler.h"
#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
#if defined(OS_ANDROID)
#include "base/android/task_scheduler/post_task_android.h"
@@ -23,174 +23,112 @@
namespace content {
namespace {
-using QueueType = content::BrowserUIThreadTaskQueue::QueueType;
+using QueueType = ::content::BrowserTaskQueues::QueueType;
// |g_browser_task_executor| is intentionally leaked on shutdown.
BrowserTaskExecutor* g_browser_task_executor = nullptr;
-// An implementation of SingleThreadTaskRunner to be used in conjunction with
-// BrowserThread. BrowserThreadTaskRunners are vended by
-// base::Create*TaskRunnerWithTraits({BrowserThread::UI/IO}).
-//
-// TODO(gab): Consider replacing this with direct calls to task runners obtained
-// via |BrowserThreadImpl::GetTaskRunnerForThread()| -- only works if none are
-// requested before starting the threads.
-class BrowserThreadTaskRunner : public base::SingleThreadTaskRunner {
- public:
- explicit BrowserThreadTaskRunner(BrowserThread::ID identifier)
- : id_(identifier) {}
-
- // SingleThreadTaskRunner implementation.
- bool PostDelayedTask(const base::Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay) override {
- return BrowserThreadImpl::GetTaskRunnerForThread(id_)->PostDelayedTask(
- from_here, std::move(task), delay);
- }
-
- bool PostNonNestableDelayedTask(const base::Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay) override {
- return BrowserThreadImpl::GetTaskRunnerForThread(id_)
- ->PostNonNestableDelayedTask(from_here, std::move(task), delay);
- }
-
- bool RunsTasksInCurrentSequence() const override {
- return BrowserThread::CurrentlyOn(id_);
- }
-
- private:
- ~BrowserThreadTaskRunner() override {}
-
- const BrowserThread::ID id_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserThreadTaskRunner);
-};
+QueueType GetQueueType(const base::TaskTraits& traits,
+ BrowserTaskType task_type) {
+ switch (task_type) {
+ case BrowserTaskType::kBootstrap:
+ // Note we currently ignore the priority for bootstrap tasks.
+ return QueueType::kBootstrap;
-// TODO(eseckler): This should be replaced by the BrowserUIThreadScheduler.
-class AfterStartupTaskRunner : public base::SingleThreadTaskRunner {
- public:
- explicit AfterStartupTaskRunner(
- scoped_refptr<base::SingleThreadTaskRunner> proxied_task_runner)
- : proxied_task_runner_(proxied_task_runner) {
- Reset();
- }
+ case BrowserTaskType::kNavigation:
+ case BrowserTaskType::kPreconnect:
+ // Note we currently ignore the priority for navigation and preconnection
+ // tasks.
+ return QueueType::kNavigationAndPreconnection;
- void Reset() {
- listening_for_startup_ = false;
- deferred_task_runner_ =
- base::MakeRefCounted<base::DeferredSequencedTaskRunner>(
- proxied_task_runner_);
- }
+ case BrowserTaskType::kDefault:
+ // Defer to traits.priority() below.
+ break;
- // SingleThreadTaskRunner implementation.
- bool PostDelayedTask(const base::Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay) override {
- EnsureListeningForStartup();
- return deferred_task_runner_->PostDelayedTask(from_here, std::move(task),
- delay);
+ case BrowserTaskType::kBrowserTaskType_Last:
+ NOTREACHED();
}
- bool PostNonNestableDelayedTask(const base::Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay) override {
- EnsureListeningForStartup();
- return deferred_task_runner_->PostNonNestableDelayedTask(
- from_here, std::move(task), delay);
- }
+ switch (traits.priority()) {
+ case base::TaskPriority::BEST_EFFORT:
+ return QueueType::kBestEffort;
- bool RunsTasksInCurrentSequence() const override {
- return deferred_task_runner_->RunsTasksInCurrentSequence();
- }
+ case base::TaskPriority::USER_VISIBLE:
+ return QueueType::kDefault;
- void EnsureListeningForStartup() {
- if (!listening_for_startup_.exchange(true)) {
- BrowserThread::PostAfterStartupTask(
- FROM_HERE, proxied_task_runner_,
- base::BindOnce(&AfterStartupTaskRunner::Start,
- base::Unretained(this)));
- }
+ case base::TaskPriority::USER_BLOCKING:
+ return QueueType::kUserBlocking;
}
-
- private:
- ~AfterStartupTaskRunner() override {}
-
- void Start() { deferred_task_runner_->Start(); }
-
- std::atomic_bool listening_for_startup_;
- scoped_refptr<SingleThreadTaskRunner> proxied_task_runner_;
- scoped_refptr<base::DeferredSequencedTaskRunner> deferred_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(AfterStartupTaskRunner);
-};
-
-scoped_refptr<BrowserThreadTaskRunner> GetProxyTaskRunnerForThreadImpl(
- BrowserThread::ID id) {
- using TaskRunnerMap = std::array<scoped_refptr<BrowserThreadTaskRunner>,
- BrowserThread::ID_COUNT>;
- static const base::NoDestructor<TaskRunnerMap> task_runners([] {
- TaskRunnerMap task_runners;
- for (int i = 0; i < BrowserThread::ID_COUNT; ++i)
- task_runners[i] = base::MakeRefCounted<BrowserThreadTaskRunner>(
- static_cast<BrowserThread::ID>(i));
- return task_runners;
- }());
- return (*task_runners)[id];
-}
-
-scoped_refptr<AfterStartupTaskRunner> GetAfterStartupTaskRunnerForThreadImpl(
- BrowserThread::ID id) {
- using TaskRunnerMap = std::array<scoped_refptr<AfterStartupTaskRunner>,
- BrowserThread::ID_COUNT>;
- static const base::NoDestructor<TaskRunnerMap> task_runners([] {
- TaskRunnerMap task_runners;
- for (int i = 0; i < BrowserThread::ID_COUNT; ++i)
- task_runners[i] = base::MakeRefCounted<AfterStartupTaskRunner>(
- GetProxyTaskRunnerForThreadImpl(static_cast<BrowserThread::ID>(i)));
- return task_runners;
- }());
- return (*task_runners)[id];
}
} // namespace
BrowserTaskExecutor::BrowserTaskExecutor(
- std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler)
- : browser_ui_thread_scheduler_(std::move(browser_ui_thread_scheduler)) {}
+ std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler,
+ std::unique_ptr<BrowserIOTaskEnvironment> browser_io_task_environment)
+ : browser_ui_thread_scheduler_(std::move(browser_ui_thread_scheduler)),
+ browser_ui_thread_handle_(browser_ui_thread_scheduler_->GetHandle()),
+ browser_io_task_environment_(std::move(browser_io_task_environment)),
+ browser_io_thread_handle_(browser_io_task_environment_->CreateHandle()) {}
BrowserTaskExecutor::~BrowserTaskExecutor() = default;
// static
void BrowserTaskExecutor::Create() {
- DCHECK(!g_browser_task_executor);
DCHECK(!base::ThreadTaskRunnerHandle::IsSet());
+ CreateInternal(std::make_unique<BrowserUIThreadScheduler>(),
+ std::make_unique<BrowserIOTaskEnvironment>());
+}
+
+// static
+void BrowserTaskExecutor::CreateForTesting(
+ std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler,
+ std::unique_ptr<BrowserIOTaskEnvironment> browser_io_task_environment) {
+ CreateInternal(std::move(browser_ui_thread_scheduler),
+ std::move(browser_io_task_environment));
+}
+
+// static
+void BrowserTaskExecutor::CreateInternal(
+ std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler,
+ std::unique_ptr<BrowserIOTaskEnvironment> browser_io_task_environment) {
+ DCHECK(!g_browser_task_executor);
g_browser_task_executor =
- new BrowserTaskExecutor(std::make_unique<BrowserUIThreadScheduler>());
+ new BrowserTaskExecutor(std::move(browser_ui_thread_scheduler),
+ std::move(browser_io_task_environment));
base::RegisterTaskExecutor(BrowserTaskTraitsExtension::kExtensionId,
g_browser_task_executor);
+ g_browser_task_executor->browser_ui_thread_handle_
+ .EnableAllExceptBestEffortQueues();
+
#if defined(OS_ANDROID)
base::PostTaskAndroid::SignalNativeSchedulerReady();
#endif
}
// static
-void BrowserTaskExecutor::CreateWithBrowserUIThreadSchedulerForTesting(
- std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler) {
- DCHECK(!g_browser_task_executor);
- g_browser_task_executor =
- new BrowserTaskExecutor(std::move(browser_ui_thread_scheduler));
- base::RegisterTaskExecutor(BrowserTaskTraitsExtension::kExtensionId,
- g_browser_task_executor);
+void BrowserTaskExecutor::ResetForTesting() {
#if defined(OS_ANDROID)
- base::PostTaskAndroid::SignalNativeSchedulerReady();
+ base::PostTaskAndroid::SignalNativeSchedulerShutdown();
#endif
+
+ if (g_browser_task_executor) {
+ base::UnregisterTaskExecutorForTesting(
+ BrowserTaskTraitsExtension::kExtensionId);
+ delete g_browser_task_executor;
+ g_browser_task_executor = nullptr;
+ }
}
// static
void BrowserTaskExecutor::PostFeatureListSetup() {
DCHECK(g_browser_task_executor);
- g_browser_task_executor->browser_ui_thread_scheduler_->PostFeatureListSetup();
+ DCHECK(g_browser_task_executor->browser_ui_thread_scheduler_);
+ DCHECK(g_browser_task_executor->browser_io_task_environment_);
+ g_browser_task_executor->browser_ui_thread_handle_
+ .PostFeatureListInitializationSetup();
+ g_browser_task_executor->browser_io_thread_handle_
+ .PostFeatureListInitializationSetup();
}
// static
@@ -199,62 +137,39 @@ void BrowserTaskExecutor::Shutdown() {
return;
DCHECK(g_browser_task_executor->browser_ui_thread_scheduler_);
- // We don't delete either |g_browser_task_executor| or the
- // BrowserUIThreadScheduler it owns because other threads may PostTask or call
- // BrowserTaskExecutor::GetTaskRunner while we're tearing things down. We
- // don't want to add locks so we just leak instead of dealing with that.
- // For similar reasons we don't need to call
+ // We don't delete |g_browser_task_executor| because other threads may
+ // PostTask or call BrowserTaskExecutor::GetTaskRunner while we're tearing
+ // things down. We don't want to add locks so we just leak instead of dealing
+ // with that. For similar reasons we don't need to call
// PostTaskAndroid::SignalNativeSchedulerShutdown on Android. In tests however
// we need to clean up, so BrowserTaskExecutor::ResetForTesting should be
// called.
- g_browser_task_executor->browser_ui_thread_scheduler_->Shutdown();
-}
-
-// static
-void BrowserTaskExecutor::ResetForTesting() {
-#if defined(OS_ANDROID)
- base::PostTaskAndroid::SignalNativeSchedulerShutdown();
-#endif
-
- for (int i = 0; i < BrowserThread::ID_COUNT; ++i) {
- GetAfterStartupTaskRunnerForThreadImpl(static_cast<BrowserThread::ID>(i))
- ->Reset();
- }
- if (g_browser_task_executor) {
- base::UnregisterTaskExecutorForTesting(
- BrowserTaskTraitsExtension::kExtensionId);
- delete g_browser_task_executor;
- g_browser_task_executor = nullptr;
- }
+ g_browser_task_executor->browser_ui_thread_scheduler_.reset();
+ g_browser_task_executor->browser_io_task_environment_.reset();
}
// static
void BrowserTaskExecutor::RunAllPendingTasksOnThreadForTesting(
BrowserThread::ID identifier) {
DCHECK(g_browser_task_executor);
- DCHECK(g_browser_task_executor->browser_ui_thread_scheduler_);
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
switch (identifier) {
case BrowserThread::UI:
- g_browser_task_executor->browser_ui_thread_scheduler_
- ->RunAllPendingTasksForTesting();
+ g_browser_task_executor->browser_ui_thread_handle_
+ .ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
break;
-
case BrowserThread::IO: {
- // TODO(https://crbug/863341): Do something more clever once we have a
- // scheduler
- base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
- base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
- run_loop.QuitClosure());
- run_loop.Run();
+ g_browser_task_executor->browser_io_thread_handle_
+ .ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
break;
}
-
case BrowserThread::ID_COUNT:
NOTREACHED();
- break;
}
+
+ run_loop.Run();
}
bool BrowserTaskExecutor::PostDelayedTaskWithTraits(
@@ -266,11 +181,11 @@ bool BrowserTaskExecutor::PostDelayedTaskWithTraits(
const BrowserTaskTraitsExtension& extension =
traits.GetExtension<BrowserTaskTraitsExtension>();
if (extension.nestable()) {
- return GetTaskRunner(traits, extension)
- ->PostDelayedTask(from_here, std::move(task), delay);
+ return GetTaskRunner(traits)->PostDelayedTask(from_here, std::move(task),
+ delay);
} else {
- return GetTaskRunner(traits, extension)
- ->PostNonNestableDelayedTask(from_here, std::move(task), delay);
+ return GetTaskRunner(traits)->PostNonNestableDelayedTask(
+ from_here, std::move(task), delay);
}
}
@@ -302,80 +217,77 @@ BrowserTaskExecutor::CreateCOMSTATaskRunnerWithTraits(
#endif // defined(OS_WIN)
scoped_refptr<base::SingleThreadTaskRunner> BrowserTaskExecutor::GetTaskRunner(
- const base::TaskTraits& traits) {
+ const base::TaskTraits& traits) const {
+ auto id_and_queue = GetThreadIdAndQueueType(traits);
+
+ switch (id_and_queue.thread_id) {
+ case BrowserThread::UI: {
+ return browser_ui_thread_handle_.GetBrowserTaskRunner(
+ id_and_queue.queue_type);
+ }
+ case BrowserThread::IO:
+ return browser_io_thread_handle_.GetBrowserTaskRunner(
+ id_and_queue.queue_type);
+ case BrowserThread::ID_COUNT:
+ NOTREACHED();
+ }
+ return nullptr;
+}
+
+// static
+BrowserTaskExecutor::ThreadIdAndQueueType
+BrowserTaskExecutor::GetThreadIdAndQueueType(const base::TaskTraits& traits) {
DCHECK_EQ(BrowserTaskTraitsExtension::kExtensionId, traits.extension_id());
- const BrowserTaskTraitsExtension& extension =
+ BrowserTaskTraitsExtension extension =
traits.GetExtension<BrowserTaskTraitsExtension>();
- return GetTaskRunner(traits, extension);
-}
-scoped_refptr<base::SingleThreadTaskRunner> BrowserTaskExecutor::GetTaskRunner(
- const base::TaskTraits& traits,
- const BrowserTaskTraitsExtension& extension) {
BrowserThread::ID thread_id = extension.browser_thread();
DCHECK_GE(thread_id, 0);
- DCHECK_LT(thread_id, BrowserThread::ID_COUNT);
- if (thread_id != BrowserThread::UI) {
- // TODO(scheduler-dev): Consider adding a simple (static priority based)
- // scheduler to the IO thread and getting rid of AfterStartupTaskRunner.
- if (traits.priority() == base::TaskPriority::BEST_EFFORT)
- return GetAfterStartupTaskRunnerForThread(thread_id);
- return GetProxyTaskRunnerForThread(thread_id);
- }
BrowserTaskType task_type = extension.task_type();
DCHECK_LT(task_type, BrowserTaskType::kBrowserTaskType_Last);
- switch (task_type) {
- case BrowserTaskType::kBootstrap:
- // Note we currently ignore the priority for bootstrap tasks.
- return browser_ui_thread_scheduler_->GetTaskRunner(QueueType::kBootstrap);
-
- case BrowserTaskType::kNavigation:
- case BrowserTaskType::kPreconnect:
- // Note we currently ignore the priority for navigation and preconnection
- // tasks.
- return browser_ui_thread_scheduler_->GetTaskRunner(
- QueueType::kNavigationAndPreconnection);
-
- case BrowserTaskType::kDefault:
- // Defer to traits.priority() below.
- break;
-
- case BrowserTaskType::kBrowserTaskType_Last:
- NOTREACHED();
- }
-
- switch (traits.priority()) {
- case base::TaskPriority::BEST_EFFORT:
- return browser_ui_thread_scheduler_->GetTaskRunner(
- QueueType::kBestEffort);
-
- case base::TaskPriority::USER_VISIBLE:
- return browser_ui_thread_scheduler_->GetTaskRunner(QueueType::kDefault);
- case base::TaskPriority::USER_BLOCKING:
- return browser_ui_thread_scheduler_->GetTaskRunner(
- QueueType::kUserBlocking);
- }
+ return {thread_id, GetQueueType(traits, task_type)};
}
// static
-scoped_refptr<base::SingleThreadTaskRunner>
-BrowserTaskExecutor::GetProxyTaskRunnerForThread(BrowserThread::ID id) {
- return GetProxyTaskRunnerForThreadImpl(id);
+void BrowserTaskExecutor::EnableAllQueues() {
+ DCHECK(g_browser_task_executor);
+ g_browser_task_executor->browser_ui_thread_handle_.EnableAllQueues();
+ g_browser_task_executor->browser_io_thread_handle_.EnableAllQueues();
}
// static
-scoped_refptr<base::SingleThreadTaskRunner>
-BrowserTaskExecutor::GetAfterStartupTaskRunnerForThread(BrowserThread::ID id) {
- return GetAfterStartupTaskRunnerForThreadImpl(id);
+void BrowserTaskExecutor::InitializeIOThread() {
+ DCHECK(g_browser_task_executor);
+ g_browser_task_executor->browser_io_thread_handle_
+ .EnableAllExceptBestEffortQueues();
}
-// static
-void BrowserTaskExecutor::NotifyBrowserStartupCompleted() {
+std::unique_ptr<BrowserProcessSubThread> BrowserTaskExecutor::CreateIOThread() {
DCHECK(g_browser_task_executor);
- g_browser_task_executor->browser_ui_thread_scheduler_
- ->EnableBestEffortQueues();
+ DCHECK(g_browser_task_executor->browser_io_task_environment_);
+ TRACE_EVENT0("startup", "BrowserTaskExecutor::CreateIOThread");
+
+ auto io_thread = std::make_unique<BrowserProcessSubThread>(BrowserThread::IO);
+
+ if (g_browser_task_executor->browser_io_task_environment_
+ ->allow_blocking_for_testing()) {
+ io_thread->AllowBlockingForTesting();
+ }
+
+ base::Thread::Options options;
+ options.message_loop_type = base::MessageLoop::TYPE_IO;
+ options.task_environment =
+ g_browser_task_executor->browser_io_task_environment_.release();
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(USE_OZONE)
+ // Up the priority of the |io_thread_| as some of its IPCs relate to
+ // display tasks.
+ options.priority = base::ThreadPriority::DISPLAY;
+#endif
+ if (!io_thread->StartWithOptions(options))
+ LOG(FATAL) << "Failed to start BrowserThread:IO";
+ return io_thread;
}
} // namespace content
diff --git a/chromium/content/browser/scheduler/browser_task_executor.h b/chromium/content/browser/scheduler/browser_task_executor.h
index 65a084e6b00..8e102006689 100644
--- a/chromium/content/browser/scheduler/browser_task_executor.h
+++ b/chromium/content/browser/scheduler/browser_task_executor.h
@@ -11,6 +11,8 @@
#include "base/memory/scoped_refptr.h"
#include "base/task/task_executor.h"
#include "build/build_config.h"
+#include "content/browser/scheduler/browser_io_task_environment.h"
+#include "content/browser/scheduler/browser_ui_thread_scheduler.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -18,7 +20,7 @@
namespace content {
class BrowserTaskExecutorTest;
-class BrowserUIThreadScheduler;
+class BrowserProcessSubThread;
// This class's job is to map base::TaskTraits to actual task queues for the
// browser process.
@@ -27,11 +29,53 @@ class CONTENT_EXPORT BrowserTaskExecutor : public base::TaskExecutor {
// Creates and registers a BrowserTaskExecutor on the current thread which
// owns a BrowserUIThreadScheduler. This facilitates posting tasks to a
// BrowserThread via //base/task/post_task.h.
+ // All BrowserThread::UI task queues except best effort ones are also enabled.
+ // TODO(carlscab): These queues should be enabled in
+ // BrowserMainLoop::InitializeMainThread() but some Android tests fail if we
+ // do so.
static void Create();
- // As Create but with the user provided |browser_ui_thread_scheduler|.
- static void CreateWithBrowserUIThreadSchedulerForTesting(
- std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler);
+ // Creates the IO thread using the scheduling infrastructure set up in the
+ // Create() method. That means that clients have access to TaskRunners
+ // associated with the IO thread before that thread is even created. In order
+ // to do so this class will own the TaskEnvironment for the IO thread until
+ // the thread is created, at which point ownership will be transferred and the
+ // |BrowserTaskExecutor| will only communicate with it via TaskRunner
+ // instances.
+ //
+ // Browser task queues will initially be disabled, that is tasks posted to
+ // them will not run. But the default task runner of the thread (the one you
+ // get via ThreadTaskRunnerHandle::Get()) will be active. This is the same
+ // task runner you get by calling BrowserProcessSubThread::task_runner(). The
+ // queues can be initialized by calling InitializeIOThread which is done
+ // during Chromium starup in BrowserMainLoop::CreateThreads.
+ //
+ // Early on during Chromium startup we initialize the ServiceManager and it
+ // needs to run tasks immediately. The ServiceManager itself does not know
+ // about the IO thread (it does not use the browser task traits), it only uses
+ // the task runner provided to it during initialization and possibly
+ // ThreadTaskRunnerHandle::Get() from tasks it posts. But we currently run it
+ // on the IO thread so we need the default task runner to be active for its
+ // tasks to run. Note that since tasks posted via the browser task traits will
+ // not run they won't be able to access the default task runner either, so for
+ // those tasks the default task queue is also "disabled".
+ //
+ // Attention: This method can only be called once (as there must be only one
+ // IO thread).
+ static std::unique_ptr<BrowserProcessSubThread> CreateIOThread();
+
+ // Enables non best effort queues on the IO thread. Usually called from
+ // BrowserMainLoop::CreateThreads.
+ static void InitializeIOThread();
+
+ // Enables all queues on all threads.
+ // Can be called multiple times.
+ static void EnableAllQueues();
+
+ // As Create but with the user provided objects.
+ static void CreateForTesting(
+ std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler,
+ std::unique_ptr<BrowserIOTaskEnvironment> browser_io_task_environment);
// This must be called after the FeatureList has been initialized in order
// for scheduling experiments to function.
@@ -42,8 +86,6 @@ class CONTENT_EXPORT BrowserTaskExecutor : public base::TaskExecutor {
// called.
static void Shutdown();
- static void NotifyBrowserStartupCompleted();
-
// Unregister and delete the TaskExecutor after a test.
static void ResetForTesting();
@@ -55,11 +97,17 @@ class CONTENT_EXPORT BrowserTaskExecutor : public base::TaskExecutor {
// If any of the pending tasks posted a task, these could be run by calling
// this method again or running a regular RunLoop. But if that were the case
// you should probably rewrite you tests to wait for a specific event instead.
- //
- // NOTE: Can only be called from the UI thread.
static void RunAllPendingTasksOnThreadForTesting(
BrowserThread::ID identifier);
+ struct ThreadIdAndQueueType {
+ BrowserThread::ID thread_id;
+ BrowserTaskQueues::QueueType queue_type;
+ };
+
+ static ThreadIdAndQueueType GetThreadIdAndQueueType(
+ const base::TaskTraits& traits);
+
// base::TaskExecutor implementation.
bool PostDelayedTaskWithTraits(const base::Location& from_here,
const base::TaskTraits& traits,
@@ -86,6 +134,10 @@ class CONTENT_EXPORT BrowserTaskExecutor : public base::TaskExecutor {
private:
friend class BrowserTaskExecutorTest;
+ static void CreateInternal(
+ std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler,
+ std::unique_ptr<BrowserIOTaskEnvironment> browser_io_task_environment);
+
// For GetProxyTaskRunnerForThread().
FRIEND_TEST_ALL_PREFIXES(BrowserTaskExecutorTest,
EnsureUIThreadTraitPointsToExpectedQueue);
@@ -95,23 +147,18 @@ class CONTENT_EXPORT BrowserTaskExecutor : public base::TaskExecutor {
BestEffortTasksRunAfterStartup);
explicit BrowserTaskExecutor(
- std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler);
+ std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler,
+ std::unique_ptr<BrowserIOTaskEnvironment> browser_io_task_environment);
~BrowserTaskExecutor() override;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
- const base::TaskTraits& traits);
-
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
- const base::TaskTraits& traits,
- const BrowserTaskTraitsExtension& extension);
-
- static scoped_refptr<base::SingleThreadTaskRunner>
- GetProxyTaskRunnerForThread(BrowserThread::ID id);
-
- static scoped_refptr<base::SingleThreadTaskRunner>
- GetAfterStartupTaskRunnerForThread(BrowserThread::ID id);
+ const base::TaskTraits& traits) const;
std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler_;
+ BrowserUIThreadScheduler::Handle browser_ui_thread_handle_;
+
+ std::unique_ptr<BrowserIOTaskEnvironment> browser_io_task_environment_;
+ BrowserIOTaskEnvironment::Handle browser_io_thread_handle_;
DISALLOW_COPY_AND_ASSIGN(BrowserTaskExecutor);
};
diff --git a/chromium/content/browser/scheduler/browser_task_executor_unittest.cc b/chromium/content/browser/scheduler/browser_task_executor_unittest.cc
index 995755cd059..b18159bc342 100644
--- a/chromium/content/browser/scheduler/browser_task_executor_unittest.cc
+++ b/chromium/content/browser/scheduler/browser_task_executor_unittest.cc
@@ -4,89 +4,50 @@
#include "content/browser/scheduler/browser_task_executor.h"
+#include <map>
+#include <memory>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
#include "base/task/thread_pool/thread_pool.h"
+#include "base/test/bind_test_util.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/scheduler/browser_io_task_environment.h"
+#include "content/browser/scheduler/browser_task_queues.h"
#include "content/browser/scheduler/browser_ui_thread_scheduler.h"
#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
-#include "content/test/test_content_browser_client.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
+using ::base::TaskPriority;
using ::testing::Invoke;
using ::testing::Mock;
+using ::testing::SizeIs;
-class BrowserTaskExecutorTest : public testing::Test {
- public:
- BrowserTaskExecutorTest() {
- old_browser_client_ = SetBrowserClientForTesting(&browser_client_);
- }
-
- ~BrowserTaskExecutorTest() override {
- SetBrowserClientForTesting(old_browser_client_);
- }
-
- protected:
- class AfterStartupBrowserClient : public TestContentBrowserClient {
- public:
- void PostAfterStartupTask(
- const base::Location& from_here,
- const scoped_refptr<base::TaskRunner>& task_runner,
- base::OnceClosure task) override {
- // The tests only post from UI thread.
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- tasks_.emplace_back(TaskEntry{from_here, task_runner, std::move(task)});
- }
-
- void RunTasks() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- for (TaskEntry& task : tasks_) {
- task.task_runner->PostTask(task.from_here, std::move(task.task));
- }
- tasks_.clear();
- }
-
- struct TaskEntry {
- base::Location from_here;
- scoped_refptr<base::TaskRunner> task_runner;
- base::OnceClosure task;
- };
- std::vector<TaskEntry> tasks_;
- };
+using QueueType = BrowserTaskQueues::QueueType;
+class BrowserTaskExecutorTest : public testing::Test {
+ private:
TestBrowserThreadBundle thread_bundle_{
base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME};
- AfterStartupBrowserClient browser_client_;
- ContentBrowserClient* old_browser_client_;
};
-TEST_F(BrowserTaskExecutorTest, EnsureUIThreadTraitPointsToExpectedQueue) {
- EXPECT_EQ(base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}),
- thread_bundle_.GetMainThreadTaskRunner());
-}
-
-TEST_F(BrowserTaskExecutorTest, EnsureIOThreadTraitPointsToExpectedQueue) {
- EXPECT_EQ(
- base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
- BrowserTaskExecutor::GetProxyTaskRunnerForThread(BrowserThread::IO));
-}
-
-using MockTask =
+using StrictMockTask =
testing::StrictMock<base::MockCallback<base::RepeatingCallback<void()>>>;
TEST_F(BrowserTaskExecutorTest, RunAllPendingTasksForTestingOnUI) {
- MockTask task_1;
- MockTask task_2;
+ StrictMockTask task_1;
+ StrictMockTask task_2;
EXPECT_CALL(task_1, Run).WillOnce(testing::Invoke([&]() {
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task_2.Get());
}));
@@ -102,10 +63,10 @@ TEST_F(BrowserTaskExecutorTest, RunAllPendingTasksForTestingOnUI) {
}
TEST_F(BrowserTaskExecutorTest, RunAllPendingTasksForTestingOnIO) {
- MockTask task_1;
- MockTask task_2;
+ StrictMockTask task_1;
+ StrictMockTask task_2;
EXPECT_CALL(task_1, Run).WillOnce(testing::Invoke([&]() {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task_2.Get());
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, task_2.Get());
}));
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, task_1.Get());
@@ -119,17 +80,17 @@ TEST_F(BrowserTaskExecutorTest, RunAllPendingTasksForTestingOnIO) {
}
TEST_F(BrowserTaskExecutorTest, RunAllPendingTasksForTestingOnIOIsReentrant) {
- MockTask task_1;
- MockTask task_2;
- MockTask task_3;
+ StrictMockTask task_1;
+ StrictMockTask task_2;
+ StrictMockTask task_3;
EXPECT_CALL(task_1, Run).WillOnce(Invoke([&]() {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task_2.Get());
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, task_2.Get());
BrowserTaskExecutor::RunAllPendingTasksOnThreadForTesting(
BrowserThread::IO);
}));
EXPECT_CALL(task_2, Run).WillOnce(Invoke([&]() {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task_3.Get());
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, task_3.Get());
}));
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, task_1.Get());
@@ -142,6 +103,41 @@ TEST_F(BrowserTaskExecutorTest, RunAllPendingTasksForTestingOnIOIsReentrant) {
BrowserTaskExecutor::RunAllPendingTasksOnThreadForTesting(BrowserThread::IO);
}
+// Helper to perform the same tets for all BrowserThread::ID values.
+class BrowserTaskTraitsMappingTest : public BrowserTaskExecutorTest {
+ protected:
+ template <BrowserThread::ID ID>
+ void CheckExpectations() {
+ EXPECT_EQ(GetQueueType({ID, TaskPriority::BEST_EFFORT}),
+ QueueType::kBestEffort);
+ EXPECT_EQ(GetQueueType({ID, TaskPriority::USER_VISIBLE}),
+ QueueType::kDefault);
+ EXPECT_EQ(GetQueueType({ID, TaskPriority::USER_BLOCKING}),
+ QueueType::kUserBlocking);
+
+ EXPECT_EQ(GetQueueType({ID, BrowserTaskType::kBootstrap}),
+ QueueType::kBootstrap);
+ EXPECT_EQ(GetQueueType({ID, BrowserTaskType::kDefault}),
+ QueueType::kUserBlocking);
+ EXPECT_EQ(GetQueueType({ID, BrowserTaskType::kNavigation}),
+ QueueType::kNavigationAndPreconnection);
+ EXPECT_EQ(GetQueueType({ID, BrowserTaskType::kPreconnect}),
+ QueueType::kNavigationAndPreconnection);
+
+ EXPECT_EQ(GetQueueType({ID}), QueueType::kUserBlocking);
+ }
+
+ private:
+ QueueType GetQueueType(const base::TaskTraits& traits) {
+ return BrowserTaskExecutor::GetThreadIdAndQueueType(traits).queue_type;
+ }
+};
+
+TEST_F(BrowserTaskTraitsMappingTest, BrowserTaskTraitsMapToProperPriorities) {
+ CheckExpectations<BrowserThread::UI>();
+ CheckExpectations<BrowserThread::IO>();
+}
+
class BrowserTaskExecutorWithCustomSchedulerTest : public testing::Test {
private:
class ScopedTaskEnvironmentWithCustomScheduler
@@ -155,23 +151,16 @@ class BrowserTaskExecutorWithCustomSchedulerTest : public testing::Test {
BrowserUIThreadScheduler::CreateForTesting(sequence_manager(),
GetTimeDomain());
DeferredInitFromSubclass(
- browser_ui_thread_scheduler->GetTaskRunnerForTesting(
+ browser_ui_thread_scheduler->GetHandle().GetBrowserTaskRunner(
QueueType::kDefault));
- browser_ui_thread_scheduler_ = browser_ui_thread_scheduler.get();
- BrowserTaskExecutor::CreateWithBrowserUIThreadSchedulerForTesting(
- std::move(browser_ui_thread_scheduler));
- }
-
- BrowserUIThreadScheduler* browser_ui_thread_scheduler() const {
- return browser_ui_thread_scheduler_;
+ BrowserTaskExecutor::CreateForTesting(
+ std::move(browser_ui_thread_scheduler),
+ std::make_unique<BrowserIOTaskEnvironment>());
}
-
- private:
- BrowserUIThreadScheduler* browser_ui_thread_scheduler_;
};
public:
- using QueueType = BrowserUIThreadTaskQueue::QueueType;
+ using QueueType = BrowserTaskQueues::QueueType;
~BrowserTaskExecutorWithCustomSchedulerTest() override {
BrowserTaskExecutor::ResetForTesting();
@@ -182,19 +171,10 @@ class BrowserTaskExecutorWithCustomSchedulerTest : public testing::Test {
};
TEST_F(BrowserTaskExecutorWithCustomSchedulerTest,
- EnsureUIThreadTraitPointsToExpectedQueue) {
- EXPECT_EQ(base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}),
- scoped_task_environment_.browser_ui_thread_scheduler()
- ->GetTaskRunnerForTesting(QueueType::kDefault));
- EXPECT_EQ(base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}),
- scoped_task_environment_.GetMainThreadTaskRunner());
-}
-
-TEST_F(BrowserTaskExecutorWithCustomSchedulerTest,
UserVisibleOrBlockingTasksRunDuringStartup) {
- MockTask best_effort;
- MockTask user_visible;
- MockTask user_blocking;
+ StrictMockTask best_effort;
+ StrictMockTask user_visible;
+ StrictMockTask user_blocking;
base::PostTaskWithTraits(FROM_HERE,
{BrowserThread::UI, base::TaskPriority::BEST_EFFORT},
@@ -217,7 +197,7 @@ TEST_F(BrowserTaskExecutorWithCustomSchedulerTest,
auto ui_best_effort_runner = base::CreateSingleThreadTaskRunnerWithTraits(
{BrowserThread::UI, base::TaskPriority::BEST_EFFORT});
- MockTask best_effort;
+ StrictMockTask best_effort;
ui_best_effort_runner->PostTask(FROM_HERE, best_effort.Get());
ui_best_effort_runner->PostDelayedTask(
@@ -230,7 +210,7 @@ TEST_F(BrowserTaskExecutorWithCustomSchedulerTest,
best_effort.Get());
scoped_task_environment_.RunUntilIdle();
- BrowserTaskExecutor::NotifyBrowserStartupCompleted();
+ BrowserTaskExecutor::EnableAllQueues();
EXPECT_CALL(best_effort, Run).Times(4);
scoped_task_environment_.FastForwardBy(
base::TimeDelta::FromMilliseconds(100));
diff --git a/chromium/content/browser/scheduler/browser_task_queues.cc b/chromium/content/browser/scheduler/browser_task_queues.cc
new file mode 100644
index 00000000000..b95e60fd79a
--- /dev/null
+++ b/chromium/content/browser/scheduler/browser_task_queues.cc
@@ -0,0 +1,274 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/scheduler/browser_task_queues.h"
+
+#include <iterator>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/feature_list.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task/sequence_manager/sequence_manager.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_features.h"
+
+namespace content {
+namespace {
+
+using QueuePriority = ::base::sequence_manager::TaskQueue::QueuePriority;
+using InsertFencePosition =
+ ::base::sequence_manager::TaskQueue::InsertFencePosition;
+
+const char* GetControlTaskQueueName(BrowserThread::ID thread_id) {
+ switch (thread_id) {
+ case BrowserThread::UI:
+ return "ui_control_tq";
+ case BrowserThread::IO:
+ return "io_control_tq";
+ case BrowserThread::ID_COUNT:
+ break;
+ }
+ NOTREACHED();
+ return "";
+}
+
+const char* GetRunAllPendingTaskQueueName(BrowserThread::ID thread_id) {
+ switch (thread_id) {
+ case BrowserThread::UI:
+ return "ui_run_all_pending_tq";
+ case BrowserThread::IO:
+ return "io_run_all_pending_tq";
+ case BrowserThread::ID_COUNT:
+ break;
+ }
+ NOTREACHED();
+ return "";
+}
+
+const char* GetUITaskQueueName(BrowserTaskQueues::QueueType queue_type) {
+ switch (queue_type) {
+ case BrowserTaskQueues::QueueType::kBestEffort:
+ return "ui_best_effort_tq";
+ case BrowserTaskQueues::QueueType::kBootstrap:
+ return "ui_bootstrap_tq";
+ case BrowserTaskQueues::QueueType::kNavigationAndPreconnection:
+ return "ui_navigation_and_preconnection_tq";
+ case BrowserTaskQueues::QueueType::kDefault:
+ return "ui_default_tq";
+ case BrowserTaskQueues::QueueType::kUserBlocking:
+ return "ui_user_blocking_tq";
+ }
+}
+
+const char* GetIOTaskQueueName(BrowserTaskQueues::QueueType queue_type) {
+ switch (queue_type) {
+ case BrowserTaskQueues::QueueType::kBestEffort:
+ return "io_best_effort_tq";
+ case BrowserTaskQueues::QueueType::kBootstrap:
+ return "io_bootstrap_tq";
+ case BrowserTaskQueues::QueueType::kNavigationAndPreconnection:
+ return "io_navigation_and_preconnection_tq";
+ case BrowserTaskQueues::QueueType::kDefault:
+ return "io_default_tq";
+ case BrowserTaskQueues::QueueType::kUserBlocking:
+ return "io_user_blocking_tq";
+ }
+}
+
+const char* GetTaskQueueName(BrowserThread::ID thread_id,
+ BrowserTaskQueues::QueueType queue_type) {
+ switch (thread_id) {
+ case BrowserThread::UI:
+ return GetUITaskQueueName(queue_type);
+ case BrowserThread::IO:
+ return GetIOTaskQueueName(queue_type);
+ case BrowserThread::ID_COUNT:
+ break;
+ }
+ NOTREACHED();
+ return "";
+}
+
+const char* GetDefaultQueueName(BrowserThread::ID thread_id) {
+ switch (thread_id) {
+ case BrowserThread::UI:
+ return "ui_thread_tq";
+ case BrowserThread::IO:
+ return "io_thread_tq";
+ case BrowserThread::ID_COUNT:
+ break;
+ }
+ NOTREACHED();
+ return "";
+}
+
+} // namespace
+
+BrowserTaskQueues::Handle::Handle(Handle&&) = default;
+BrowserTaskQueues::Handle::Handle(const Handle&) = default;
+BrowserTaskQueues::Handle::~Handle() = default;
+BrowserTaskQueues::Handle& BrowserTaskQueues::Handle::operator=(Handle&&) =
+ default;
+BrowserTaskQueues::Handle& BrowserTaskQueues::Handle::operator=(const Handle&) =
+ default;
+
+BrowserTaskQueues::Handle::Handle(BrowserTaskQueues* outer)
+ : outer_(outer),
+ control_task_runner_(outer_->control_queue_->task_runner()),
+ default_task_runner_(outer_->default_task_queue_->task_runner()),
+ browser_task_runners_(outer_->CreateBrowserTaskRunners()) {}
+
+void BrowserTaskQueues::Handle::PostFeatureListInitializationSetup() {
+ control_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&BrowserTaskQueues::PostFeatureListInitializationSetup,
+ base::Unretained(outer_)));
+}
+
+void BrowserTaskQueues::Handle::EnableAllQueues() {
+ control_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&BrowserTaskQueues::EnableAllQueues,
+ base::Unretained(outer_)));
+}
+
+void BrowserTaskQueues::Handle::EnableAllExceptBestEffortQueues() {
+ control_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&BrowserTaskQueues::EnableAllExceptBestEffortQueues,
+ base::Unretained(outer_)));
+}
+
+void BrowserTaskQueues::Handle::ScheduleRunAllPendingTasksForTesting(
+ base::OnceClosure on_pending_task_ran) {
+ control_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &BrowserTaskQueues::StartRunAllPendingTasksForTesting,
+ base::Unretained(outer_),
+ base::ScopedClosureRunner(std::move(on_pending_task_ran))));
+}
+
+BrowserTaskQueues::BrowserTaskQueues(
+ BrowserThread::ID thread_id,
+ base::sequence_manager::SequenceManager* sequence_manager,
+ base::sequence_manager::TimeDomain* time_domain) {
+ for (size_t i = 0; i < browser_queues_and_voters_.size(); ++i) {
+ browser_queues_and_voters_[i].first = sequence_manager->CreateTaskQueue(
+ base::sequence_manager::TaskQueue::Spec(
+ GetTaskQueueName(thread_id, static_cast<QueueType>(i)))
+ .SetTimeDomain(time_domain));
+ browser_queues_and_voters_[i].second =
+ browser_queues_and_voters_[i].first->CreateQueueEnabledVoter();
+ browser_queues_and_voters_[i].second->SetVoteToEnable(false);
+ }
+
+ // Default task queue
+ default_task_queue_ = sequence_manager->CreateTaskQueue(
+ base::sequence_manager::TaskQueue::Spec(GetDefaultQueueName(thread_id))
+ .SetTimeDomain(time_domain));
+
+ // Best effort queue
+ GetBrowserTaskQueue(QueueType::kBestEffort)
+ ->SetQueuePriority(QueuePriority::kBestEffortPriority);
+
+ // Control queue
+ control_queue_ =
+ sequence_manager->CreateTaskQueue(base::sequence_manager::TaskQueue::Spec(
+ GetControlTaskQueueName(thread_id))
+ .SetTimeDomain(time_domain));
+ control_queue_->SetQueuePriority(QueuePriority::kControlPriority);
+
+ // Run all pending queue
+ run_all_pending_tasks_queue_ = sequence_manager->CreateTaskQueue(
+ base::sequence_manager::TaskQueue::Spec(
+ GetRunAllPendingTaskQueueName(thread_id))
+ .SetTimeDomain(time_domain));
+ run_all_pending_tasks_queue_->SetQueuePriority(
+ QueuePriority::kBestEffortPriority);
+}
+
+BrowserTaskQueues::~BrowserTaskQueues() {
+ for (auto& queue : browser_queues_and_voters_) {
+ queue.first->ShutdownTaskQueue();
+ }
+ control_queue_->ShutdownTaskQueue();
+ default_task_queue_->ShutdownTaskQueue();
+ run_all_pending_tasks_queue_->ShutdownTaskQueue();
+}
+
+std::array<scoped_refptr<base::SingleThreadTaskRunner>,
+ BrowserTaskQueues::kNumQueueTypes>
+BrowserTaskQueues::CreateBrowserTaskRunners() const {
+ std::array<scoped_refptr<base::SingleThreadTaskRunner>, kNumQueueTypes>
+ task_runners;
+ for (size_t i = 0; i < browser_queues_and_voters_.size(); ++i) {
+ task_runners[i] = browser_queues_and_voters_[i].first->task_runner();
+ }
+ return task_runners;
+}
+
+void BrowserTaskQueues::PostFeatureListInitializationSetup() {
+ if (base::FeatureList::IsEnabled(features::kPrioritizeBootstrapTasks)) {
+ GetBrowserTaskQueue(QueueType::kBootstrap)
+ ->SetQueuePriority(QueuePriority::kHighestPriority);
+
+ // Navigation and preconnection tasks are also important during startup so
+ // prioritize them too.
+ GetBrowserTaskQueue(QueueType::kNavigationAndPreconnection)
+ ->SetQueuePriority(QueuePriority::kHighPriority);
+ }
+}
+
+void BrowserTaskQueues::EnableAllQueues() {
+ for (size_t i = 0; i < browser_queues_and_voters_.size(); ++i) {
+ browser_queues_and_voters_[i].second->SetVoteToEnable(true);
+ }
+}
+
+void BrowserTaskQueues::EnableAllExceptBestEffortQueues() {
+ for (size_t i = 0; i < browser_queues_and_voters_.size(); ++i) {
+ if (i != static_cast<size_t>(QueueType::kBestEffort))
+ browser_queues_and_voters_[i].second->SetVoteToEnable(true);
+ }
+}
+
+// To run all pending tasks we do the following. We insert a fence in all queues
+// and post a task to the |run_all_pending_queue_| which has the lowest priority
+// possible. That makes sure that all tasks up to the fences will have run
+// before this posted task runs. Note that among tasks with the same priority
+// ties are broken by using the enqueue order, so all prior best effort tasks
+// will have run before this one does. This task will then remove all the fences
+// and call the user provided callback to signal that all pending tasks have
+// run. This method is "reentrant" as in we can call it multiple times as the
+// fences will just be moved back, but we need to make sure that only the last
+// call removes the fences, for that we keep track of "nesting" with
+// |run_all_pending_nesting_level_|
+void BrowserTaskQueues::StartRunAllPendingTasksForTesting(
+ base::ScopedClosureRunner on_pending_task_ran) {
+ ++run_all_pending_nesting_level_;
+ for (const auto& queue : browser_queues_and_voters_) {
+ queue.first->InsertFence(InsertFencePosition::kNow);
+ }
+ default_task_queue_->InsertFence(InsertFencePosition::kNow);
+ run_all_pending_tasks_queue_->task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&BrowserTaskQueues::EndRunAllPendingTasksForTesting,
+ base::Unretained(this), std::move(on_pending_task_ran)));
+}
+
+void BrowserTaskQueues::EndRunAllPendingTasksForTesting(
+ base::ScopedClosureRunner on_pending_task_ran) {
+ --run_all_pending_nesting_level_;
+ if (run_all_pending_nesting_level_ == 0) {
+ for (const auto& queue : browser_queues_and_voters_) {
+ queue.first->RemoveFence();
+ }
+ default_task_queue_->RemoveFence();
+ }
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/scheduler/browser_task_queues.h b/chromium/content/browser/scheduler/browser_task_queues.h
new file mode 100644
index 00000000000..5c81ebefd7f
--- /dev/null
+++ b/chromium/content/browser/scheduler/browser_task_queues.h
@@ -0,0 +1,187 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SCHEDULER_BROWSER_TASK_QUEUES_H_
+#define CONTENT_BROWSER_SCHEDULER_BROWSER_TASK_QUEUES_H_
+
+#include <array>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace base {
+namespace sequence_manager {
+class SequenceManager;
+class TimeDomain;
+} // namespace sequence_manager
+} // namespace base
+
+namespace content {
+
+// Common task queues for browser threads. This class holds all the queues
+// needed by browser threads. This makes it easy for all browser threads to have
+// the same queues. Thic class also provides a Handler to act on the queues from
+// any thread.
+//
+// Instances must be created and destroyed on the same thread as the
+// underlying SequenceManager and instances are not allowed to outlive this
+// SequenceManager. All methods of this class must be called from the
+// associated thread unless noted otherwise. If you need to perform operations
+// from a different thread use the a Handle instance instead.
+//
+// Attention: All queues are initially disabled, that is, tasks will not be run
+// for them.
+class CONTENT_EXPORT BrowserTaskQueues {
+ public:
+ enum class QueueType {
+ // Catch all for tasks that don't fit other categories.
+ // TODO(alexclarke): Introduce new semantic types as needed to minimize the
+ // number of default tasks.
+ kDefault,
+
+ // For non-urgent work, that will only execute if there's nothing else to
+ // do. Can theoretically be starved indefinitely although that's unlikely in
+ // practice.
+ kBestEffort,
+
+ // For tasks on the critical path up to issuing the initial navigation.
+ kBootstrap,
+
+ // For navigation and preconnection related tasks.
+ kNavigationAndPreconnection,
+
+ // A generic high priority queue. Long term we should replace this with
+ // additional semantic annotations.
+ kUserBlocking,
+
+ kMaxValue = kUserBlocking
+ };
+
+ static constexpr size_t kNumQueueTypes =
+ static_cast<size_t>(QueueType::kMaxValue) + 1;
+
+ // Handle to a BrowserTaskQueues instance that can be used from any thread
+ // as all operations are thread safe.
+ //
+ // If the underlying BrowserTaskQueues is destroyed all methods of this
+ // class become no-ops, that is it is safe for this class to outlive its
+ // parent BrowserTaskQueues.
+ class CONTENT_EXPORT Handle {
+ public:
+ // Handles can be copied / moved around.
+ Handle(Handle&&) noexcept;
+ Handle(const Handle&);
+ ~Handle();
+ Handle& operator=(Handle&&) noexcept;
+ Handle& operator=(const Handle&);
+
+ // Returns the task runner that should be returned by
+ // ThreadTaskRunnerHandle::Get().
+ const scoped_refptr<base::SingleThreadTaskRunner>& GetDefaultTaskRunner() {
+ return default_task_runner_;
+ }
+
+ const scoped_refptr<base::SingleThreadTaskRunner>& GetBrowserTaskRunner(
+ QueueType queue_type) const {
+ return browser_task_runners_[static_cast<size_t>(queue_type)];
+ }
+
+ // Initializes any scheduler experiments. Should be called after
+ // FeatureLists have been initialized (which usually happens after task
+ // queues are set up).
+ void PostFeatureListInitializationSetup();
+
+ // Enables all tasks queues. Can be called multiple times.
+ void EnableAllQueues();
+
+ // Enables all task queues except the effort ones. Can be called multiple
+ // times.
+ void EnableAllExceptBestEffortQueues();
+
+ // Schedules |on_pending_task_ran| to run when all pending tasks (at the
+ // time this method was invoked) have run. Only "runnable" tasks are taken
+ // into account, that is tasks from disabled queues are ignored, also this
+ // only works reliably for immediate tasks, delayed tasks might or might not
+ // run depending on timing.
+ //
+ // The callback will run on the thread associated with this Handle, unless
+ // that thread is no longer accepting tasks; in which case it will be run
+ // inline immediately.
+ //
+ // The recommended usage pattern is:
+ // RunLoop run_loop;
+ // handle.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ // run_loop.Run();
+ void ScheduleRunAllPendingTasksForTesting(
+ base::OnceClosure on_pending_task_ran);
+
+ private:
+ // Only BrowserTaskQueues can create new instances
+ friend class BrowserTaskQueues;
+ explicit Handle(BrowserTaskQueues* task_queues);
+
+ // |outer_| can only be safely used from a task posted to one of the
+ // runners.
+ BrowserTaskQueues* outer_ = nullptr;
+ scoped_refptr<base::SingleThreadTaskRunner> control_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
+ std::array<scoped_refptr<base::SingleThreadTaskRunner>, kNumQueueTypes>
+ browser_task_runners_;
+ };
+
+ // |sequence_manager| and |time_domain| must outlive this instance.
+ explicit BrowserTaskQueues(
+ BrowserThread::ID thread_id,
+ base::sequence_manager::SequenceManager* sequence_manager,
+ base::sequence_manager::TimeDomain* time_domain);
+
+ // Destroys all queues.
+ ~BrowserTaskQueues();
+
+ Handle CreateHandle() { return Handle(this); }
+
+ private:
+ // All these methods can only be called from the associated thread. To make
+ // sure that is the case they will always be called from a task posted to the
+ // |control_queue_|.
+ void StartRunAllPendingTasksForTesting(
+ base::ScopedClosureRunner on_pending_task_ran);
+ void EndRunAllPendingTasksForTesting(
+ base::ScopedClosureRunner on_pending_task_ran);
+ void EnableAllQueues();
+ void EnableAllExceptBestEffortQueues();
+ void PostFeatureListInitializationSetup();
+
+ base::sequence_manager::TaskQueue* GetBrowserTaskQueue(QueueType type) const {
+ return browser_queues_and_voters_[static_cast<size_t>(type)].first.get();
+ }
+
+ std::array<scoped_refptr<base::SingleThreadTaskRunner>, kNumQueueTypes>
+ CreateBrowserTaskRunners() const;
+
+ using QueueVoterPair = std::pair<
+ scoped_refptr<base::sequence_manager::TaskQueue>,
+ std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter>>;
+
+ std::array<QueueVoterPair, kNumQueueTypes> browser_queues_and_voters_;
+ // Helper queue to make sure private methods run on the associated thread. the
+ // control queue has maximum priority and will never be disabled.
+ scoped_refptr<base::sequence_manager::TaskQueue> control_queue_;
+
+ // Queue that backs the default TaskRunner registered with SequenceManager.
+ // This will be the one returned by ThreadTaskRunnerHandle::Get(). Note this
+ // is different from QueueType:kDefault as this queue needs to be enabled from
+ // the beginning.
+ scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_;
+
+ // Helper queue to run all pending tasks.
+ scoped_refptr<base::sequence_manager::TaskQueue> run_all_pending_tasks_queue_;
+ int run_all_pending_nesting_level_ = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCHEDULER_BROWSER_TASK_QUEUES_H_
diff --git a/chromium/content/browser/scheduler/browser_task_queues_unittest.cc b/chromium/content/browser/scheduler/browser_task_queues_unittest.cc
new file mode 100644
index 00000000000..8575e6524f8
--- /dev/null
+++ b/chromium/content/browser/scheduler/browser_task_queues_unittest.cc
@@ -0,0 +1,275 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/scheduler/browser_task_queues.h"
+
+#include <array>
+#include <memory>
+
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/task/sequence_manager/sequence_manager.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/mock_callback.h"
+#include "content/public/browser/browser_thread.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+using ::base::MessageLoop;
+using ::base::RunLoop;
+using ::base::sequence_manager::CreateSequenceManagerOnCurrentThreadWithPump;
+using ::base::sequence_manager::SequenceManager;
+using ::testing::Invoke;
+using ::testing::Mock;
+
+using StrictMockTask =
+ testing::StrictMock<base::MockCallback<base::RepeatingCallback<void()>>>;
+
+using QueueType = BrowserTaskQueues::QueueType;
+
+class BrowserTaskQueuesTest : public testing::Test {
+ protected:
+ BrowserTaskQueuesTest()
+ : sequence_manager_(CreateSequenceManagerOnCurrentThreadWithPump(
+ base::MessagePump::Create(base::MessagePump::Type::DEFAULT))),
+ queues_(std::make_unique<BrowserTaskQueues>(
+ BrowserThread::UI,
+ sequence_manager_.get(),
+ sequence_manager_->GetRealTimeDomain())),
+ handle_(queues_->CreateHandle()) {
+ sequence_manager_->SetDefaultTaskRunner(handle_.GetDefaultTaskRunner());
+ }
+
+ std::unique_ptr<SequenceManager> sequence_manager_;
+ std::unique_ptr<BrowserTaskQueues> queues_;
+ BrowserTaskQueues::Handle handle_;
+};
+
+TEST_F(BrowserTaskQueuesTest, NoTaskRunsUntilQueuesAreEnabled) {
+ StrictMockTask task;
+ for (size_t i = 0; i < BrowserTaskQueues::kNumQueueTypes; ++i) {
+ handle_.GetBrowserTaskRunner(static_cast<QueueType>(i))
+ ->PostTask(FROM_HERE, task.Get());
+ }
+
+ {
+ RunLoop run_loop;
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ handle_.EnableAllQueues();
+
+ {
+ RunLoop run_loop;
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ EXPECT_CALL(task, Run).Times(BrowserTaskQueues::kNumQueueTypes);
+ run_loop.Run();
+ }
+}
+
+TEST_F(BrowserTaskQueuesTest, OnlyDefaultQueueRunsTasksOnCreation) {
+ StrictMockTask task;
+ for (size_t i = 0; i < BrowserTaskQueues::kNumQueueTypes; ++i) {
+ handle_.GetBrowserTaskRunner(static_cast<QueueType>(i))
+ ->PostTask(FROM_HERE, task.Get());
+ }
+
+ StrictMockTask default_task;
+ handle_.GetDefaultTaskRunner()->PostTask(FROM_HERE, default_task.Get());
+
+ {
+ RunLoop run_loop;
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ EXPECT_CALL(default_task, Run);
+ run_loop.Run();
+ }
+}
+
+TEST_F(BrowserTaskQueuesTest, TasksRunWhenQueuesAreEnabled) {
+ StrictMockTask task;
+ for (size_t i = 0; i < BrowserTaskQueues::kNumQueueTypes; ++i) {
+ handle_.GetBrowserTaskRunner(static_cast<QueueType>(i))
+ ->PostTask(FROM_HERE, task.Get());
+ }
+
+ {
+ RunLoop run_loop;
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ handle_.EnableAllQueues();
+
+ {
+ RunLoop run_loop;
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ EXPECT_CALL(task, Run).Times(BrowserTaskQueues::kNumQueueTypes);
+ run_loop.Run();
+ }
+}
+
+TEST_F(BrowserTaskQueuesTest, SimplePosting) {
+ handle_.EnableAllQueues();
+ scoped_refptr<base::SingleThreadTaskRunner> tq =
+ handle_.GetBrowserTaskRunner(QueueType::kDefault);
+
+ StrictMockTask task_1;
+ StrictMockTask task_2;
+ StrictMockTask task_3;
+
+ {
+ testing::InSequence s;
+ EXPECT_CALL(task_1, Run);
+ EXPECT_CALL(task_2, Run);
+ EXPECT_CALL(task_3, Run);
+ }
+
+ tq->PostTask(FROM_HERE, task_1.Get());
+ tq->PostTask(FROM_HERE, task_2.Get());
+ tq->PostTask(FROM_HERE, task_3.Get());
+
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(BrowserTaskQueuesTest, RunAllPendingTasksForTesting) {
+ handle_.EnableAllQueues();
+
+ StrictMockTask task;
+ StrictMockTask followup_task;
+ EXPECT_CALL(task, Run).WillOnce(Invoke([&]() {
+ for (size_t i = 0; i < BrowserTaskQueues::kNumQueueTypes; ++i) {
+ handle_.GetBrowserTaskRunner(static_cast<QueueType>(i))
+ ->PostTask(FROM_HERE, followup_task.Get());
+ }
+ }));
+
+ handle_.GetBrowserTaskRunner(QueueType::kDefault)
+ ->PostTask(FROM_HERE, task.Get());
+
+ {
+ RunLoop run_loop;
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ Mock::VerifyAndClearExpectations(&task);
+ EXPECT_CALL(followup_task, Run).Times(BrowserTaskQueues::kNumQueueTypes);
+
+ RunLoop run_loop;
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ run_loop.Run();
+}
+
+TEST_F(BrowserTaskQueuesTest, RunAllPendingTasksForTestingRunsAllTasks) {
+ constexpr size_t kTasksPerPriority = 100;
+ handle_.EnableAllQueues();
+
+ StrictMockTask task;
+ EXPECT_CALL(task, Run).Times(BrowserTaskQueues::kNumQueueTypes *
+ kTasksPerPriority);
+ for (size_t i = 0; i < BrowserTaskQueues::kNumQueueTypes; ++i) {
+ for (size_t j = 0; j < kTasksPerPriority; ++j) {
+ handle_.GetBrowserTaskRunner(static_cast<QueueType>(i))
+ ->PostTask(FROM_HERE, task.Get());
+ }
+ }
+
+ RunLoop run_loop;
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ run_loop.Run();
+}
+
+TEST_F(BrowserTaskQueuesTest, RunAllPendingTasksForTestingIsReentrant) {
+ handle_.EnableAllQueues();
+ StrictMockTask task_1;
+ StrictMockTask task_2;
+ StrictMockTask task_3;
+
+ EXPECT_CALL(task_1, Run).WillOnce(Invoke([&]() {
+ handle_.GetBrowserTaskRunner(QueueType::kDefault)
+ ->PostTask(FROM_HERE, task_2.Get());
+ RunLoop run_loop(RunLoop::Type::kNestableTasksAllowed);
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ run_loop.Run();
+ }));
+
+ EXPECT_CALL(task_2, Run).WillOnce(Invoke([&]() {
+ handle_.GetBrowserTaskRunner(QueueType::kDefault)
+ ->PostTask(FROM_HERE, task_3.Get());
+ }));
+
+ handle_.GetBrowserTaskRunner(QueueType::kDefault)
+ ->PostTask(FROM_HERE, task_1.Get());
+
+ RunLoop run_loop;
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ run_loop.Run();
+}
+
+TEST_F(BrowserTaskQueuesTest,
+ RunAllPendingTasksForTestingIgnoresBestEffortIfNotEnabled) {
+ handle_.EnableAllExceptBestEffortQueues();
+ StrictMockTask best_effort_task;
+ StrictMockTask default_task;
+
+ handle_.GetBrowserTaskRunner(QueueType::kBestEffort)
+ ->PostTask(FROM_HERE, best_effort_task.Get());
+ handle_.GetBrowserTaskRunner(QueueType::kDefault)
+ ->PostTask(FROM_HERE, default_task.Get());
+
+ EXPECT_CALL(default_task, Run);
+
+ RunLoop run_loop;
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ run_loop.Run();
+}
+
+TEST_F(BrowserTaskQueuesTest,
+ RunAllPendingTasksForTestingRunsBestEffortTasksWhenEnabled) {
+ handle_.EnableAllExceptBestEffortQueues();
+ StrictMockTask task_1;
+ StrictMockTask task_2;
+ StrictMockTask task_3;
+
+ EXPECT_CALL(task_1, Run).WillOnce(Invoke([&]() {
+ // This task should not run as it is posted after the
+ // RunAllPendingTasksForTesting() call
+ handle_.GetBrowserTaskRunner(QueueType::kBestEffort)
+ ->PostTask(FROM_HERE, task_3.Get());
+ handle_.EnableAllQueues();
+ }));
+ EXPECT_CALL(task_2, Run);
+
+ handle_.GetBrowserTaskRunner(QueueType::kDefault)
+ ->PostTask(FROM_HERE, task_1.Get());
+ handle_.GetBrowserTaskRunner(QueueType::kBestEffort)
+ ->PostTask(FROM_HERE, task_2.Get());
+
+ RunLoop run_loop;
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ run_loop.Run();
+}
+
+TEST_F(BrowserTaskQueuesTest, HandleStillWorksWhenQueuesDestroyed) {
+ handle_.EnableAllQueues();
+ StrictMockTask task;
+ queues_.reset();
+
+ for (size_t i = 0; i < BrowserTaskQueues::kNumQueueTypes; ++i) {
+ EXPECT_FALSE(
+ handle_.GetBrowserTaskRunner(static_cast<QueueType>(i))
+ ->PostTask(FROM_HERE, base::BindLambdaForTesting([]() {})));
+ }
+
+ RunLoop run_loop;
+ handle_.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
+ run_loop.Run();
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/scheduler/browser_ui_thread_scheduler.cc b/chromium/content/browser/scheduler/browser_ui_thread_scheduler.cc
index 54cae8574a5..ca438a9c7e7 100644
--- a/chromium/content/browser/scheduler/browser_ui_thread_scheduler.cc
+++ b/chromium/content/browser/scheduler/browser_ui_thread_scheduler.cc
@@ -9,7 +9,7 @@
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_pump.h"
#include "base/process/process.h"
#include "base/run_loop.h"
#include "base/task/sequence_manager/sequence_manager.h"
@@ -18,6 +18,7 @@
#include "base/task/sequence_manager/time_domain.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
namespace content {
@@ -33,117 +34,34 @@ BrowserUIThreadScheduler::CreateForTesting(
new BrowserUIThreadScheduler(sequence_manager, time_domain));
}
-void BrowserUIThreadScheduler::PostFeatureListSetup() {
- if (base::FeatureList::IsEnabled(features::kPrioritizeBootstrapTasks)) {
- task_queues_[QueueType::kBootstrap]->SetQueuePriority(
- base::sequence_manager::TaskQueue::kHighestPriority);
-
- // Navigation and preconnection tasks are also important during startup so
- // prioritize them too.
- task_queues_[QueueType::kNavigationAndPreconnection]->SetQueuePriority(
- base::sequence_manager::TaskQueue::kHighPriority);
- }
-}
-
-void BrowserUIThreadScheduler::Shutdown() {
- task_queues_.clear();
- owned_sequence_manager_.reset();
- sequence_manager_ = nullptr;
-}
-
BrowserUIThreadScheduler::BrowserUIThreadScheduler()
: owned_sequence_manager_(
base::sequence_manager::CreateUnboundSequenceManager(
- base::sequence_manager::SequenceManager::Settings{
- .message_loop_type = base::MessageLoop::TYPE_UI})),
- sequence_manager_(owned_sequence_manager_.get()),
- time_domain_(sequence_manager_->GetRealTimeDomain()) {
- InitialiseTaskQueues();
-
- sequence_manager_->SetDefaultTaskRunner(GetTaskRunner(QueueType::kDefault));
-
- sequence_manager_->BindToMessagePump(
- base::MessageLoop::CreateMessagePumpForType(base::MessageLoop::TYPE_UI));
+ base::sequence_manager::SequenceManager::Settings::Builder()
+ .SetMessagePumpType(base::MessageLoop::TYPE_UI)
+ .Build())),
+ task_queues_(BrowserThread::UI,
+ owned_sequence_manager_.get(),
+ owned_sequence_manager_->GetRealTimeDomain()),
+ handle_(task_queues_.CreateHandle()) {
+ CommonSequenceManagerSetup(owned_sequence_manager_.get());
+ owned_sequence_manager_->SetDefaultTaskRunner(handle_.GetDefaultTaskRunner());
+
+ owned_sequence_manager_->BindToMessagePump(
+ base::MessagePump::Create(base::MessagePump::Type::UI));
}
BrowserUIThreadScheduler::BrowserUIThreadScheduler(
base::sequence_manager::SequenceManager* sequence_manager,
base::sequence_manager::TimeDomain* time_domain)
- : sequence_manager_(sequence_manager), time_domain_(time_domain) {
- InitialiseTaskQueues();
-}
-
-void BrowserUIThreadScheduler::InitialiseTaskQueues() {
- DCHECK(sequence_manager_);
- sequence_manager_->EnableCrashKeys("ui_scheduler_async_stack");
-
- // To avoid locks in BrowserUIThreadScheduler::GetTaskRunner, eagerly
- // create all the well known task queues.
- CreateTaskQueuesAndRunners();
-
- InitialiseBestEffortQueue();
-}
-
-void BrowserUIThreadScheduler::CreateTaskQueuesAndRunners() {
- for (int i = 0;
- i < static_cast<int>(BrowserUIThreadTaskQueue::QueueType::kCount); i++) {
- BrowserUIThreadTaskQueue::QueueType queue_type =
- static_cast<BrowserUIThreadTaskQueue::QueueType>(i);
- scoped_refptr<BrowserUIThreadTaskQueue> task_queue =
- sequence_manager_->CreateTaskQueueWithType<BrowserUIThreadTaskQueue>(
- base::sequence_manager::TaskQueue::Spec(
- BrowserUIThreadTaskQueue::NameForQueueType(queue_type))
- .SetTimeDomain(time_domain_),
- queue_type);
- task_queues_.emplace(queue_type, task_queue);
- task_runners_.emplace(queue_type, task_queue->task_runner());
- }
-}
-
-void BrowserUIThreadScheduler::InitialiseBestEffortQueue() {
- auto queue = task_queues_[BrowserUIThreadTaskQueue::QueueType::kBestEffort];
- queue->SetQueuePriority(
- base::sequence_manager::TaskQueue::kBestEffortPriority);
- best_effort_voter_ = queue->CreateQueueEnabledVoter();
- best_effort_voter_->SetVoteToEnable(false);
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-BrowserUIThreadScheduler::GetTaskRunnerForTesting(QueueType queue_type) {
- return GetTaskRunner(queue_type);
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-BrowserUIThreadScheduler::GetTaskRunner(QueueType queue_type) {
- auto it = task_runners_.find(queue_type);
- if (it != task_runners_.end())
- return it->second;
- NOTREACHED();
- return scoped_refptr<base::SingleThreadTaskRunner>();
-}
-
-void BrowserUIThreadScheduler::EnableBestEffortQueues() {
- DCHECK(!best_effort_voter_->IsVotingToEnable());
- best_effort_voter_->SetVoteToEnable(true);
+ : task_queues_(BrowserThread::UI, sequence_manager, time_domain),
+ handle_(task_queues_.CreateHandle()) {
+ CommonSequenceManagerSetup(sequence_manager);
}
-void BrowserUIThreadScheduler::RunAllPendingTasksForTesting() {
- std::vector<scoped_refptr<BrowserUIThreadTaskQueue>> fenced_queues;
- for (const auto& queue : task_queues_) {
- bool had_fence = queue.second->HasActiveFence();
- queue.second->InsertFence(
- base::sequence_manager::TaskQueue::InsertFencePosition::kNow);
- // If there was a fence already this must be a re-entrant call to this
- // method. The previous statement just moved the fence further back. In this
- // case we do not remove the fence as the parent run loop needs all queues
- // to be fenced to be able to exit the run loop (i.e. become idle)
- if (!had_fence)
- fenced_queues.push_back(queue.second);
- }
- base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
- for (const auto& queue : fenced_queues) {
- queue->RemoveFence();
- }
+void BrowserUIThreadScheduler::CommonSequenceManagerSetup(
+ base::sequence_manager::SequenceManager* sequence_manager) {
+ sequence_manager->EnableCrashKeys("ui_scheduler_async_stack");
}
} // namespace content
diff --git a/chromium/content/browser/scheduler/browser_ui_thread_scheduler.h b/chromium/content/browser/scheduler/browser_ui_thread_scheduler.h
index 17f7c4f42cf..565f0a8ef28 100644
--- a/chromium/content/browser/scheduler/browser_ui_thread_scheduler.h
+++ b/chromium/content/browser/scheduler/browser_ui_thread_scheduler.h
@@ -10,7 +10,7 @@
#include "base/containers/flat_map.h"
#include "base/message_loop/message_loop.h"
#include "base/task/sequence_manager/task_queue.h"
-#include "content/browser/scheduler/browser_ui_thread_task_queue.h"
+#include "content/browser/scheduler/browser_task_queues.h"
#include "content/common/content_export.h"
namespace base {
@@ -27,6 +27,8 @@ class BrowserTaskExecutor;
// implement scheduling policy. This class is never deleted in production.
class CONTENT_EXPORT BrowserUIThreadScheduler {
public:
+ using Handle = BrowserTaskQueues::Handle;
+
BrowserUIThreadScheduler();
~BrowserUIThreadScheduler();
@@ -35,26 +37,9 @@ class CONTENT_EXPORT BrowserUIThreadScheduler {
base::sequence_manager::SequenceManager* sequence_manager,
base::sequence_manager::TimeDomain* time_domain);
- // Initializes any scheduler experiments.
- void PostFeatureListSetup();
-
- // Releases the scheduler although GetTaskRunner() continues to operate
- // however no tasks will be executed after this point.
- void Shutdown();
-
- // Attention: Can only be called once
- void EnableBestEffortQueues();
-
- using QueueType = BrowserUIThreadTaskQueue::QueueType;
-
- // Can be called from any thread.
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunnerForTesting(
- QueueType queue_type);
+ using QueueType = BrowserTaskQueues::QueueType;
- // Adds a fence to all queues, runs all tasks until idle, and finally removes
- // the fences. Note that the run loop will eventually become idle, as new
- // tasks will not be scheduled due to the fence.
- void RunAllPendingTasksForTesting();
+ Handle GetHandle() const { return handle_; }
private:
friend class BrowserTaskExecutor;
@@ -63,36 +48,16 @@ class CONTENT_EXPORT BrowserUIThreadScheduler {
base::sequence_manager::SequenceManager* sequence_manager,
base::sequence_manager::TimeDomain* time_domain);
- // Note this will be called before the FeatureList has been initialized.
- void InitialiseTaskQueues();
-
- // Creates all well known task queues (BrowserUIThreadTaskQueue::QueueType).
- void CreateTaskQueuesAndRunners();
-
- void InitialiseBestEffortQueue();
-
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
- QueueType queue_type);
+ void CommonSequenceManagerSetup(
+ base::sequence_manager::SequenceManager* sequence_manager);
// In production the BrowserUIThreadScheduler will own its SequenceManager,
// but in tests it may not.
std::unique_ptr<base::sequence_manager::SequenceManager>
owned_sequence_manager_;
- base::sequence_manager::SequenceManager* sequence_manager_;
- base::sequence_manager::TimeDomain* time_domain_;
-
- // The |task_queues_| and |task_runners_| are eagerly constructed and are
- // immutable after InitialiseTaskQueues() has run. If we ever change that e.g.
- // for per-frame scheduling then we will need to protect this with a lock.
- // NB |task_runners_| outlive the SequenceManager, but |task_queues_| do not.
- base::flat_map<QueueType, scoped_refptr<BrowserUIThreadTaskQueue>>
- task_queues_;
- base::flat_map<QueueType, scoped_refptr<base::SingleThreadTaskRunner>>
- task_runners_;
-
- std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter>
- best_effort_voter_;
+ BrowserTaskQueues task_queues_;
+ Handle handle_;
DISALLOW_COPY_AND_ASSIGN(BrowserUIThreadScheduler);
};
diff --git a/chromium/content/browser/scheduler/browser_ui_thread_scheduler_unittest.cc b/chromium/content/browser/scheduler/browser_ui_thread_scheduler_unittest.cc
index 9b47b06732c..fb88e16bb21 100644
--- a/chromium/content/browser/scheduler/browser_ui_thread_scheduler_unittest.cc
+++ b/chromium/content/browser/scheduler/browser_ui_thread_scheduler_unittest.cc
@@ -4,6 +4,7 @@
#include "content/browser/scheduler/browser_ui_thread_scheduler.h"
+#include <memory>
#include <utility>
#include <vector>
@@ -13,25 +14,20 @@
#include "base/task/post_task.h"
#include "base/task/thread_pool/thread_pool.h"
#include "base/test/mock_callback.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/public/browser/browser_task_traits.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
-using ::testing::ElementsAre;
-using ::testing::Invoke;
-using ::testing::Mock;
-
-void RecordRunOrder(std::vector<int>* run_order, int order) {
- run_order->push_back(order);
-}
+using StrictMockTask =
+ testing::StrictMock<base::MockCallback<base::RepeatingCallback<void()>>>;
base::OnceClosure RunOnDestruction(base::OnceClosure task) {
return base::BindOnce(
[](std::unique_ptr<base::ScopedClosureRunner>) {},
- base::Passed(
- std::make_unique<base::ScopedClosureRunner>(std::move(task))));
+ std::make_unique<base::ScopedClosureRunner>(std::move(task)));
}
base::OnceClosure PostOnDestruction(
@@ -42,122 +38,16 @@ base::OnceClosure PostOnDestruction(
scoped_refptr<base::SingleThreadTaskRunner> task_queue) {
task_queue->PostTask(FROM_HERE, std::move(task));
},
- base::Passed(std::move(task)), task_queue));
-}
-
-} // namespace
-
-class BrowserUIThreadSchedulerTest : public testing::Test {
- public:
- BrowserUIThreadSchedulerTest() {
- browser_ui_thread_scheduler_ = std::make_unique<BrowserUIThreadScheduler>();
- for (int i = 0;
- i < static_cast<int>(BrowserUIThreadTaskQueue::QueueType::kCount);
- i++) {
- auto queue_type = static_cast<BrowserUIThreadTaskQueue::QueueType>(i);
- task_runners_.emplace(
- queue_type,
- browser_ui_thread_scheduler_->GetTaskRunnerForTesting(queue_type));
- }
- }
-
- protected:
- using QueueType = BrowserUIThreadScheduler::QueueType;
- using MockTask =
- testing::StrictMock<base::MockCallback<base::RepeatingCallback<void()>>>;
-
- std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler_;
- base::flat_map<BrowserUIThreadScheduler::QueueType,
- scoped_refptr<base::SingleThreadTaskRunner>>
- task_runners_;
-};
-
-TEST_F(BrowserUIThreadSchedulerTest, RunAllPendingTasksForTesting) {
- browser_ui_thread_scheduler_->EnableBestEffortQueues();
- MockTask task_1;
- MockTask task_2;
- EXPECT_CALL(task_1, Run).WillOnce(Invoke([&]() {
- task_runners_[QueueType::kDefault]->PostTask(FROM_HERE, task_2.Get());
- task_runners_[QueueType::kBestEffort]->PostTask(FROM_HERE, task_2.Get());
- }));
-
- task_runners_[QueueType::kDefault]->PostTask(FROM_HERE, task_1.Get());
-
- browser_ui_thread_scheduler_->RunAllPendingTasksForTesting();
-
- Mock::VerifyAndClearExpectations(&task_1);
- EXPECT_CALL(task_2, Run).Times(2);
-
- browser_ui_thread_scheduler_->RunAllPendingTasksForTesting();
-}
-
-TEST_F(BrowserUIThreadSchedulerTest,
- RunAllPendingTasksForTestingIgnoresBestEffortIfNotEnabled) {
- MockTask best_effort_task;
- MockTask default_task;
-
- task_runners_[QueueType::kBestEffort]->PostTask(FROM_HERE,
- best_effort_task.Get());
- task_runners_[QueueType::kDefault]->PostTask(FROM_HERE, default_task.Get());
-
- EXPECT_CALL(default_task, Run);
-
- browser_ui_thread_scheduler_->RunAllPendingTasksForTesting();
-}
-
-TEST_F(BrowserUIThreadSchedulerTest,
- RunAllPendingTasksForTestingRunsBestEffortTasksWhenEnabled) {
- MockTask task_1;
- MockTask task_2;
- MockTask task_3;
- EXPECT_CALL(task_1, Run).WillOnce(Invoke([&]() {
- // This task should not run as it is posted after the
- // RunAllPendingTasksForTesting() call
- task_runners_[QueueType::kBestEffort]->PostTask(FROM_HERE, task_3.Get());
- browser_ui_thread_scheduler_->EnableBestEffortQueues();
- }));
- EXPECT_CALL(task_2, Run);
-
- task_runners_[QueueType::kDefault]->PostTask(FROM_HERE, task_1.Get());
- task_runners_[QueueType::kBestEffort]->PostTask(FROM_HERE, task_2.Get());
-
- browser_ui_thread_scheduler_->RunAllPendingTasksForTesting();
-}
-
-TEST_F(BrowserUIThreadSchedulerTest, RunAllPendingTasksForTestingIsReentrant) {
- MockTask task_1;
- MockTask task_2;
- MockTask task_3;
-
- EXPECT_CALL(task_1, Run).WillOnce(Invoke([&]() {
- task_runners_[QueueType::kDefault]->PostTask(FROM_HERE, task_2.Get());
- browser_ui_thread_scheduler_->RunAllPendingTasksForTesting();
- }));
- EXPECT_CALL(task_2, Run).WillOnce(Invoke([&]() {
- task_runners_[QueueType::kDefault]->PostTask(FROM_HERE, task_3.Get());
- }));
-
- task_runners_[QueueType::kDefault]->PostTask(FROM_HERE, task_1.Get());
- browser_ui_thread_scheduler_->RunAllPendingTasksForTesting();
-}
-
-TEST_F(BrowserUIThreadSchedulerTest, SimplePosting) {
- scoped_refptr<base::SingleThreadTaskRunner> tq =
- task_runners_[QueueType::kDefault];
-
- std::vector<int> order;
- tq->PostTask(FROM_HERE, base::BindOnce(RecordRunOrder, &order, 1));
- tq->PostTask(FROM_HERE, base::BindOnce(RecordRunOrder, &order, 2));
- tq->PostTask(FROM_HERE, base::BindOnce(RecordRunOrder, &order, 3));
-
- base::RunLoop().RunUntilIdle();
-
- EXPECT_THAT(order, ElementsAre(1, 2, 3));
+ std::move(task), task_queue));
}
-TEST_F(BrowserUIThreadSchedulerTest, DestructorPostChainDuringShutdown) {
- scoped_refptr<base::SingleThreadTaskRunner> task_queue =
- task_runners_[QueueType::kDefault];
+TEST(BrowserUIThreadSchedulerTest, DestructorPostChainDuringShutdown) {
+ auto browser_ui_thread_scheduler_ =
+ std::make_unique<BrowserUIThreadScheduler>();
+ browser_ui_thread_scheduler_->GetHandle().EnableAllQueues();
+ auto task_queue =
+ browser_ui_thread_scheduler_->GetHandle().GetBrowserTaskRunner(
+ BrowserUIThreadScheduler::QueueType::kDefault);
bool run = false;
task_queue->PostTask(
@@ -174,4 +64,18 @@ TEST_F(BrowserUIThreadSchedulerTest, DestructorPostChainDuringShutdown) {
EXPECT_TRUE(run);
}
+TEST(BrowserUIThreadSchedulerTest,
+ TaskPostedWithThreadHandleRunBeforeQueuesAreEnabled) {
+ auto browser_ui_thread_scheduler_ =
+ std::make_unique<BrowserUIThreadScheduler>();
+
+ StrictMockTask task;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task.Get());
+
+ EXPECT_CALL(task, Run);
+ base::RunLoop().RunUntilIdle();
+}
+
+} // namespace
+
} // namespace content
diff --git a/chromium/content/browser/scheduler/browser_ui_thread_task_queue.cc b/chromium/content/browser/scheduler/browser_ui_thread_task_queue.cc
deleted file mode 100644
index 3f87e3403de..00000000000
--- a/chromium/content/browser/scheduler/browser_ui_thread_task_queue.cc
+++ /dev/null
@@ -1,42 +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/scheduler/browser_ui_thread_task_queue.h"
-
-#include <utility>
-
-#include "base/task/sequence_manager/task_queue_impl.h"
-
-namespace content {
-
-BrowserUIThreadTaskQueue::BrowserUIThreadTaskQueue(
- std::unique_ptr<base::sequence_manager::internal::TaskQueueImpl> impl,
- const TaskQueue::Spec& spec,
- QueueType queue_type)
- : base::sequence_manager::TaskQueue(std::move(impl), spec),
- queue_type_(queue_type) {}
-
-BrowserUIThreadTaskQueue::~BrowserUIThreadTaskQueue() = default;
-
-// static
-const char* BrowserUIThreadTaskQueue::NameForQueueType(QueueType queue_type) {
- switch (queue_type) {
- case QueueType::kBestEffort:
- return "best_effort_tq";
- case QueueType::kBootstrap:
- return "bootstrap_tq";
- case QueueType::kNavigationAndPreconnection:
- return "navigation_and_preconnection_tq";
- case QueueType::kDefault:
- return "default_tq";
- case QueueType::kUserBlocking:
- return "user_blocking_tq";
- case QueueType::kCount:
- break;
- }
- NOTREACHED();
- return nullptr;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/scheduler/browser_ui_thread_task_queue.h b/chromium/content/browser/scheduler/browser_ui_thread_task_queue.h
deleted file mode 100644
index 389b2888f3a..00000000000
--- a/chromium/content/browser/scheduler/browser_ui_thread_task_queue.h
+++ /dev/null
@@ -1,76 +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_SCHEDULER_BROWSER_UI_THREAD_TASK_QUEUE_H_
-#define CONTENT_BROWSER_SCHEDULER_BROWSER_UI_THREAD_TASK_QUEUE_H_
-
-#include <memory>
-
-#include "base/task/sequence_manager/task_queue.h"
-#include "content/common/content_export.h"
-
-namespace base {
-namespace sequence_manager {
-// TODO(carlscab): Refactor creation of task queues so we don't need to expose
-// the internal namespace.
-namespace internal {
-class TaskQueueImpl;
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
-
-namespace content {
-
-// There are a number of BrowserUIThreadTaskQueues and all UI thread tasks are
-// posted to one of these. The scheduler manipulates these queues in order to
-// implement scheduling policy.
-class CONTENT_EXPORT BrowserUIThreadTaskQueue
- : public base::sequence_manager::TaskQueue {
- public:
- enum class QueueType {
- // Catch all for tasks that don't fit other categories.
- // TODO(alexclarke): Introduce new semantic types as needed to minimize the
- // number of default tasks.
- kDefault,
-
- // For non-urgent work, that will only execute if there's nothing else to
- // do. Can theoretically be starved indefinitely although that's unlikely in
- // practice.
- kBestEffort,
-
- // For tasks on the critical path up to issuing the initial navigation.
- kBootstrap,
-
- // For navigation and preconnection related tasks.
- kNavigationAndPreconnection,
-
- // A generic high priority queue. Long term we should replace this with
- // additional semantic annotations.
- kUserBlocking,
-
- kCount
- };
-
- BrowserUIThreadTaskQueue(
- std::unique_ptr<base::sequence_manager::internal::TaskQueueImpl> impl,
- const TaskQueue::Spec& spec,
- QueueType queue_type);
-
- QueueType queue_type() const { return queue_type_; }
-
- // Returns name of the given queue type. Returned string has application
- // lifetime.
- static const char* NameForQueueType(QueueType queue_type);
-
- private:
- ~BrowserUIThreadTaskQueue() override;
-
- QueueType queue_type_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserUIThreadTaskQueue);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_SCHEDULER_BROWSER_UI_THREAD_TASK_QUEUE_H_
diff --git a/chromium/content/browser/scheduler/responsiveness/watcher.cc b/chromium/content/browser/scheduler/responsiveness/watcher.cc
index 7a6f4cfd236..e0d934b44fd 100644
--- a/chromium/content/browser/scheduler/responsiveness/watcher.cc
+++ b/chromium/content/browser/scheduler/responsiveness/watcher.cc
@@ -14,10 +14,6 @@
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
-#if defined(OS_CHROMEOS)
-#include "ui/base/ui_base_features.h"
-#endif
-
namespace content {
namespace responsiveness {
@@ -192,15 +188,11 @@ void Watcher::DidRunTask(const base::PendingTask* task,
if (UNLIKELY(currently_running_metadata->empty() ||
(task != currently_running_metadata->back().identifier))) {
*mismatched_task_identifiers += 1;
- // Mismatches can happen (e.g: on ChromeOS, with window service when
- // tab-dragging is involved; on ozone/wayland when Paste button is pressed
+ // Mismatches can happen (e.g: on ozone/wayland when Paste button is pressed
// in context menus, among others). Simply ignore the mismatches for now.
// See https://crbug.com/929813 for the details of why the mismatch
- // happens. TODO(mukai): fix the event order issue.
-#if defined(OS_CHROMEOS)
- if (features::IsUsingWindowService())
- return currently_running_metadata_ui_.clear();
-#elif defined(OS_LINUX) && defined(USE_OZONE)
+ // happens.
+#if !defined(OS_CHROMEOS) && defined(OS_LINUX) && defined(USE_OZONE)
return currently_running_metadata_ui_.clear();
#endif
DCHECK_LE(*mismatched_task_identifiers, 1);
@@ -258,15 +250,9 @@ void Watcher::DidRunEventOnUIThread(const void* opaque_identifier) {
(opaque_identifier !=
currently_running_metadata_ui_.back().identifier))) {
mismatched_event_identifiers_ui_ += 1;
- // Mismatches can happen (e.g: on ChromeOS, with window service when
- // tab-dragging is involved; on ozone/wayland when Paste button is pressed
- // in context menus, among others). Simply ignore the mismatches for now.
- // See https://crbug.com/929813 for the details of why the mismatch
- // happens. TODO(mukai): fix the event order issue.
-#if defined(OS_CHROMEOS)
- if (features::IsUsingWindowService())
- return currently_running_metadata_ui_.clear();
-#elif defined(OS_LINUX) && defined(USE_OZONE)
+ // See comment in DidRunTask() for why |currently_running_metadata_ui_| may
+ // be reset.
+#if !defined(OS_CHROMEOS) && defined(OS_LINUX) && defined(USE_OZONE)
return currently_running_metadata_ui_.clear();
#endif
DCHECK_LE(mismatched_event_identifiers_ui_, 1);
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 7f88ed37799..535fd96b10e 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc
+++ b/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc
@@ -4,6 +4,7 @@
#include "content/browser/screen_orientation/screen_orientation_delegate_android.h"
+#include "base/android/scoped_java_ref.h"
#include "content/browser/screen_orientation/screen_orientation_provider.h"
#include "jni/ScreenOrientationProviderImpl_jni.h"
#include "ui/android/window_android.h"
@@ -27,25 +28,33 @@ bool ScreenOrientationDelegateAndroid::FullScreenRequired(
void ScreenOrientationDelegateAndroid::Lock(
WebContents* web_contents,
blink::WebScreenOrientationLockType lock_orientation) {
+ base::android::ScopedJavaLocalRef<jobject> java_instance =
+ Java_ScreenOrientationProviderImpl_getInstance(
+ base::android::AttachCurrentThread());
gfx::NativeWindow window = web_contents->GetTopLevelNativeWindow();
Java_ScreenOrientationProviderImpl_lockOrientation(
- base::android::AttachCurrentThread(),
- window ? window->GetJavaObject() : nullptr,
- lock_orientation);
+ base::android::AttachCurrentThread(), java_instance,
+ window ? window->GetJavaObject() : nullptr, lock_orientation);
}
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.
+ base::android::ScopedJavaLocalRef<jobject> java_instance =
+ Java_ScreenOrientationProviderImpl_getInstance(
+ base::android::AttachCurrentThread());
return Java_ScreenOrientationProviderImpl_isOrientationLockEnabled(
- base::android::AttachCurrentThread());
+ base::android::AttachCurrentThread(), java_instance);
}
void ScreenOrientationDelegateAndroid::Unlock(WebContents* web_contents) {
+ base::android::ScopedJavaLocalRef<jobject> java_instance =
+ Java_ScreenOrientationProviderImpl_getInstance(
+ base::android::AttachCurrentThread());
gfx::NativeWindow window = web_contents->GetTopLevelNativeWindow();
Java_ScreenOrientationProviderImpl_unlockOrientation(
- base::android::AttachCurrentThread(),
+ base::android::AttachCurrentThread(), java_instance,
window ? window->GetJavaObject() : nullptr);
}
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_provider.cc b/chromium/content/browser/screen_orientation/screen_orientation_provider.cc
index 6d2e9140bb5..47cc1210f74 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_provider.cc
+++ b/chromium/content/browser/screen_orientation/screen_orientation_provider.cc
@@ -6,7 +6,6 @@
#include <utility>
-#include "base/callback_helpers.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/navigation_handle.h"
@@ -110,7 +109,7 @@ void ScreenOrientationProvider::OnOrientationChange() {
void ScreenOrientationProvider::NotifyLockResult(
ScreenOrientationLockResult result) {
if (!pending_callback_.is_null())
- base::ResetAndReturn(&pending_callback_).Run(result);
+ std::move(pending_callback_).Run(result);
pending_lock_orientation_.reset();
}
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index d543da021ee..1762c5779ec 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -146,7 +146,7 @@ network::ResourceRequest CreateXHRRequest(const char* url) {
request.load_flags = 0;
request.plugin_child_id = -1;
request.resource_type = static_cast<int>(ResourceType::kXhr);
- request.appcache_host_id = blink::mojom::kAppCacheNoHostId;
+ request.appcache_host_id = base::nullopt;
request.should_reset_appcache = false;
request.is_main_frame = true;
request.transition_type = ui::PAGE_TRANSITION_LINK;
@@ -809,7 +809,6 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
params.disposition = WindowOpenDisposition::CURRENT_TAB;
params.should_replace_current_entry = true;
params.user_gesture = true;
- params.is_history_navigation_in_new_child = false;
FrameHostMsg_OpenURL msg(root->current_frame_host()->routing_id(), params);
IPC::IpcSecurityTestUtil::PwnMessageReceived(
@@ -1095,7 +1094,6 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
params.disposition = WindowOpenDisposition::CURRENT_TAB;
params.should_replace_current_entry = false;
params.user_gesture = true;
- params.is_history_navigation_in_new_child = false;
SiteInstance* a_com_instance = root->current_frame_host()->GetSiteInstance();
RenderFrameProxyHost* proxy =
@@ -1401,7 +1399,9 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
// Have the main frame navigate and lie that the initiator origin is b.com.
injector.Activate();
- EXPECT_TRUE(ExecJs(web_contents, "window.location = '/title2.html';"));
+ // Don't expect a response for the script, as the process may be killed
+ // before the script sends its completion message.
+ ExecuteScriptAsync(web_contents, "window.location = '/title2.html';");
// Verify that the renderer was terminated.
EXPECT_EQ(bad_message::INVALID_INITIATOR_ORIGIN, kill_waiter.Wait());
@@ -1424,13 +1424,71 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
// Have the main frame submit a BeginNavigation IPC with a missing initiator.
injector.Activate();
- EXPECT_TRUE(ExecJs(web_contents, "window.location = '/title2.html';"));
+ // Don't expect a response for the script, as the process may be killed
+ // before the script sends its completion message.
+ ExecuteScriptAsync(web_contents, "window.location = '/title2.html';");
// Verify that the renderer was terminated.
EXPECT_EQ(bad_message::RFHI_BEGIN_NAVIGATION_MISSING_INITIATOR_ORIGIN,
kill_waiter.Wait());
}
+namespace {
+
+// An interceptor class that allows replacing the URL of the commit IPC from
+// the renderer process to the browser process.
+class DidCommitUrlReplacer : public DidCommitNavigationInterceptor {
+ public:
+ DidCommitUrlReplacer(WebContents* web_contents, const GURL& replacement_url)
+ : DidCommitNavigationInterceptor(web_contents),
+ replacement_url_(replacement_url) {}
+ ~DidCommitUrlReplacer() override = default;
+
+ protected:
+ bool WillProcessDidCommitNavigation(
+ RenderFrameHost* render_frame_host,
+ NavigationRequest* navigation_request,
+ ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
+ mojom::DidCommitProvisionalLoadInterfaceParamsPtr* interface_params)
+ override {
+ params->url = replacement_url_;
+ return true;
+ }
+
+ private:
+ GURL replacement_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(DidCommitUrlReplacer);
+};
+
+} // namespace
+
+// Test which verifies that when an exploited renderer process sends a commit
+// message with URL that the process is not allowed to commit.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, DidCommitInvalidURL) {
+ // Explicitly isolating foo.com helps ensure that this test is applicable on
+ // platforms without site-per-process.
+ IsolateOrigin("foo.com");
+
+ // Navigate to foo.com initially.
+ GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), foo_url));
+
+ // Create the interceptor object which will replace the URL of the subsequent
+ // navigation with bar.com based URL.
+ GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title3.html"));
+ DidCommitUrlReplacer url_replacer(shell()->web_contents(), bar_url);
+
+ // Navigate to another URL within foo.com, which would usually be committed
+ // succsesfuly, but when the URL is modified it should result in the
+ // termination of the renderer process.
+ RenderProcessHostKillWaiter kill_waiter(
+ shell()->web_contents()->GetMainFrame()->GetProcess());
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL("foo.com", "/title2.html"));
+ EXPECT_EQ(bad_message::RFH_CAN_COMMIT_URL_BLOCKED, kill_waiter.Wait());
+}
+
class BeginNavigationTransitionReplacer : public FrameHostInterceptor {
public:
BeginNavigationTransitionReplacer(WebContents* web_contents,
@@ -1491,7 +1549,9 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, NonWebbyTransition) {
// Have the main frame submit a BeginNavigation IPC with a missing
// initiator.
injector.Activate();
- EXPECT_TRUE(ExecJs(web_contents, "window.location = '/title2.html';"));
+ // Don't expect a response for the script, as the process may be killed
+ // before the script sends its completion message.
+ ExecuteScriptAsync(web_contents, "window.location = '/title2.html';");
// Verify that the renderer was terminated.
EXPECT_EQ(bad_message::RFHI_BEGIN_NAVIGATION_NON_WEBBY_TRANSITION,
diff --git a/chromium/content/browser/serial/serial_browsertest.cc b/chromium/content/browser/serial/serial_browsertest.cc
index 9c6c33686c3..e59042d93f0 100644
--- a/chromium/content/browser/serial/serial_browsertest.cc
+++ b/chromium/content/browser/serial/serial_browsertest.cc
@@ -11,6 +11,7 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/serial_chooser.h"
#include "content/public/browser/serial_delegate.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"
@@ -21,6 +22,7 @@
using testing::_;
using testing::ByMove;
+using testing::Exactly;
using testing::Return;
namespace content {
@@ -37,7 +39,8 @@ class SerialTest : public ContentBrowserTest {
void SetUpCommandLine(base::CommandLine* command_line) override {
ContentBrowserTest::SetUpCommandLine(command_line);
- command_line->AppendSwitchASCII("enable-blink-features", "Serial");
+ command_line->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
}
void SetUpOnMainThread() override {
@@ -83,6 +86,8 @@ IN_PROC_BROWSER_TEST_F(SerialTest, GetPorts) {
IN_PROC_BROWSER_TEST_F(SerialTest, RequestPort) {
NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html"));
+ EXPECT_CALL(delegate(), CanRequestPortPermission).WillOnce(Return(true));
+
auto port = device::mojom::SerialPortInfo::New();
port->token = base::UnguessableToken::Create();
EXPECT_CALL(delegate(), RunChooserInternal)
@@ -95,4 +100,21 @@ IN_PROC_BROWSER_TEST_F(SerialTest, RequestPort) {
})())"));
}
+IN_PROC_BROWSER_TEST_F(SerialTest, DisallowRequestPort) {
+ NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html"));
+
+ EXPECT_CALL(delegate(), CanRequestPortPermission(_)).WillOnce(Return(false));
+ EXPECT_CALL(delegate(), RunChooserInternal).Times(Exactly(0));
+
+ EXPECT_EQ(false, EvalJs(shell(),
+ R"((async () => {
+ try {
+ await navigator.serial.requestPort({});
+ return true;
+ } catch (e) {
+ return false;
+ }
+ })())"));
+}
+
} // namespace content
diff --git a/chromium/content/browser/serial/serial_service.cc b/chromium/content/browser/serial/serial_service.cc
index e4b7c9d0e8a..0241fb004aa 100644
--- a/chromium/content/browser/serial/serial_service.cc
+++ b/chromium/content/browser/serial/serial_service.cc
@@ -76,6 +76,11 @@ void SerialService::RequestPort(
return;
}
+ if (!delegate->CanRequestPortPermission(render_frame_host_)) {
+ std::move(callback).Run(nullptr);
+ return;
+ }
+
chooser_ = delegate->RunChooser(
render_frame_host_, std::move(filters),
base::BindOnce(&SerialService::FinishRequestPort,
diff --git a/chromium/content/browser/serial/serial_test_utils.h b/chromium/content/browser/serial/serial_test_utils.h
index cdc08c6afc1..371a4b0f593 100644
--- a/chromium/content/browser/serial/serial_test_utils.h
+++ b/chromium/content/browser/serial/serial_test_utils.h
@@ -22,6 +22,7 @@ class MockSerialDelegate : public SerialDelegate {
SerialChooser::Callback callback) override;
MOCK_METHOD0(RunChooserInternal, device::mojom::SerialPortInfoPtr());
+ MOCK_METHOD1(CanRequestPortPermission, bool(RenderFrameHost* frame));
MOCK_METHOD2(HasPortPermission,
bool(content::RenderFrameHost* frame,
const device::mojom::SerialPortInfo& port));
diff --git a/chromium/content/browser/serial/serial_unittest.cc b/chromium/content/browser/serial/serial_unittest.cc
index c29428dd52d..a1bf5837c8d 100644
--- a/chromium/content/browser/serial/serial_unittest.cc
+++ b/chromium/content/browser/serial/serial_unittest.cc
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/command_line.h"
#include "content/browser/serial/serial_test_utils.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/content_switches.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "services/device/public/cpp/test/fake_serial_port_manager.h"
@@ -27,6 +29,8 @@ class SerialTest : public RenderViewHostImplTestHarness {
~SerialTest() override = default;
void SetUp() override {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
original_client_ = SetBrowserClientForTesting(&test_client_);
RenderViewHostTestHarness::SetUp();
}
diff --git a/chromium/content/browser/service_manager/common_browser_interfaces.cc b/chromium/content/browser/service_manager/common_browser_interfaces.cc
index 0a2112b6def..91716b6f9a1 100644
--- a/chromium/content/browser/service_manager/common_browser_interfaces.cc
+++ b/chromium/content/browser/service_manager/common_browser_interfaces.cc
@@ -28,7 +28,6 @@
#include "mojo/public/cpp/bindings/interface_request.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/ws/public/mojom/gpu.mojom.h"
-#include "ui/base/ui_base_features.h"
#if defined(OS_WIN)
#include "content/browser/renderer_host/dwrite_font_proxy_impl_win.h"
@@ -55,21 +54,19 @@ class ConnectionFilterImpl : public ConnectionFilter {
base::BindRepeating(&SandboxSupportMacImpl::BindRequest,
base::Owned(new SandboxSupportMacImpl)));
#endif
- if (!features::IsMultiProcessMash()) {
- // 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();
- if (browser_main_loop) {
- auto* manager = browser_main_loop->discardable_shared_memory_manager();
- if (manager) {
- registry_.AddInterface(base::BindRepeating(
- &discardable_memory::DiscardableSharedMemoryManager::Bind,
- base::Unretained(manager)));
- }
+ // 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();
+ if (browser_main_loop) {
+ auto* manager = browser_main_loop->discardable_shared_memory_manager();
+ if (manager) {
+ registry_.AddInterface(base::BindRepeating(
+ &discardable_memory::DiscardableSharedMemoryManager::Bind,
+ base::Unretained(manager)));
}
- registry_.AddInterface(base::BindRepeating(
- &ConnectionFilterImpl::BindGpuRequest, base::Unretained(this)));
}
+ registry_.AddInterface(base::BindRepeating(
+ &ConnectionFilterImpl::BindGpuRequest, base::Unretained(this)));
}
~ConnectionFilterImpl() override { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
@@ -124,16 +121,6 @@ class ConnectionFilterImpl : public ConnectionFilter {
gpu_clients_.erase(service_identity);
}
- template <typename Interface>
- static void BindOnTaskRunner(
- const scoped_refptr<base::TaskRunner>& task_runner,
- const InterfaceBinder<Interface>& binder,
- mojo::InterfaceRequest<Interface> request,
- const service_manager::BindSourceInfo& source_info) {
- task_runner->PostTask(
- FROM_HERE, base::BindOnce(binder, std::move(request), source_info));
- }
-
service_manager::BinderRegistryWithArgs<
const service_manager::BindSourceInfo&>
registry_;
diff --git a/chromium/content/browser/service_manager/service_manager_context.cc b/chromium/content/browser/service_manager/service_manager_context.cc
index 28b8075b3ae..2f00ec042d5 100644
--- a/chromium/content/browser/service_manager/service_manager_context.cc
+++ b/chromium/content/browser/service_manager/service_manager_context.cc
@@ -19,6 +19,7 @@
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/no_destructor.h"
+#include "base/optional.h"
#include "base/process/process_handle.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
@@ -27,6 +28,7 @@
#include "build/build_config.h"
#include "content/app/strings/grit/content_strings.h"
#include "content/browser/browser_main_loop.h"
+#include "content/browser/builtin_service_manifests.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/service_manager/common_browser_interfaces.h"
@@ -35,11 +37,6 @@
#include "content/browser/wake_lock/wake_lock_context_host.h"
#include "content/common/service_manager/service_manager_connection_impl.h"
#include "content/public/app/content_browser_manifest.h"
-#include "content/public/app/content_gpu_manifest.h"
-#include "content/public/app/content_packaged_services_manifest.h"
-#include "content/public/app/content_plugin_manifest.h"
-#include "content/public/app/content_renderer_manifest.h"
-#include "content/public/app/content_utility_manifest.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
@@ -56,6 +53,7 @@
#include "media/media_buildflags.h"
#include "media/mojo/buildflags.h"
#include "media/mojo/interfaces/constants.mojom.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/invitation.h"
#include "services/audio/public/mojom/constants.mojom.h"
@@ -72,9 +70,9 @@
#include "services/network/public/cpp/cross_thread_shared_url_loader_factory_info.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/network_service_test.mojom.h"
+#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
#include "services/resource_coordinator/resource_coordinator_service.h"
-#include "services/service_manager/connect_params.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/constants.h"
#include "services/service_manager/public/cpp/manifest.h"
@@ -82,6 +80,7 @@
#include "services/service_manager/public/mojom/service.mojom.h"
#include "services/service_manager/sandbox/sandbox_type.h"
#include "services/service_manager/service_manager.h"
+#include "services/service_manager/service_process_host.h"
#include "services/service_manager/service_process_launcher.h"
#include "services/shape_detection/public/mojom/constants.mojom.h"
#include "services/tracing/public/cpp/tracing_features.h"
@@ -101,7 +100,7 @@
#if defined(OS_LINUX)
#include "components/services/font/font_service_app.h"
-#include "components/services/font/public/interfaces/constants.mojom.h"
+#include "components/services/font/public/interfaces/constants.mojom.h" // nogncheck
#endif
#if defined(OS_CHROMEOS)
@@ -135,136 +134,93 @@ const base::Feature kNetworkServiceDedicatedThread{
#endif
};
-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 ContentBrowserClient::ProcessNameCallback& process_name_callback,
- base::Optional<std::string> process_group,
- service_manager::mojom::ServiceRequest request,
- service_manager::Service::CreatePackagedServiceInstanceCallback callback,
- service_manager::mojom::ServiceInfoPtr service_info) {
- DCHECK(service_info);
- service_manager::SandboxType sandbox_type =
- service_manager::UtilitySandboxTypeFromString(service_info->sandbox_type);
-
- // Look for an existing process group.
- base::WeakPtr<UtilityProcessHost>* weak_host = nullptr;
- if (process_group)
- weak_host = &g_active_process_groups.Get()[*process_group];
-
- UtilityProcessHost* process_host = nullptr;
- if (weak_host && *weak_host) {
- // Start service in an existing process.
- process_host = weak_host->get();
- } 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);
- // NOTE: This is not the service instance's real Identity. For all current
- // practical purposes however, only the name is relevant.
- impl->SetServiceIdentity(service_manager::Identity(
- service_name, service_manager::kSystemInstanceGroup, base::Token{},
- base::Token{1, 1}));
- impl->SetSandboxType(sandbox_type);
- impl->Start();
- if (weak_host)
- *weak_host = impl->AsWeakPtr();
- process_host = impl;
- }
-
- process_host->RunService(
- service_name,
- mojo::PendingReceiver<service_manager::mojom::Service>(
- request.PassMessagePipe()),
- std::move(callback));
+service_manager::Manifest GetContentSystemManifest() {
+ // TODO(https://crbug.com/961869): This is a bit of a temporary hack so that
+ // we can make the global service instance a singleton. For now we just mirror
+ // the per-BrowserContext manifest (formerly also used for the global
+ // singleton instance), sans packaged services, since those are only meant to
+ // be tied to a BrowserContext. The per-BrowserContext service should go away
+ // soon, and then this can be removed.
+ service_manager::Manifest manifest = GetContentBrowserManifest();
+ manifest.Amend(GetContentClient()
+ ->browser()
+ ->GetServiceManifestOverlay(mojom::kBrowserServiceName)
+ .value_or(service_manager::Manifest()));
+ manifest.service_name = mojom::kSystemServiceName;
+ manifest.packaged_services.clear();
+ manifest.options.instance_sharing_policy =
+ service_manager::Manifest::InstanceSharingPolicy::kSingleton;
+ return manifest;
}
-// Determine a sandbox type for a service and launch a process for it.
-void QueryAndStartServiceInUtilityProcess(
- const std::string& service_name,
- const ContentBrowserClient::ProcessNameCallback& process_name_callback,
- base::Optional<std::string> process_group,
- service_manager::mojom::ServiceRequest request,
- service_manager::Service::CreatePackagedServiceInstanceCallback callback) {
- ServiceManagerContext::GetConnectorForIOThread()->QueryService(
- service_name,
- base::BindOnce(&StartServiceInUtilityProcess, service_name,
- process_name_callback, std::move(process_group),
- std::move(request), std::move(callback)));
-}
-
-// Send a RunService request through the GpuProcessHost.
-void StartServiceInGpuProcess(
- const std::string& service_name,
- service_manager::mojom::ServiceRequest request,
- service_manager::Service::CreatePackagedServiceInstanceCallback callback) {
- GpuProcessHost* process_host = GpuProcessHost::Get();
- if (!process_host) {
- DLOG(ERROR) << "GPU process host not available.";
- return;
- }
-
- // TODO(xhwang): It's possible that |process_host| is non-null, but the actual
- // process is dead. In that case, |request| will be dropped and application
- // load requests through ServiceFactory will also fail. Make sure we handle
- // these cases correctly.
- process_host->gpu_host()->RunService(
- service_name, mojo::PendingReceiver<service_manager::mojom::Service>(
- request.PassMessagePipe()));
- std::move(callback).Run(base::nullopt);
-}
+void DestroyConnectorOnIOThread() { g_io_thread_connector.Get().reset(); }
-class NullServiceProcessLauncherFactory
- : public service_manager::ServiceProcessLauncherFactory {
+// A ServiceProcessHost implementation which delegates to Content-managed
+// processes, either via a new UtilityProcessHost to launch new service
+// processes, or the existing GpuProcessHost to run service instances in the GPU
+// process.
+class ContentChildServiceProcessHost
+ : public service_manager::ServiceProcessHost {
public:
- NullServiceProcessLauncherFactory() {}
- ~NullServiceProcessLauncherFactory() override {}
+ ContentChildServiceProcessHost(bool run_in_gpu_process,
+ base::Optional<int> child_flags)
+ : run_in_gpu_process_(run_in_gpu_process), child_flags_(child_flags) {}
+ ~ContentChildServiceProcessHost() override = default;
+
+ // service_manager::ServiceProcessHost:
+ mojo::PendingRemote<service_manager::mojom::Service> Launch(
+ const service_manager::Identity& identity,
+ service_manager::SandboxType sandbox_type,
+ const base::string16& display_name,
+ LaunchCallback callback) override {
+ mojo::PendingRemote<service_manager::mojom::Service> remote;
+ auto receiver = remote.InitWithNewPipeAndPassReceiver();
+ if (run_in_gpu_process_) {
+ // TODO(https://crbug.com/781334): Services running in the GPU process
+ // should be packaged into the content_gpu manifest. Then this would be
+ // unnecessary.
+ GpuProcessHost* process_host = GpuProcessHost::Get();
+ if (!process_host) {
+ DLOG(ERROR) << "GPU process host not available.";
+ return mojo::NullRemote();
+ }
- private:
- std::unique_ptr<service_manager::ServiceProcessLauncher> Create(
- const base::FilePath& service_path) override {
- // 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();
+ // TODO(xhwang): It's possible that |process_host| is non-null, but the
+ // actual process is dead. In that case the receiver will be dropped. Make
+ // sure we handle these cases correctly.
+ process_host->gpu_host()->RunService(identity.name(),
+ std::move(receiver));
+ base::ProcessId process_id = process_host->process_id();
+ std::move(callback).Run(process_id != base::kNullProcessId
+ ? process_id
+ : base::GetCurrentProcId());
+ return remote;
}
- return nullptr;
- }
- DISALLOW_COPY_AND_ASSIGN(NullServiceProcessLauncherFactory);
-};
-
-// This class is intended for tests that want to load service binaries (rather
-// than via the utility process). Production code uses
-// NullServiceProcessLauncherFactory.
-class ServiceBinaryLauncherFactory
- : public service_manager::ServiceProcessLauncherFactory {
- public:
- ServiceBinaryLauncherFactory() = default;
- ~ServiceBinaryLauncherFactory() override = default;
-
- private:
- std::unique_ptr<service_manager::ServiceProcessLauncher> Create(
- const base::FilePath& service_path) override {
- return std::make_unique<service_manager::ServiceProcessLauncher>(
- nullptr, service_path);
+ // Start a new process for this service.
+ UtilityProcessHost* process_host = new UtilityProcessHost(nullptr, nullptr);
+ process_host->SetName(display_name);
+ process_host->SetMetricsName(identity.name());
+ process_host->SetServiceIdentity(identity);
+ process_host->SetSandboxType(sandbox_type);
+ if (child_flags_.has_value())
+ process_host->set_child_flags(child_flags_.value());
+ process_host->Start();
+ process_host->RunService(
+ identity.name(), std::move(receiver),
+ base::BindOnce(
+ [](LaunchCallback callback,
+ const base::Optional<base::ProcessId> pid) {
+ std::move(callback).Run(pid.value_or(base::kNullProcessId));
+ },
+ std::move(callback)));
+ return remote;
}
- DISALLOW_COPY_AND_ASSIGN(ServiceBinaryLauncherFactory);
+ private:
+ const bool run_in_gpu_process_;
+ const base::Optional<int> child_flags_;
+ DISALLOW_COPY_AND_ASSIGN(ContentChildServiceProcessHost);
};
// SharedURLLoaderFactory for device service, backed by
@@ -346,14 +302,22 @@ void LaunchInProcessService(
std::move(request)));
}
+// Temporary helper to reduce churn when moving away from Content packaged
+// services.
+using InProcessServiceMap = std::map<
+ std::string,
+ base::RepeatingCallback<void(service_manager::mojom::ServiceRequest)>>;
+InProcessServiceMap& GetInProcessServiceMap() {
+ static base::NoDestructor<InProcessServiceMap> services;
+ return *services;
+}
+
void RegisterInProcessService(
- ServiceManagerConnection* connection,
const std::string& service_name,
scoped_refptr<base::SequencedTaskRunner> task_runner,
const InProcessServiceFactory& factory) {
- connection->AddServiceRequestHandler(
- service_name,
- base::BindRepeating(&LaunchInProcessService, task_runner, factory));
+ GetInProcessServiceMap()[service_name] = base::BindRepeating(
+ &LaunchInProcessService, std::move(task_runner), factory);
}
std::unique_ptr<service_manager::Service> CreateVideoCaptureService(
@@ -402,6 +366,133 @@ std::unique_ptr<service_manager::Service> CreateMediaSessionService(
std::move(request));
}
+void RunServiceInstanceOnIOThread(
+ const service_manager::Identity& identity,
+ mojo::PendingReceiver<service_manager::mojom::Service>* receiver) {
+ if (!AudioServiceOutOfProcess() &&
+ identity.name() == audio::mojom::kServiceName) {
+ CreateInProcessAudioService(ServiceManagerContext::GetAudioServiceRunner(),
+ std::move(*receiver));
+ return;
+ }
+
+ GetContentClient()->browser()->RunServiceInstanceOnIOThread(identity,
+ receiver);
+}
+
+// A ServiceProcessHost implementation which uses the Service Manager's builtin
+// service executable launcher. Not yet intended for use in production Chrome,
+// hence availability is gated behind a flag.
+class ServiceExecutableProcessHost
+ : public service_manager::ServiceProcessHost {
+ public:
+ explicit ServiceExecutableProcessHost(const base::FilePath& executable_path)
+ : launcher_(nullptr, executable_path) {}
+ ~ServiceExecutableProcessHost() override = default;
+
+ // service_manager::ServiceProcessHost:
+ mojo::PendingRemote<service_manager::mojom::Service> Launch(
+ const service_manager::Identity& identity,
+ service_manager::SandboxType sandbox_type,
+ const base::string16& display_name,
+ LaunchCallback callback) override {
+ // TODO(https://crbug.com/781334): Support sandboxing.
+ return launcher_
+ .Start(identity, service_manager::SANDBOX_TYPE_NO_SANDBOX,
+ std::move(callback))
+ .PassInterface();
+ }
+
+ private:
+ service_manager::ServiceProcessLauncher launcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceExecutableProcessHost);
+};
+
+using ServiceRequestHandler = base::RepeatingCallback<void(
+ const service_manager::Identity& identity,
+ mojo::PendingReceiver<service_manager::mojom::Service> receiver)>;
+
+// Implements in- and out-of-process service instance launching for services
+// built into the Content embedder's binary.
+//
+// All methods on this object (except the constructor) are called on the Service
+// Manager's thread, which is effectively the browser's IO thread.
+class BrowserServiceManagerDelegate
+ : public service_manager::ServiceManager::Delegate {
+ public:
+ BrowserServiceManagerDelegate(
+ const scoped_refptr<base::SequencedTaskRunner>& main_thread_task_runner,
+ ServiceRequestHandler main_thread_request_handler)
+ : main_thread_task_runner_(main_thread_task_runner),
+ main_thread_request_handler_(std::move(main_thread_request_handler)) {}
+ ~BrowserServiceManagerDelegate() override = default;
+
+ // service_manager::ServiceManager::Delegate:
+ bool RunBuiltinServiceInstanceInCurrentProcess(
+ const service_manager::Identity& identity,
+ mojo::PendingReceiver<service_manager::mojom::Service> receiver)
+ override {
+ const auto& service_map = GetInProcessServiceMap();
+ auto it = service_map.find(identity.name());
+ if (it != service_map.end()) {
+ it->second.Run(std::move(receiver));
+ return true;
+ }
+
+ RunServiceInstanceOnIOThread(identity, &receiver);
+ if (!receiver)
+ return true;
+
+ main_thread_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(main_thread_request_handler_, identity,
+ std::move(receiver)));
+ return true;
+ }
+
+ std::unique_ptr<service_manager::ServiceProcessHost>
+ CreateProcessHostForBuiltinServiceInstance(
+ const service_manager::Identity& identity) override {
+ // TODO(crbug.com/895615): Package these services in content_gpu instead
+ // of using this hack.
+ bool run_in_gpu_process = false;
+ base::Optional<int> child_flags;
+#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
+ if (identity.name() == media::mojom::kMediaServiceName)
+ run_in_gpu_process = true;
+#endif
+ if (identity.name() == shape_detection::mojom::kServiceName)
+ run_in_gpu_process = true;
+#if defined(OS_MACOSX)
+ // The proxy_resolver service runs V8, so it needs to run in the helper
+ // application that has the com.apple.security.cs.allow-jit code signing
+ // entitlement, which is CHILD_RENDERER. The service still runs under the
+ // utility process sandbox.
+ if (identity.name() == proxy_resolver::mojom::kProxyResolverServiceName)
+ child_flags = ChildProcessHost::CHILD_RENDERER;
+#endif
+ return std::make_unique<ContentChildServiceProcessHost>(run_in_gpu_process,
+ child_flags);
+ }
+
+ std::unique_ptr<service_manager::ServiceProcessHost>
+ CreateProcessHostForServiceExecutable(
+ const base::FilePath& executable_path) override {
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableServiceBinaryLauncher)) {
+ return nullptr;
+ }
+
+ return std::make_unique<ServiceExecutableProcessHost>(executable_path);
+ }
+
+ private:
+ const scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_;
+ const ServiceRequestHandler main_thread_request_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserServiceManagerDelegate);
+};
+
} // namespace
// State which lives on the IO thread and drives the ServiceManager.
@@ -413,15 +504,15 @@ class ServiceManagerContext::InProcessServiceManagerContext
: service_manager_thread_task_runner_(
service_manager_thread_task_runner) {}
- void Start(
- service_manager::mojom::ServicePtrInfo packaged_services_service_info,
- std::vector<service_manager::Manifest> manifests) {
+ void Start(std::vector<service_manager::Manifest> manifests,
+ mojo::PendingRemote<service_manager::mojom::Service> system_remote,
+ ServiceRequestHandler request_handler) {
service_manager_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&InProcessServiceManagerContext::StartOnServiceManagerThread, this,
- std::move(manifests), std::move(packaged_services_service_info),
- base::ThreadTaskRunnerHandle::Get()));
+ std::move(manifests), base::ThreadTaskRunnerHandle::Get(),
+ std::move(system_remote), std::move(request_handler)));
}
void ShutDown() {
@@ -446,28 +537,22 @@ class ServiceManagerContext::InProcessServiceManagerContext
void StartOnServiceManagerThread(
std::vector<service_manager::Manifest> manifests,
- service_manager::mojom::ServicePtrInfo packaged_services_service_info,
- scoped_refptr<base::SequencedTaskRunner> ui_thread_task_runner) {
- std::unique_ptr<service_manager::ServiceProcessLauncherFactory>
- service_process_launcher_factory;
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableServiceBinaryLauncher)) {
- service_process_launcher_factory =
- std::make_unique<ServiceBinaryLauncherFactory>();
- } else {
- service_process_launcher_factory =
- std::make_unique<NullServiceProcessLauncherFactory>();
- }
+ scoped_refptr<base::SequencedTaskRunner> ui_thread_task_runner,
+ mojo::PendingRemote<service_manager::mojom::Service> system_remote,
+ ServiceRequestHandler request_handler) {
service_manager_ = std::make_unique<service_manager::ServiceManager>(
- std::move(service_process_launcher_factory), std::move(manifests));
+ std::move(manifests),
+ std::make_unique<BrowserServiceManagerDelegate>(
+ ui_thread_task_runner, std::move(request_handler)));
- service_manager::mojom::ServicePtr packaged_services_service;
- packaged_services_service.Bind(std::move(packaged_services_service_info));
+ mojo::Remote<service_manager::mojom::ProcessMetadata> metadata;
service_manager_->RegisterService(
- service_manager::Identity(mojom::kPackagedServicesServiceName,
+ service_manager::Identity(mojom::kSystemServiceName,
service_manager::kSystemInstanceGroup,
base::Token{}, base::Token::CreateRandom()),
- std::move(packaged_services_service), nullptr);
+ std::move(system_remote), metadata.BindNewPipeAndPassReceiver());
+ metadata->SetPID(base::GetCurrentProcId());
+
service_manager_->SetInstanceQuitCallback(
base::Bind(&OnInstanceQuitOnServiceManagerThread,
std::move(ui_thread_task_runner)));
@@ -493,6 +578,7 @@ class ServiceManagerContext::InProcessServiceManagerContext
void ShutDownOnServiceManagerThread() {
service_manager_.reset();
+ GetInProcessServiceMap().clear();
}
void StartServicesOnServiceManagerThread(
@@ -504,7 +590,7 @@ class ServiceManagerContext::InProcessServiceManagerContext
service_manager_->StartService(service_name);
}
- scoped_refptr<base::SingleThreadTaskRunner>
+ const scoped_refptr<base::SingleThreadTaskRunner>
service_manager_thread_task_runner_;
std::unique_ptr<service_manager::ServiceManager> service_manager_;
@@ -519,11 +605,9 @@ ServiceManagerContext::ServiceManagerContext(
// The |service_manager_thread_task_runner_| must have been created before
// starting the ServiceManager.
DCHECK(service_manager_thread_task_runner_);
- std::vector<service_manager::Manifest> manifests{
- GetContentBrowserManifest(), GetContentGpuManifest(),
- GetContentPackagedServicesManifest(), GetContentPluginManifest(),
- GetContentRendererManifest(), GetContentUtilityManifest(),
- };
+ std::vector<service_manager::Manifest> manifests =
+ GetBuiltinServiceManifests();
+ manifests.push_back(GetContentSystemManifest());
for (auto& manifest : manifests) {
base::Optional<service_manager::Manifest> overlay =
GetContentClient()->browser()->GetServiceManifestOverlay(
@@ -545,55 +629,31 @@ ServiceManagerContext::ServiceManagerContext(
in_process_context_ =
new InProcessServiceManagerContext(service_manager_thread_task_runner_);
- service_manager::mojom::ServicePtr packaged_services_service;
- service_manager::mojom::ServiceRequest packaged_services_request =
- mojo::MakeRequest(&packaged_services_service);
- in_process_context_->Start(packaged_services_service.PassInterface(),
- std::move(manifests));
-
- packaged_services_connection_ =
- ServiceManagerConnection::Create(std::move(packaged_services_request),
- service_manager_thread_task_runner_);
- packaged_services_connection_->SetDefaultServiceRequestHandler(
- base::BindRepeating(&ServiceManagerContext::OnUnhandledServiceRequest,
- weak_ptr_factory_.GetWeakPtr()));
-
- service_manager::mojom::ServicePtr root_browser_service;
- 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;
- packaged_services_connection_->GetConnector()->RegisterServiceInstance(
- service_manager::Identity(mojom::kBrowserServiceName,
- service_manager::kSystemInstanceGroup,
- base::Token{}, base::Token::CreateRandom()),
- std::move(root_browser_service), mojo::MakeRequest(&pid_receiver));
- pid_receiver->SetPID(base::GetCurrentProcId());
+ mojo::PendingRemote<service_manager::mojom::Service> system_remote;
+ ServiceManagerConnection::SetForProcess(ServiceManagerConnection::Create(
+ system_remote.InitWithNewPipeAndPassReceiver(),
+ service_manager_thread_task_runner_));
+ auto* system_connection = ServiceManagerConnection::GetForProcess();
RegisterInProcessService(
- packaged_services_connection_.get(),
resource_coordinator::mojom::kServiceName,
service_manager_thread_task_runner_,
base::BindRepeating(&CreateResourceCoordinatorService));
- RegisterInProcessService(packaged_services_connection_.get(),
- metrics::mojom::kMetricsServiceName,
+ RegisterInProcessService(metrics::mojom::kMetricsServiceName,
service_manager_thread_task_runner_,
base::BindRepeating(&metrics::CreateMetricsService));
if (base::FeatureList::IsEnabled(
media_session::features::kMediaSessionService)) {
- RegisterInProcessService(packaged_services_connection_.get(),
- media_session::mojom::kServiceName,
+ RegisterInProcessService(media_session::mojom::kServiceName,
base::SequencedTaskRunnerHandle::Get(),
base::BindRepeating(&CreateMediaSessionService));
}
if (features::IsVideoCaptureServiceEnabledForBrowserProcess()) {
RegisterInProcessService(
- packaged_services_connection_.get(), video_capture::mojom::kServiceName,
+ video_capture::mojom::kServiceName,
#if defined(OS_WIN)
base::CreateCOMSTATaskRunnerWithTraits(
#else
@@ -607,41 +667,30 @@ ServiceManagerContext::ServiceManagerContext(
#if defined(OS_LINUX)
RegisterInProcessService(
- packaged_services_connection_.get(), font_service::mojom::kServiceName,
+ font_service::mojom::kServiceName,
base::CreateSequencedTaskRunnerWithTraits(
base::TaskTraits({base::MayBlock(), base::WithBaseSyncPrimitives(),
base::TaskPriority::USER_BLOCKING})),
base::BindRepeating(&CreateFontService));
#endif
- GetContentClient()->browser()->RegisterIOThreadServiceHandlers(
- packaged_services_connection_.get());
-
// This is safe to assign directly from any thread, because
// ServiceManagerContext must be constructed before anyone can call
// GetConnectorForIOThread().
- g_io_thread_connector.Get() = browser_connection->GetConnector()->Clone();
+ g_io_thread_connector.Get() = system_connection->GetConnector()->Clone();
- ContentBrowserClient::OutOfProcessServiceMap out_of_process_services;
- GetContentClient()->browser()->RegisterOutOfProcessServices(
- &out_of_process_services);
+ GetContentClient()->browser()->WillStartServiceManager();
if (base::FeatureList::IsEnabled(features::kTracingServiceInProcess)) {
RegisterInProcessService(
- packaged_services_connection_.get(), tracing::mojom::kServiceName,
+ tracing::mojom::kServiceName,
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
base::WithBaseSyncPrimitives(),
base::TaskPriority::USER_BLOCKING}),
base::BindRepeating(&CreateTracingService));
- } else {
- out_of_process_services[tracing::mojom::kServiceName] =
- base::BindRepeating(&base::ASCIIToUTF16, "Tracing Service");
}
- out_of_process_services[data_decoder::mojom::kServiceName] =
- base::BindRepeating(&base::ASCIIToUTF16, "Data Decoder Service");
-
bool network_service_enabled =
base::FeatureList::IsEnabled(network::features::kNetworkService);
if (network_service_enabled) {
@@ -655,76 +704,15 @@ ServiceManagerContext::ServiceManagerContext(
}
GetNetworkTaskRunner()->StartWithTaskRunner(task_runner);
- RegisterInProcessService(packaged_services_connection_.get(),
- mojom::kNetworkServiceName, task_runner,
+ RegisterInProcessService(mojom::kNetworkServiceName, task_runner,
base::BindRepeating(&CreateNetworkService));
- } else {
- out_of_process_services[mojom::kNetworkServiceName] =
- base::BindRepeating(&base::ASCIIToUTF16, "Network Service");
}
}
- if (AudioServiceOutOfProcess()) {
- DCHECK(base::FeatureList::IsEnabled(features::kAudioServiceAudioStreams));
- out_of_process_services[audio::mojom::kServiceName] =
- base::BindRepeating(&base::ASCIIToUTF16, "Audio Service");
- } else {
- packaged_services_connection_->AddServiceRequestHandler(
- audio::mojom::kServiceName,
- base::BindRepeating(&CreateInProcessAudioService,
- base::WrapRefCounted(GetAudioServiceRunner())));
- }
-
- if (features::IsVideoCaptureServiceEnabledForOutOfProcess()) {
- out_of_process_services[video_capture::mojom::kServiceName] =
- base::BindRepeating(&base::ASCIIToUTF16, "Video Capture Service");
- }
-
-#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_UTILITY_PROCESS)
- out_of_process_services[media::mojom::kMediaServiceName] =
- base::BindRepeating(&base::ASCIIToUTF16, "Media Service");
-#endif
-
-#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
- out_of_process_services[media::mojom::kCdmServiceName] = base::BindRepeating(
- &base::ASCIIToUTF16, "Content Decryption Module Service");
-#endif
-
-#if defined(OS_CHROMEOS)
-#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
- out_of_process_services
- [chromeos::assistant::mojom::kAudioDecoderServiceName] =
- base::BindRepeating(&base::ASCIIToUTF16,
- "Assistant Audio Decoder Service");
-#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
-#endif
-
- if (features::IsMultiProcessMash() && features::IsMashOopVizEnabled()) {
- out_of_process_services[viz::mojom::kVizServiceName] =
- base::BindRepeating(&base::ASCIIToUTF16, "Visuals Service");
- }
-
- for (const auto& service : out_of_process_services) {
- packaged_services_connection_->AddServiceRequestHandlerWithCallback(
- service.first,
- base::BindRepeating(&QueryAndStartServiceInUtilityProcess,
- service.first, service.second.process_name_callback,
- service.second.process_group));
- }
-
-#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
- packaged_services_connection_->AddServiceRequestHandlerWithCallback(
- media::mojom::kMediaServiceName,
- base::Bind(&StartServiceInGpuProcess, media::mojom::kMediaServiceName));
-#endif
-
- packaged_services_connection_->AddServiceRequestHandlerWithCallback(
- shape_detection::mojom::kServiceName,
- base::Bind(&StartServiceInGpuProcess,
- shape_detection::mojom::kServiceName));
-
- packaged_services_connection_->Start();
-
+ in_process_context_->Start(
+ manifests, std::move(system_remote),
+ base::BindRepeating(&ServiceManagerContext::RunServiceInstance,
+ weak_ptr_factory_.GetWeakPtr()));
in_process_context_->StartServices(
GetContentClient()->browser()->GetStartupServices());
}
@@ -744,7 +732,6 @@ void ServiceManagerContext::ShutDown() {
ServiceManagerConnection::DestroyForProcess();
service_manager_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&DestroyConnectorOnIOThread));
- packaged_services_connection_.reset();
}
// static
@@ -764,9 +751,9 @@ bool ServiceManagerContext::HasValidProcessForProcessGroup(
// static
void ServiceManagerContext::StartBrowserConnection() {
- auto* browser_connection = ServiceManagerConnection::GetForProcess();
- RegisterCommonBrowserInterfaces(browser_connection);
- browser_connection->Start();
+ auto* system_connection = ServiceManagerConnection::GetForProcess();
+ RegisterCommonBrowserInterfaces(system_connection);
+ system_connection->Start();
if (base::FeatureList::IsEnabled(network::features::kNetworkService))
return;
@@ -784,10 +771,10 @@ ServiceManagerContext::GetAudioServiceRunner() {
return (*instance).get();
}
-void ServiceManagerContext::OnUnhandledServiceRequest(
- const std::string& service_name,
- service_manager::mojom::ServiceRequest request) {
- if (service_name == device::mojom::kServiceName) {
+void ServiceManagerContext::RunServiceInstance(
+ const service_manager::Identity& identity,
+ mojo::PendingReceiver<service_manager::mojom::Service> receiver) {
+ if (identity.name() == device::mojom::kServiceName) {
// This task runner may be used by some device service implementation bits
// to interface with dbus client code, which in turn imposes some subtle
// thread affinity on the clients. We therefore require a single-thread
@@ -807,29 +794,33 @@ void ServiceManagerContext::OnUnhandledServiceRequest(
auto service = device::CreateDeviceService(
device_blocking_task_runner, service_manager_thread_task_runner_,
base::MakeRefCounted<DeviceServiceURLLoaderFactory>(),
+ content::GetNetworkConnectionTracker(),
GetContentClient()->browser()->GetGeolocationApiKey(),
GetContentClient()->browser()->ShouldUseGmsCoreGeolocationProvider(),
base::BindRepeating(&WakeLockContextHost::GetNativeViewForContext),
base::BindRepeating(
&ContentBrowserClient::OverrideSystemLocationProvider,
base::Unretained(GetContentClient()->browser())),
- std::move(java_nfc_delegate), std::move(request));
+ std::move(java_nfc_delegate), std::move(receiver));
#else
auto service = device::CreateDeviceService(
device_blocking_task_runner, service_manager_thread_task_runner_,
base::MakeRefCounted<DeviceServiceURLLoaderFactory>(),
+ content::GetNetworkConnectionTracker(),
GetContentClient()->browser()->GetGeolocationApiKey(),
base::BindRepeating(
&ContentBrowserClient::OverrideSystemLocationProvider,
base::Unretained(GetContentClient()->browser())),
- std::move(request));
+ std::move(receiver));
#endif
service_manager::Service::RunAsyncUntilTermination(std::move(service));
return;
}
- GetContentClient()->browser()->HandleServiceRequest(service_name,
- std::move(request));
+ GetContentClient()->browser()->RunServiceInstance(identity, &receiver);
+
+ DLOG_IF(ERROR, receiver) << "Unhandled service request for \""
+ << identity.name() << "\"";
}
} // 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 f520f8f3a9f..d6ab742496f 100644
--- a/chromium/content/browser/service_manager/service_manager_context.h
+++ b/chromium/content/browser/service_manager/service_manager_context.h
@@ -14,6 +14,8 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "services/service_manager/public/cpp/identity.h"
#include "services/service_manager/public/mojom/service.mojom.h"
namespace base {
@@ -26,8 +28,6 @@ class Connector;
namespace content {
-class ServiceManagerConnection;
-
// ServiceManagerContext manages the browser's connection to the ServiceManager,
// hosting a new in-process ServiceManagerContext if the browser was not
// launched from an external one.
@@ -35,7 +35,6 @@ class CONTENT_EXPORT ServiceManagerContext {
public:
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.
@@ -58,14 +57,13 @@ class CONTENT_EXPORT ServiceManagerContext {
private:
class InProcessServiceManagerContext;
- void OnUnhandledServiceRequest(
- const std::string& service_name,
- service_manager::mojom::ServiceRequest request);
+ void RunServiceInstance(
+ const service_manager::Identity& identity,
+ mojo::PendingReceiver<service_manager::mojom::Service> receiver);
scoped_refptr<base::SingleThreadTaskRunner>
service_manager_thread_task_runner_;
scoped_refptr<InProcessServiceManagerContext> in_process_context_;
- std::unique_ptr<ServiceManagerConnection> packaged_services_connection_;
base::Thread network_service_thread_{"NetworkService"};
base::WeakPtrFactory<ServiceManagerContext> weak_ptr_factory_{this};
diff --git a/chromium/content/browser/service_manager/service_manager_context_browsertest.cc b/chromium/content/browser/service_manager/service_manager_context_browsertest.cc
index df6ffb9edbd..8f753d4516e 100644
--- a/chromium/content/browser/service_manager/service_manager_context_browsertest.cc
+++ b/chromium/content/browser/service_manager/service_manager_context_browsertest.cc
@@ -99,7 +99,7 @@ IN_PROC_BROWSER_TEST_F(ServiceManagerContextBrowserTest,
MANUAL_TerminateOnServiceQuit) {
ShellContentBrowserClient::Get()
->set_should_terminate_on_service_quit_callback(
- base::Bind(&ShouldTerminateOnServiceQuit));
+ base::BindOnce(&ShouldTerminateOnServiceQuit));
// Launch a test service.
echo::mojom::EchoPtr echo_ptr;
diff --git a/chromium/content/browser/service_worker/README.md b/chromium/content/browser/service_worker/README.md
index c0b145657b8..693d391be23 100644
--- a/chromium/content/browser/service_worker/README.md
+++ b/chromium/content/browser/service_worker/README.md
@@ -129,7 +129,7 @@ The UMA data is internal-only. Key metrics include:
controlled loads:
- PageLoad.Clients.ServiceWorker2.PaintTiming.NavigationToFirstContentfulPaint
- PageLoad.Clients.ServiceWorker2.Input.NavigationToFirstContentfulPaint
-- PageLoad.Clients.ServiceWorker2.InteractiveTiming.FirstInputDelay2
+- PageLoad.Clients.ServiceWorker2.InteractiveTiming.FirstInputDelay3
Service worker startup time and breakdown:
- ServiceWorker.StartWorker.Time
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc
index 3ac0a977793..c0094df7079 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.cc
@@ -35,7 +35,6 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_client.h"
-#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_message.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -50,10 +49,10 @@ namespace content {
namespace {
-base::Optional<EmbeddedWorkerInstance::CreateNetworkFactoryCallback>&
+EmbeddedWorkerInstance::CreateNetworkFactoryCallback&
GetNetworkFactoryCallbackForTest() {
static base::NoDestructor<
- base::Optional<EmbeddedWorkerInstance::CreateNetworkFactoryCallback>>
+ EmbeddedWorkerInstance::CreateNetworkFactoryCallback>
callback;
return *callback;
}
@@ -106,7 +105,9 @@ using SetupProcessCallback = base::OnceCallback<void(
blink::URLLoaderFactoryBundleInfo> /* factory_bundle_for_new_scripts */,
std::unique_ptr<
blink::URLLoaderFactoryBundleInfo> /* factory_bundle_for_renderer */,
- blink::mojom::CacheStoragePtrInfo)>;
+ blink::mojom::CacheStoragePtrInfo,
+ base::TimeDelta thread_hop_time,
+ base::Time ui_post_time)>;
// Allocates a renderer process for starting a worker and does setup like
// registering with DevTools. Called on the UI thread. Calls |callback| on the
@@ -124,8 +125,10 @@ void SetupOnUIThread(int embedded_worker_id,
blink::mojom::EmbeddedWorkerInstanceClientRequest request,
ServiceWorkerContextCore* context,
base::WeakPtr<ServiceWorkerContextCore> weak_context,
+ base::Time io_post_time,
SetupProcessCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ base::TimeDelta thread_hop_time = base::Time::Now() - io_post_time;
auto process_info =
std::make_unique<ServiceWorkerProcessManager::AllocatedProcessInfo>();
std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy> devtools_proxy;
@@ -137,13 +140,13 @@ void SetupOnUIThread(int embedded_worker_id,
if (!process_manager) {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
- base::BindOnce(std::move(callback),
- blink::ServiceWorkerStatusCode::kErrorAbort,
- std::move(params), std::move(process_info),
- std::move(devtools_proxy),
- std::move(factory_bundle_for_new_scripts),
- std::move(factory_bundle_for_renderer),
- nullptr /* cache_storage */));
+ base::BindOnce(
+ std::move(callback), blink::ServiceWorkerStatusCode::kErrorAbort,
+ std::move(params), std::move(process_info),
+ std::move(devtools_proxy),
+ std::move(factory_bundle_for_new_scripts),
+ std::move(factory_bundle_for_renderer), nullptr /* cache_storage */,
+ thread_hop_time, base::Time::Now()));
return;
}
@@ -159,7 +162,8 @@ void SetupOnUIThread(int embedded_worker_id,
std::move(process_info), std::move(devtools_proxy),
std::move(factory_bundle_for_new_scripts),
std::move(factory_bundle_for_renderer),
- nullptr /* cache_storage */));
+ nullptr /* cache_storage */, thread_hop_time,
+ base::Time::Now()));
return;
}
const int process_id = process_info->process_id;
@@ -248,7 +252,8 @@ void SetupOnUIThread(int embedded_worker_id,
std::move(process_info), std::move(devtools_proxy),
std::move(factory_bundle_for_new_scripts),
std::move(factory_bundle_for_renderer),
- cache_storage.PassInterface()));
+ cache_storage.PassInterface(), thread_hop_time,
+ base::Time::Now()));
}
bool HasSentStartWorker(EmbeddedWorkerInstance::StartingPhase phase) {
@@ -272,8 +277,6 @@ bool HasSentStartWorker(EmbeddedWorkerInstance::StartingPhase phase) {
void NotifyForegroundServiceWorkerOnUIThread(bool added, int process_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(
- base::FeatureList::IsEnabled(features::kServiceWorkerForegroundPriority));
RenderProcessHost* rph = RenderProcessHost::FromID(process_id);
if (!rph)
@@ -293,21 +296,23 @@ class EmbeddedWorkerInstance::DevToolsProxy {
public:
DevToolsProxy(int process_id, int agent_route_id)
: process_id_(process_id),
- agent_route_id_(agent_route_id) {}
+ agent_route_id_(agent_route_id),
+ ui_task_runner_(
+ base::CreateSequencedTaskRunnerWithTraits({BrowserThread::UI})) {}
~DevToolsProxy() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(NotifyWorkerDestroyedOnUI,
- process_id_, agent_route_id_));
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(NotifyWorkerDestroyedOnUI, process_id_,
+ agent_route_id_));
}
void NotifyWorkerReadyForInspection(
blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
+ ui_task_runner_->PostTask(
+ FROM_HERE,
base::BindOnce(NotifyWorkerReadyForInspectionOnUI, process_id_,
agent_route_id_, std::move(host_request),
std::move(devtools_agent_ptr_info)));
@@ -315,16 +320,16 @@ class EmbeddedWorkerInstance::DevToolsProxy {
void NotifyWorkerVersionInstalled() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(NotifyWorkerVersionInstalledOnUI,
- process_id_, agent_route_id_));
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(NotifyWorkerVersionInstalledOnUI, process_id_,
+ agent_route_id_));
}
void NotifyWorkerVersionDoomed() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(NotifyWorkerVersionDoomedOnUI,
- process_id_, agent_route_id_));
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(NotifyWorkerVersionDoomedOnUI, process_id_,
+ agent_route_id_));
}
bool ShouldNotifyWorkerStopIgnored() const {
@@ -338,6 +343,7 @@ class EmbeddedWorkerInstance::DevToolsProxy {
private:
const int process_id_;
const int agent_route_id_;
+ const scoped_refptr<base::TaskRunner> ui_task_runner_;
bool worker_stop_ignored_notified_ = false;
DISALLOW_COPY_AND_ASSIGN(DevToolsProxy);
@@ -372,18 +378,20 @@ class EmbeddedWorkerInstance::WorkerProcessHandle {
WorkerProcessHandle(
const base::WeakPtr<ServiceWorkerProcessManager>& process_manager,
int embedded_worker_id,
- int process_id)
+ int process_id,
+ scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
: process_manager_(process_manager),
embedded_worker_id_(embedded_worker_id),
- process_id_(process_id) {
+ process_id_(process_id),
+ ui_task_runner_(std::move(ui_task_runner)) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id_);
}
~WorkerProcessHandle() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
+ ui_task_runner_->PostTask(
+ FROM_HERE,
base::BindOnce(&ServiceWorkerProcessManager::ReleaseWorkerProcess,
process_manager_, embedded_worker_id_));
}
@@ -396,6 +404,7 @@ class EmbeddedWorkerInstance::WorkerProcessHandle {
const int embedded_worker_id_;
const int process_id_;
+ const scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
DISALLOW_COPY_AND_ASSIGN(WorkerProcessHandle);
};
@@ -447,8 +456,8 @@ class EmbeddedWorkerInstance::StartTask {
break;
case ProcessAllocationState::ALLOCATING:
// Abort half-baked process allocation on the UI thread.
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
+ instance_->ui_task_runner_->PostTask(
+ FROM_HERE,
base::BindOnce(&ServiceWorkerProcessManager::ReleaseWorkerProcess,
instance_->context_->process_manager()->AsWeakPtr(),
instance_->embedded_worker_id()));
@@ -477,6 +486,7 @@ class EmbeddedWorkerInstance::StartTask {
base::TimeTicks start_worker_sent_time() const {
return start_worker_sent_time_;
}
+ base::TimeDelta thread_hop_time() const { return thread_hop_time_; }
void set_skip_recording_startup_time() {
skip_recording_startup_time_ = true;
@@ -507,12 +517,12 @@ class EmbeddedWorkerInstance::StartTask {
// Hop to the UI thread for process allocation and setup. We will continue
// on the IO thread in StartTask::OnSetupCompleted().
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
+ instance_->ui_task_runner_->PostTask(
+ FROM_HERE,
base::BindOnce(
&SetupOnUIThread, instance_->embedded_worker_id(), process_manager,
can_use_existing_process, std::move(params), std::move(request_),
- context.get(), context,
+ context.get(), context, base::Time::Now(),
base::BindOnce(&StartTask::OnSetupCompleted,
weak_factory_.GetWeakPtr(), process_manager)));
}
@@ -531,16 +541,20 @@ class EmbeddedWorkerInstance::StartTask {
factory_bundle_for_new_scripts,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
factory_bundle_for_renderer,
- blink::mojom::CacheStoragePtrInfo cache_storage) {
+ blink::mojom::CacheStoragePtrInfo cache_storage,
+ base::TimeDelta thread_hop_time,
+ base::Time ui_post_time) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ thread_hop_time_ = thread_hop_time + (base::Time::Now() - ui_post_time);
+
std::unique_ptr<WorkerProcessHandle> process_handle;
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>(
process_manager, instance_->embedded_worker_id(),
- process_info->process_id);
+ process_info->process_id, instance_->ui_task_runner_);
if (!instance_->context_)
status = blink::ServiceWorkerStatusCode::kErrorAbort;
@@ -587,7 +601,7 @@ class EmbeddedWorkerInstance::StartTask {
DCHECK(factory_bundle_for_new_scripts || is_installed_);
if (factory_bundle_for_new_scripts) {
params->provider_info->script_loader_factory_ptr_info =
- instance_->MakeScriptLoaderFactoryAssociatedPtrInfo(
+ instance_->MakeScriptLoaderFactoryPtrInfo(
std::move(factory_bundle_for_new_scripts));
}
@@ -619,6 +633,7 @@ class EmbeddedWorkerInstance::StartTask {
bool skip_recording_startup_time_;
base::TimeTicks start_time_;
base::TimeTicks start_worker_sent_time_;
+ base::TimeDelta thread_hop_time_;
base::WeakPtrFactory<StartTask> weak_factory_;
@@ -725,6 +740,8 @@ EmbeddedWorkerInstance::EmbeddedWorkerInstance(
devtools_attached_(false),
network_accessed_for_script_(false),
foreground_notified_(false),
+ ui_task_runner_(
+ base::CreateSequencedTaskRunnerWithTraits({BrowserThread::UI})),
weak_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(context_);
@@ -886,6 +903,7 @@ void EmbeddedWorkerInstance::OnStarted(
times.remote_script_evaluation_end =
start_timing->script_evaluation_end_time;
times.local_end = base::TimeTicks::Now();
+ times.thread_hop_time = inflight_start_task_->thread_hop_time();
ServiceWorkerMetrics::RecordStartWorkerTiming(times, start_situation_);
}
@@ -974,16 +992,16 @@ EmbeddedWorkerInstance::CreateFactoryBundleOnUI(RenderProcessHost* rph,
rph, routing_id, &default_factory_request);
}
- if (!GetNetworkFactoryCallbackForTest()) {
+ if (GetNetworkFactoryCallbackForTest().is_null()) {
rph->CreateURLLoaderFactory(origin, std::move(default_header_client),
std::move(default_factory_request));
} else {
network::mojom::URLLoaderFactoryPtr original_factory;
rph->CreateURLLoaderFactory(origin, std::move(default_header_client),
mojo::MakeRequest(&original_factory));
- GetNetworkFactoryCallbackForTest()->Run(std::move(default_factory_request),
- rph->GetID(),
- original_factory.PassInterface());
+ GetNetworkFactoryCallbackForTest().Run(std::move(default_factory_request),
+ rph->GetID(),
+ original_factory.PassInterface());
}
factory_bundle->set_bypass_redirect_checks(bypass_redirect_checks);
@@ -1169,47 +1187,39 @@ void EmbeddedWorkerInstance::SetNetworkFactoryForTesting(
void EmbeddedWorkerInstance::NotifyForegroundServiceWorkerAdded() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(
- base::FeatureList::IsEnabled(features::kServiceWorkerForegroundPriority));
if (!process_handle_ || foreground_notified_)
return;
foreground_notified_ = true;
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&NotifyForegroundServiceWorkerOnUIThread, true /* added */,
- process_id()));
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&NotifyForegroundServiceWorkerOnUIThread,
+ true /* added */, process_id()));
}
void EmbeddedWorkerInstance::NotifyForegroundServiceWorkerRemoved() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(
- !foreground_notified_ ||
- base::FeatureList::IsEnabled(features::kServiceWorkerForegroundPriority));
if (!process_handle_ || !foreground_notified_)
return;
foreground_notified_ = false;
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&NotifyForegroundServiceWorkerOnUIThread,
- false /* added */, process_id()));
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&NotifyForegroundServiceWorkerOnUIThread,
+ false /* added */, process_id()));
}
-network::mojom::URLLoaderFactoryAssociatedPtrInfo
-EmbeddedWorkerInstance::MakeScriptLoaderFactoryAssociatedPtrInfo(
+network::mojom::URLLoaderFactoryPtrInfo
+EmbeddedWorkerInstance::MakeScriptLoaderFactoryPtrInfo(
std::unique_ptr<blink::URLLoaderFactoryBundleInfo> script_bundle) {
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_ptr_info;
+ network::mojom::URLLoaderFactoryPtrInfo script_loader_factory_ptr_info;
auto script_bundle_factory =
base::MakeRefCounted<blink::URLLoaderFactoryBundle>(
std::move(script_bundle));
- script_loader_factory_ = mojo::MakeStrongAssociatedBinding(
+ script_loader_factory_ = mojo::MakeStrongBinding(
std::make_unique<ServiceWorkerScriptLoaderFactory>(
context_, owner_version_->provider_host()->AsWeakPtr(),
std::move(script_bundle_factory)),
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.h b/chromium/content/browser/service_worker/embedded_worker_instance.h
index 959afaa648b..8d3c6923a95 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.h
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.h
@@ -24,7 +24,7 @@
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/content_export.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"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
@@ -310,8 +310,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
void NotifyForegroundServiceWorkerAdded();
void NotifyForegroundServiceWorkerRemoved();
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- MakeScriptLoaderFactoryAssociatedPtrInfo(
+ network::mojom::URLLoaderFactoryPtrInfo MakeScriptLoaderFactoryPtrInfo(
std::unique_ptr<blink::URLLoaderFactoryBundleInfo> script_bundle);
base::WeakPtr<ServiceWorkerContextCore> context_;
@@ -359,9 +358,11 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
std::unique_ptr<ServiceWorkerContentSettingsProxyImpl> content_settings_;
- mojo::StrongAssociatedBindingPtr<network::mojom::URLLoaderFactory>
+ mojo::StrongBindingPtr<network::mojom::URLLoaderFactory>
script_loader_factory_;
+ const scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
+
base::WeakPtrFactory<EmbeddedWorkerInstance> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstance);
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 85c0942ff38..ddc0c29c06a 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -16,59 +16,13 @@
#include "content/common/renderer.mojom.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
+#include "content/test/fake_network_url_loader_factory.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/interface_request.h"
-#include "net/http/http_util.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
namespace content {
-// 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);
-};
-
class EmbeddedWorkerTestHelper::MockRendererInterface : public mojom::Renderer {
public:
// |helper| must outlive this.
@@ -181,7 +135,7 @@ EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
std::move(new_renderer_interface_ptr));
default_network_loader_factory_ =
- std::make_unique<MockNetworkURLLoaderFactory>();
+ std::make_unique<FakeNetworkURLLoaderFactory>();
SetNetworkFactory(default_network_loader_factory_.get());
}
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 f5c939dcfe4..b715b0a9515 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
@@ -22,8 +22,9 @@
namespace content {
-class MockRenderProcessHost;
+class FakeNetworkURLLoaderFactory;
class FakeServiceWorker;
+class MockRenderProcessHost;
class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
class TestBrowserContext;
@@ -154,7 +155,6 @@ class EmbeddedWorkerTestHelper {
virtual std::unique_ptr<FakeServiceWorker> CreateServiceWorker();
private:
- class MockNetworkURLLoaderFactory;
class MockRendererInterface;
std::unique_ptr<TestBrowserContext> browser_context_;
@@ -180,7 +180,7 @@ class EmbeddedWorkerTestHelper {
int new_mock_render_process_id_;
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_;
- std::unique_ptr<MockNetworkURLLoaderFactory> default_network_loader_factory_;
+ std::unique_ptr<FakeNetworkURLLoaderFactory> default_network_loader_factory_;
DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerTestHelper);
};
diff --git a/chromium/content/browser/service_worker/fake_embedded_worker_instance_client.cc b/chromium/content/browser/service_worker/fake_embedded_worker_instance_client.cc
index ab886046c6e..80b8b335ad1 100644
--- a/chromium/content/browser/service_worker/fake_embedded_worker_instance_client.cc
+++ b/chromium/content/browser/service_worker/fake_embedded_worker_instance_client.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
namespace content {
@@ -69,6 +70,15 @@ void FakeEmbeddedWorkerInstanceClient::StartWorker(
// |script_loader_factory_ptr_info| from |start_params_->provider_info|
// to request the script and the browser process should be able to mock it.
// For installed workers, the map should already be populated.
+ ServiceWorkerVersion* version = helper_->context()->GetLiveVersion(
+ start_params_->service_worker_version_id);
+ if (version && version->status() == ServiceWorkerVersion::REDUNDANT) {
+ // This can happen if ForceDelete() was called on the registration. Early
+ // return because otherwise PopulateScriptCacheMap will DCHECK. If we mocked
+ // things as per the TODO, the script load would fail and we don't need to
+ // special case this.
+ return;
+ }
helper_->PopulateScriptCacheMap(
start_params_->service_worker_version_id,
base::BindOnce(
diff --git a/chromium/content/browser/service_worker/fake_service_worker.cc b/chromium/content/browser/service_worker/fake_service_worker.cc
index 199ab562b0a..12ea329891a 100644
--- a/chromium/content/browser/service_worker/fake_service_worker.cc
+++ b/chromium/content/browser/service_worker/fake_service_worker.cc
@@ -147,6 +147,13 @@ void FakeServiceWorker::DispatchSyncEvent(const std::string& tag,
NOTIMPLEMENTED();
}
+void FakeServiceWorker::DispatchPeriodicSyncEvent(
+ const std::string& tag,
+ base::TimeDelta timeout,
+ DispatchPeriodicSyncEventCallback callback) {
+ NOTIMPLEMENTED();
+}
+
void FakeServiceWorker::DispatchAbortPaymentEvent(
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
DispatchAbortPaymentEventCallback callback) {
diff --git a/chromium/content/browser/service_worker/fake_service_worker.h b/chromium/content/browser/service_worker/fake_service_worker.h
index ddf80fdc09b..ed00f5e1cf5 100644
--- a/chromium/content/browser/service_worker/fake_service_worker.h
+++ b/chromium/content/browser/service_worker/fake_service_worker.h
@@ -86,6 +86,10 @@ class FakeServiceWorker : public blink::mojom::ServiceWorker {
bool last_chance,
base::TimeDelta timeout,
DispatchSyncEventCallback callback) override;
+ void DispatchPeriodicSyncEvent(
+ const std::string& tag,
+ base::TimeDelta timeout,
+ DispatchPeriodicSyncEventCallback callback) override;
void DispatchAbortPaymentEvent(
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
DispatchAbortPaymentEventCallback callback) override;
diff --git a/chromium/content/browser/service_worker/service_worker_browsertest.cc b/chromium/content/browser/service_worker/service_worker_browsertest.cc
index 5a0c4558d21..d6d393ae3db 100644
--- a/chromium/content/browser/service_worker/service_worker_browsertest.cc
+++ b/chromium/content/browser/service_worker/service_worker_browsertest.cc
@@ -31,6 +31,7 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/cache_storage/cache_storage.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
@@ -72,6 +73,7 @@
#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/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "content/test/test_content_browser_client.h"
@@ -458,10 +460,19 @@ const char kNavigationPreloadNetworkError[] =
} // namespace
-class ServiceWorkerBrowserTest : public ContentBrowserTest {
+class ServiceWorkerBrowserTest : public ContentBrowserTest,
+ public testing::WithParamInterface<bool> {
protected:
using self = ServiceWorkerBrowserTest;
+ void SetUp() override {
+ if (ShouldDisableOffMainScriptFetch()) {
+ feature_list_.InitAndDisableFeature(
+ blink::features::kOffMainThreadServiceWorkerScriptFetch);
+ }
+ ContentBrowserTest::SetUp();
+ }
+
void SetUpOnMainThread() override {
ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(
@@ -499,7 +510,11 @@ class ServiceWorkerBrowserTest : public ContentBrowserTest {
ServiceWorkerContextWrapper* wrapper() { return wrapper_.get(); }
ServiceWorkerContext* public_context() { return wrapper(); }
+ base::test::ScopedFeatureList feature_list_;
+
private:
+ bool ShouldDisableOffMainScriptFetch() { return GetParam(); }
+
scoped_refptr<ServiceWorkerContextWrapper> wrapper_;
};
@@ -818,11 +833,6 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
registration_.get(), version_.get(), status);
}
- void RemoveLiveRegistrationOnIOThread(int64_t id) {
- ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
- wrapper()->context()->RemoveLiveRegistration(id);
- }
-
void StartOnIOThread(base::OnceClosure done,
base::Optional<blink::ServiceWorkerStatusCode>* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -1037,6 +1047,21 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
version_->StopWorker(std::move(done));
}
+ void SetActiveVersionOnIOThread(ServiceWorkerRegistration* registration,
+ ServiceWorkerVersion* version) {
+ version->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration->SetActiveVersion(version);
+ }
+
+ void SetResourcesOnIOThread(
+ ServiceWorkerVersion* version,
+ const std::vector<ServiceWorkerDatabase::ResourceRecord>& resources) {
+ version->script_cache_map()->resource_map_.clear();
+ version->script_cache_map()->SetResources(resources);
+ }
+
protected:
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> version_;
@@ -1045,7 +1070,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
std::vector<ServiceWorkerRemoteProviderEndpoint> remote_endpoints_;
};
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, StartAndStop) {
StartServerAndNavigateToSetup();
RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread,
base::Unretained(this),
@@ -1072,7 +1097,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
// TODO(lunalu): remove this test when blink side use counter is removed
// (crbug.com/811948).
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
DropCountsOnBlinkUseCounter) {
StartServerAndNavigateToSetup();
RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread,
@@ -1104,7 +1129,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
"Blink.UseCounter.Features"));
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, StartNotFound) {
StartServerAndNavigateToSetup();
RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread,
base::Unretained(this),
@@ -1114,28 +1139,24 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) {
StartWorker(blink::ServiceWorkerStatusCode::kErrorNetwork);
}
-#if defined(ANDROID)
-// Flaky failures on Android; see https://crbug.com/720275.
-#define MAYBE_ReadResourceFailure DISABLED_ReadResourceFailure
-#else
-#define MAYBE_ReadResourceFailure ReadResourceFailure
-#endif
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
- MAYBE_ReadResourceFailure) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, ReadResourceFailure) {
StartServerAndNavigateToSetup();
- // Create a registration.
- RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread,
- base::Unretained(this),
- "/service_worker/worker.js"));
- version_->set_fetch_handler_existence(
- ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
- version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+
+ // Create a registration with an active version.
+ RunOnIOThread(base::BindOnce(
+ &ServiceWorkerVersionBrowserTest::SetUpRegistrationOnIOThread,
+ base::Unretained(this), "/service_worker/worker.js"));
+ RunOnIOThread(base::BindOnce(
+ &ServiceWorkerVersionBrowserTest::SetActiveVersionOnIOThread,
+ base::Unretained(this), base::Unretained(registration_.get()),
+ base::Unretained(version_.get())));
// Add a non-existent resource to the version.
- std::vector<ServiceWorkerDatabase::ResourceRecord> records;
- records.push_back(
- ServiceWorkerDatabase::ResourceRecord(30, version_->script_url(), 100));
- version_->script_cache_map()->SetResources(records);
+ std::vector<ServiceWorkerDatabase::ResourceRecord> records = {
+ ServiceWorkerDatabase::ResourceRecord(30, version_->script_url(), 100)};
+ RunOnIOThread(base::BindOnce(
+ &ServiceWorkerVersionBrowserTest::SetResourcesOnIOThread,
+ base::Unretained(this), base::Unretained(version_.get()), records));
// Store the registration.
StoreRegistration(version_->version_id(),
@@ -1145,15 +1166,13 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
StartWorker(blink::ServiceWorkerStatusCode::kErrorDiskCache);
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
- // The registration should be deleted from storage since the broken worker was
- // the stored one.
- RunOnIOThread(base::BindOnce(&self::RemoveLiveRegistrationOnIOThread,
- base::Unretained(this), registration_->id()));
+ // The registration should be deleted from storage.
FindRegistrationForId(registration_->id(), registration_->scope().GetOrigin(),
blink::ServiceWorkerStatusCode::kErrorNotFound);
+ EXPECT_TRUE(registration_->is_uninstalled());
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
ReadResourceFailure_WaitingWorker) {
StartServerAndNavigateToSetup();
// Create a registration and active version.
@@ -1166,17 +1185,23 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
RunOnIOThread(
base::BindOnce(&self::AddControlleeOnIOThread, base::Unretained(this)));
- // Add a non-existent resource to the version.
- version_->script_cache_map()->resource_map_[version_->script_url()] =
- ServiceWorkerDatabase::ResourceRecord(30, version_->script_url(), 100);
+ // Set a non-existent resource to the version.
+ std::vector<ServiceWorkerDatabase::ResourceRecord> records = {
+ ServiceWorkerDatabase::ResourceRecord(30, version_->script_url(), 100)};
+ RunOnIOThread(base::BindOnce(
+ &ServiceWorkerVersionBrowserTest::SetResourcesOnIOThread,
+ base::Unretained(this), base::Unretained(version_.get()), records));
// Make a waiting version and store it.
RunOnIOThread(base::BindOnce(&self::AddWaitingWorkerOnIOThread,
base::Unretained(this),
"/service_worker/worker.js"));
- std::vector<ServiceWorkerDatabase::ResourceRecord> records = {
+ records = {
ServiceWorkerDatabase::ResourceRecord(31, version_->script_url(), 100)};
- registration_->waiting_version()->script_cache_map()->SetResources(records);
+ RunOnIOThread(base::BindOnce(
+ &ServiceWorkerVersionBrowserTest::SetResourcesOnIOThread,
+ base::Unretained(this),
+ base::Unretained(registration_->waiting_version()), records));
StoreRegistration(registration_->waiting_version()->version_id(),
blink::ServiceWorkerStatusCode::kOk);
@@ -1186,28 +1211,27 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
StartWorker(blink::ServiceWorkerStatusCode::kErrorDiskCache);
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
- // The registration should still be in storage since the waiting worker was
- // the stored one.
- RunOnIOThread(base::BindOnce(&self::RemoveLiveRegistrationOnIOThread,
- base::Unretained(this), registration_->id()));
+ // The whole registration should be deleted from storage even though the
+ // waiting version was not the broken one.
FindRegistrationForId(registration_->id(), registration_->scope().GetOrigin(),
- blink::ServiceWorkerStatusCode::kOk);
+ blink::ServiceWorkerStatusCode::kErrorNotFound);
+ EXPECT_TRUE(registration_->is_uninstalled());
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Install) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, Install) {
StartServerAndNavigateToSetup();
InstallTestHelper("/service_worker/worker.js",
blink::ServiceWorkerStatusCode::kOk);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
InstallWithWaitUntil_Fulfilled) {
StartServerAndNavigateToSetup();
InstallTestHelper("/service_worker/worker_install_fulfilled.js",
blink::ServiceWorkerStatusCode::kOk);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
InstallWithFetchHandler) {
StartServerAndNavigateToSetup();
InstallTestHelper("/service_worker/fetch_event.js",
@@ -1216,7 +1240,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
version_->fetch_handler_existence());
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
InstallWithoutFetchHandler) {
StartServerAndNavigateToSetup();
InstallTestHelper("/service_worker/worker.js",
@@ -1227,7 +1251,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
// Check that ServiceWorker script requests set a "Service-Worker: script"
// header.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
ServiceWorkerScriptHeader) {
embedded_test_server()->RegisterRequestHandler(
base::BindRepeating(&VerifyServiceWorkerHeaderInRequest));
@@ -1236,7 +1260,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
blink::ServiceWorkerStatusCode::kOk);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
Activate_NoEventListener) {
StartServerAndNavigateToSetup();
InstallTestHelper("/service_worker/worker.js",
@@ -1245,7 +1269,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
StartServerAndNavigateToSetup();
InstallTestHelper("/service_worker/worker_activate_rejected.js",
blink::ServiceWorkerStatusCode::kOk);
@@ -1253,7 +1277,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
InstallWithWaitUntil_Rejected) {
StartServerAndNavigateToSetup();
InstallTestHelper(
@@ -1261,7 +1285,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
InstallWithWaitUntil_RejectConsoleMessage) {
StartServerAndNavigateToSetup();
RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread,
@@ -1295,7 +1319,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
}
// Tests starting an installed classic service worker while offline.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
StartInstalledClassicScriptWhileOffline) {
StartServerAndNavigateToSetup();
@@ -1314,7 +1338,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
}
// Tests starting an installed module service worker while offline.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
StartInstalledModuleScriptWhileOffline) {
StartServerAndNavigateToSetup();
@@ -1346,7 +1370,7 @@ class WaitForLoaded : public EmbeddedWorkerInstance::Listener {
base::OnceClosure quit_;
};
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
StartServerAndNavigateToSetup();
RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread,
base::Unretained(this),
@@ -1383,7 +1407,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout, status.value());
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
StartServerAndNavigateToSetup();
RunOnIOThread(
base::BindOnce(&self::SetUpRegistrationOnIOThread, base::Unretained(this),
@@ -1419,7 +1443,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
status.value());
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
StartServerAndNavigateToSetup();
ServiceWorkerFetchDispatcher::FetchEventResult result;
blink::mojom::FetchAPIResponsePtr response;
@@ -1450,7 +1474,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
}
// Tests for response type when a service worker does respondWith(fetch()).
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
FetchEvent_ResponseNetwork) {
const char* kPath = "/service_worker/http_cache.html";
@@ -1467,7 +1491,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
FetchOnRegisteredWorker(kPath, &result, &response1, &blob_data_handle);
ASSERT_EQ(ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
result);
- EXPECT_EQ(std::string(), *response1->cache_storage_cache_name);
+ EXPECT_FALSE(response1->cache_storage_cache_name.has_value());
EXPECT_EQ(network::mojom::FetchResponseSource::kNetwork,
response1->response_source);
@@ -1482,7 +1506,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
response2->response_source);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
FetchEvent_ResponseViaCache) {
const char* kPath = "/service_worker/empty.html";
StartServerAndNavigateToSetup();
@@ -1498,7 +1522,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
FetchOnRegisteredWorker(kPath, &result, &response1, &blob_data_handle);
ASSERT_EQ(ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
result);
- EXPECT_EQ(std::string(), *response1->cache_storage_cache_name);
+ EXPECT_FALSE(response1->cache_storage_cache_name.has_value());
EXPECT_EQ(network::mojom::FetchResponseSource::kNetwork,
response1->response_source);
@@ -1514,7 +1538,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
response2->response_source);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
FetchEvent_respondWithRejection) {
StartServerAndNavigateToSetup();
ServiceWorkerFetchDispatcher::FetchEventResult result;
@@ -1557,7 +1581,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
// 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,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
UpdateBypassesCacheAfter24Hours) {
const char kScope[] = "/service_worker/handle_fetch.html";
const char kWorkerUrl[] = "/service_worker/update_worker.js";
@@ -1657,7 +1681,7 @@ class MockContentBrowserClient : public TestContentBrowserClient {
bool data_saver_enabled_;
};
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchWithSaveData) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, FetchWithSaveData) {
embedded_test_server()->RegisterRequestHandler(
base::BindRepeating(&VerifySaveDataHeaderInRequest));
StartServerAndNavigateToSetup();
@@ -1671,7 +1695,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchWithSaveData) {
SetBrowserClientForTesting(old_client);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
RequestWorkerScriptWithSaveData) {
embedded_test_server()->RegisterRequestHandler(
base::BindRepeating(&VerifySaveDataHeaderInRequest));
@@ -1686,7 +1710,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
SetBrowserClientForTesting(old_client);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchWithoutSaveData) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, FetchWithoutSaveData) {
embedded_test_server()->RegisterRequestHandler(
base::BindRepeating(&VerifySaveDataHeaderNotInRequest));
StartServerAndNavigateToSetup();
@@ -1698,7 +1722,65 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchWithoutSaveData) {
SetBrowserClientForTesting(old_client);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, FetchPageWithSaveData) {
+// Tests the |top_frame_origin| and |request_initiator| on the main resource and
+// subresource requests from service workers, in order to ensure proper handling
+// by the SplitCache. See https://crbug.com/918868.
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, RequestOrigin) {
+ embedded_test_server()->StartAcceptingConnections();
+
+ // To make things tricky about |top_frame_origin|, this test navigates to a
+ // page on |embedded_test_server()| which has a cross-origin iframe that
+ // registers the service worker.
+ net::EmbeddedTestServer cross_origin_server;
+ cross_origin_server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
+ ASSERT_TRUE(cross_origin_server.Start());
+
+ // There are three requests to test:
+ // 1) The request for the worker itself ("request_origin_worker.js").
+ // 2) importScripts("empty.js") from the service worker.
+ // 3) fetch("empty.html") from the service worker.
+ std::set<GURL> expected_request_urls = {
+ cross_origin_server.GetURL("/service_worker/request_origin_worker.js"),
+ cross_origin_server.GetURL("/service_worker/empty.js"),
+ cross_origin_server.GetURL("/service_worker/empty.html")};
+
+ base::RunLoop request_origin_expectation_waiter;
+ URLLoaderInterceptor request_listener(base::BindLambdaForTesting(
+ [&](URLLoaderInterceptor::RequestParams* params) {
+ auto it = expected_request_urls.find(params->url_request.url);
+ if (it != expected_request_urls.end()) {
+ EXPECT_TRUE(params->url_request.originated_from_service_worker);
+ EXPECT_FALSE(params->url_request.top_frame_origin.has_value());
+ EXPECT_TRUE(params->url_request.request_initiator.has_value());
+ EXPECT_EQ(params->url_request.request_initiator->GetURL(),
+ cross_origin_server.base_url());
+ expected_request_urls.erase(it);
+ }
+ if (expected_request_urls.empty())
+ request_origin_expectation_waiter.Quit();
+ return false;
+ }));
+
+ NavigateToURLBlockUntilNavigationsComplete(
+ shell(),
+ embedded_test_server()->GetURL(
+ "/service_worker/one_subframe.html?subframe_url=" +
+ cross_origin_server
+ .GetURL("/service_worker/create_service_worker.html")
+ .spec()),
+ 1);
+ RenderFrameHost* subframe_rfh = FrameMatchingPredicate(
+ shell()->web_contents(),
+ base::BindRepeating(&FrameMatchesName, "subframe_name"));
+ DCHECK(subframe_rfh);
+
+ EXPECT_EQ("DONE",
+ EvalJs(subframe_rfh, "register('request_origin_worker.js');"));
+
+ request_origin_expectation_waiter.Run();
+}
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, FetchPageWithSaveData) {
StartServerAndNavigateToSetup();
const char kPageUrl[] = "/service_worker/handle_fetch.html";
const char kWorkerUrl[] = "/service_worker/add_save_data_to_title.js";
@@ -1737,7 +1819,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, FetchPageWithSaveData) {
// Tests that when data saver is enabled and a cross-origin fetch by a webpage
// is intercepted by a serviceworker, and the serviceworker does a fetch, the
// preflight request does not have save-data in Access-Control-Request-Headers.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, CrossOriginFetchWithSaveData) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, CrossOriginFetchWithSaveData) {
StartServerAndNavigateToSetup();
const char kPageUrl[] = "/service_worker/fetch_cross_origin.html";
const char kWorkerUrl[] = "/service_worker/fetch_event_pass_through.js";
@@ -1784,7 +1866,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, CrossOriginFetchWithSaveData) {
run_loop.Run();
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest,
FetchPageWithSaveDataPassThroughOnFetch) {
const char kPageUrl[] = "/service_worker/pass_through_fetch.html";
const char kWorkerUrl[] = "/service_worker/fetch_event_pass_through.js";
@@ -1823,7 +1905,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
run_loop.Run();
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, Reload) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, Reload) {
StartServerAndNavigateToSetup();
const char kPageUrl[] = "/service_worker/reload.html";
const char kWorkerUrl[] = "/service_worker/fetch_event_reload.js";
@@ -1863,7 +1945,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, Reload) {
// renderer should continue processing events on the service worker instead of
// waiting for termination or an event from the browser. Regression test for
// https://crbug.com/878667.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, IdleTimerWithDevTools) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, IdleTimerWithDevTools) {
StartServerAndNavigateToSetup();
// Register a service worker.
@@ -2169,7 +2251,7 @@ const std::string
" result => event.source.postMessage(result)));\n"
" });";
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NetworkFallback) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, NetworkFallback) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
const char kPage[] = "<title>PASS</title>Hello world.";
@@ -2208,7 +2290,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NetworkFallback) {
EXPECT_GT(fallback_count, 0);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, SetHeaderValue) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, SetHeaderValue) {
const std::string kPageUrl = "/service_worker/navigation_preload.html";
const std::string kWorkerUrl = "/service_worker/navigation_preload.js";
const std::string kPage = "<title>FROM_SERVER</title>";
@@ -2293,7 +2375,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, SetHeaderValue) {
ASSERT_EQ(0, GetRequestCount(kPageUrl4));
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
RespondWithNavigationPreload) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2324,7 +2406,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
request_log_[kPageUrl][0].headers[kNavigationPreloadHeaderName]);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, GetResponseText) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, GetResponseText) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
const char kPage[] = "<title>PASS</title>Hello world.";
@@ -2352,7 +2434,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, GetResponseText) {
EXPECT_EQ(1, GetRequestCount(kPageUrl));
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
GetLargeResponseText) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2389,7 +2471,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
EXPECT_EQ(1, GetRequestCount(kPageUrl));
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
GetLargeResponseCloneText) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2427,7 +2509,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
EXPECT_EQ(1, GetRequestCount(kPageUrl));
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
GetLargeResponseReadableStream) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2476,7 +2558,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
EXPECT_EQ(1, GetRequestCount(kPageUrl));
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NetworkError) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, NetworkError) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
@@ -2509,7 +2591,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NetworkError) {
EXPECT_NE(base::string16::npos, messages[0].find(expected));
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
PreloadHeadersSimple) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2539,7 +2621,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
base::NumberToString(sizeof(kPage) - 1)));
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NotEnabled) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, NotEnabled) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
const char kPage[] = "<title>ERROR</title>Hello world.";
@@ -2556,7 +2638,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NotEnabled) {
EXPECT_EQ(0, GetRequestCount(kPageUrl));
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
PreloadHeadersCustom) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2599,7 +2681,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
EXPECT_FALSE(HasHeader(*dict, "set-cookie2"));
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
InvalidRedirect_MultiLocation) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2646,7 +2728,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
EXPECT_EQ(0, GetRequestCount(kRedirectedPageUrl2));
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
InvalidRedirect_InvalidLocation) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2676,7 +2758,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
// Tests responding with the navigation preload response when the navigation
// occurred after a redirect.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
RedirectAndRespondWithNavigationPreload) {
const std::string kPageUrl = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2741,7 +2823,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
EXPECT_EQ(1, GetRequestCount(kPageUrl + "?3"));
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest,
ResponseFromHTTPSServiceWorkerIsMarkedAsSecure) {
StartServerAndNavigateToSetup();
const char kPageUrl[] = "/service_worker/fetch_event_blob.html";
@@ -2783,7 +2865,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
run_loop.Run();
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest,
ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure) {
StartServerAndNavigateToSetup();
const char kPageUrl[] = "/service_worker/fetch_event_blob.html";
@@ -2820,7 +2902,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
run_loop.Run();
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, ImportsBustMemcache) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, ImportsBustMemcache) {
StartServerAndNavigateToSetup();
const char kScopeUrl[] = "/service_worker/imports_bust_memcache_scope/";
const char kPageUrl[] = "/service_worker/imports_bust_memcache.html";
@@ -2877,7 +2959,7 @@ class WorkerRunningStatusObserver : public ServiceWorkerContextObserver {
int64_t version_id_ = blink::mojom::kInvalidServiceWorkerVersionId;
};
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest,
GetAllServiceWorkerRunningInfos) {
StartServerAndNavigateToSetup();
WorkerRunningStatusObserver observer(public_context());
@@ -2900,7 +2982,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
infos[0].process_id);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, GetServiceWorkerRunningInfo) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, GetServiceWorkerRunningInfo) {
StartServerAndNavigateToSetup();
WorkerRunningStatusObserver observer(public_context());
EXPECT_TRUE(NavigateToURL(shell(),
@@ -2941,7 +3023,7 @@ class StopObserver : public ServiceWorkerVersion::Observer {
base::OnceClosure quit_closure_;
};
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, RendererCrash) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, RendererCrash) {
// Start a worker.
StartServerAndNavigateToSetup();
RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread,
@@ -2993,7 +3075,7 @@ static int CountRenderProcessHosts() {
return RenderProcessHost::GetCurrentRenderProcessCountForTesting();
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, Registration) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBlackBoxBrowserTest, Registration) {
StartServerAndNavigateToSetup();
// Close the only window to be sure we're not re-using its RenderProcessHost.
shell()->Close();
@@ -3126,7 +3208,7 @@ class ServiceWorkerVersionBrowserV8FullCodeCacheTest
size_t metadata_size_ = 0;
};
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8FullCodeCacheTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserV8FullCodeCacheTest,
FullCode) {
StartServerAndNavigateToSetup();
RunOnIOThread(base::BindOnce(&self::SetUpRegistrationAndListenerOnIOThread,
@@ -3223,7 +3305,7 @@ class CacheStorageSideDataSizeChecker
blob_handle->get()->ReadSideData(base::BindOnce(
[](scoped_refptr<storage::BlobHandle> blob_handle, int* result,
base::OnceClosure continuation,
- const base::Optional<std::vector<uint8_t>>& data) {
+ const base::Optional<mojo_base::BigBuffer> data) {
*result = data ? data->size() : 0;
std::move(continuation).Run();
},
@@ -3310,7 +3392,7 @@ const char ServiceWorkerV8CodeCacheForCacheStorageTest::kWorkerUrl[] =
const char ServiceWorkerV8CodeCacheForCacheStorageTest::kScriptUrl[] =
"/service_worker/v8_cache_test.js";
-IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CodeCacheForCacheStorageTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerV8CodeCacheForCacheStorageTest,
V8CacheOnCacheStorage) {
RegisterAndActivateServiceWorker();
@@ -3338,7 +3420,7 @@ class ServiceWorkerV8CodeCacheForCacheStorageNoneTest
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerV8CodeCacheForCacheStorageNoneTest);
};
-IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CodeCacheForCacheStorageNoneTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerV8CodeCacheForCacheStorageNoneTest,
V8CacheOnCacheStorage) {
RegisterAndActivateServiceWorker();
@@ -3417,8 +3499,6 @@ class ServiceWorkerCodeCacheStrategyTestBase : public ServiceWorkerBrowserTest {
}
}
- base::test::ScopedFeatureList feature_list_;
-
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCodeCacheStrategyTestBase);
};
@@ -3442,11 +3522,16 @@ class ServiceWorkerCodeCacheStrategyDontGenerateTest
feature_list_.InitAndEnableFeatureWithParameters(
blink::features::kServiceWorkerAggressiveCodeCache,
{{blink::kServiceWorkerEagerCodeCacheStrategy, "dontgenerate"}});
- ServiceWorkerCodeCacheStrategyTestBase::SetUp();
+ // Call ContentBrowserTest::SetUp() to avoid initializing |feature_list_|
+ // twice.
+ // TODO(crbug.com/967272): Change this to call
+ // ServiceWorkerCodeCacheStrategyTestBase::SetUp() once we fully ship
+ // off-the-main-thread script fetch.
+ ContentBrowserTest::SetUp();
}
};
-IN_PROC_BROWSER_TEST_F(ServiceWorkerCodeCacheStrategyDontGenerateTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerCodeCacheStrategyDontGenerateTest,
DontGenerate) {
NavigateToTestPage();
InitiateEventsToCacheScript();
@@ -3462,11 +3547,16 @@ class ServiceWorkerCodeCacheStrategyInstallEventTest
feature_list_.InitAndEnableFeatureWithParameters(
blink::features::kServiceWorkerAggressiveCodeCache,
{{blink::kServiceWorkerEagerCodeCacheStrategy, "installevent"}});
- ServiceWorkerCodeCacheStrategyTestBase::SetUp();
+ // Call ContentBrowserTest::SetUp() to avoid initializing |feature_list_|
+ // twice.
+ // TODO(crbug.com/967272): Change this to call
+ // ServiceWorkerCodeCacheStrategyTestBase::SetUp() once we fully ship
+ // off-the-main-thread script fetch.
+ ContentBrowserTest::SetUp();
}
};
-IN_PROC_BROWSER_TEST_F(ServiceWorkerCodeCacheStrategyInstallEventTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerCodeCacheStrategyInstallEventTest,
GenerateInInstallEvent) {
NavigateToTestPage();
InitiateEventsToCacheScript();
@@ -3482,11 +3572,16 @@ class ServiceWorkerCodeCacheStrategyIdleTaskTest
feature_list_.InitAndEnableFeatureWithParameters(
blink::features::kServiceWorkerAggressiveCodeCache,
{{blink::kServiceWorkerEagerCodeCacheStrategy, "idletask"}});
- ServiceWorkerCodeCacheStrategyTestBase::SetUp();
+ // Call ContentBrowserTest::SetUp() to avoid initializing |feature_list_|
+ // twice.
+ // TODO(crbug.com/967272): Change this to call
+ // ServiceWorkerCodeCacheStrategyTestBase::SetUp() once we fully ship
+ // off-the-main-thread script fetch.
+ ContentBrowserTest::SetUp();
}
};
-IN_PROC_BROWSER_TEST_F(ServiceWorkerCodeCacheStrategyIdleTaskTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerCodeCacheStrategyIdleTaskTest,
GenerateInIdleTask) {
NavigateToTestPage();
InitiateEventsToCacheScript();
@@ -3498,7 +3593,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerCodeCacheStrategyIdleTaskTest,
// Test that generating and storing code cache in idle tasks doesn't corrupt
// cache entry when Cache#put() is called twice asynchronously.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerCodeCacheStrategyIdleTaskTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerCodeCacheStrategyIdleTaskTest,
CacheScriptTwice) {
const char kCachedTwiceUrl[] =
"/service_worker/code_cache_strategy_test_script.js?cached_twice";
@@ -3566,7 +3661,7 @@ class ServiceWorkerDisableWebSecurityTest : public ServiceWorkerBrowserTest {
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDisableWebSecurityTest);
};
-IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerDisableWebSecurityTest,
GetRegistrationNoCrash) {
StartServerAndNavigateToSetup();
const char kPageUrl[] =
@@ -3575,14 +3670,14 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest,
RunTestWithCrossOriginURL(kPageUrl, kScopeUrl);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest, RegisterNoCrash) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerDisableWebSecurityTest, RegisterNoCrash) {
StartServerAndNavigateToSetup();
const char kPageUrl[] = "/service_worker/disable_web_security_register.html";
const char kScopeUrl[] = "/service_worker/";
RunTestWithCrossOriginURL(kPageUrl, kScopeUrl);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest, UnregisterNoCrash) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerDisableWebSecurityTest, UnregisterNoCrash) {
StartServerAndNavigateToSetup();
const char kPageUrl[] =
"/service_worker/disable_web_security_unregister.html";
@@ -3592,7 +3687,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest, UnregisterNoCrash) {
RunTestWithCrossOriginURL(kPageUrl, kScopeUrl);
}
-IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest, UpdateNoCrash) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerDisableWebSecurityTest, UpdateNoCrash) {
StartServerAndNavigateToSetup();
const char kPageUrl[] = "/service_worker/disable_web_security_update.html";
const char kScopeUrl[] = "/service_worker/scope/";
@@ -3678,7 +3773,7 @@ class ServiceWorkerURLLoaderThrottleTest : public ServiceWorkerBrowserTest {
// Test that the throttles can inject headers during navigation that are
// observable inside the service worker's fetch event.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerURLLoaderThrottleTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerURLLoaderThrottleTest,
FetchEventForNavigationHasThrottledRequest) {
// Add a throttle which injects a header.
ThrottlingContentBrowserClient content_browser_client;
@@ -3713,7 +3808,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerURLLoaderThrottleTest,
}
// Test that redirects by throttles occur before service worker interception.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerURLLoaderThrottleTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerURLLoaderThrottleTest,
RedirectOccursBeforeFetchEvent) {
// Add a throttle which performs a redirect.
ThrottlingContentBrowserClient content_browser_client;
@@ -3757,7 +3852,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerURLLoaderThrottleTest,
// Test that the headers injected by throttles during navigation are
// present in the network request in the case of network fallback.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
ServiceWorkerURLLoaderThrottleTest,
NavigationHasThrottledRequestHeadersAfterNetworkFallback) {
// Add a throttle which injects a header.
@@ -3788,7 +3883,7 @@ IN_PROC_BROWSER_TEST_F(
// Test that the headers injected by throttles during navigation are
// present in the navigation preload request.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerURLLoaderThrottleTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerURLLoaderThrottleTest,
NavigationPreloadHasThrottledRequestHeaders) {
// Add a throttle which injects a header.
ThrottlingContentBrowserClient content_browser_client;
@@ -3817,4 +3912,61 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerURLLoaderThrottleTest,
SetBrowserClientForTesting(old_content_browser_client);
}
+// TODO(crbug.com/967272): Remove following parameterized tests once we fully
+// ship off-the-main-thread script fetch.
+
+INSTANTIATE_TEST_SUITE_P(ServiceWorkerBrowserTestOnMainThreadFetch,
+ ServiceWorkerBrowserTest,
+ testing::Bool());
+
+INSTANTIATE_TEST_SUITE_P(ServiceWorkerVersionBrowserTestOnMainThreadFetch,
+ ServiceWorkerVersionBrowserTest,
+ testing::Bool());
+
+INSTANTIATE_TEST_SUITE_P(ServiceWorkerNavigationPreloadTestOnMainThreadFetch,
+ ServiceWorkerNavigationPreloadTest,
+ testing::Bool());
+
+INSTANTIATE_TEST_SUITE_P(ServiceWorkerDisableWebSecurityTestOnMainThreadFetch,
+ ServiceWorkerDisableWebSecurityTest,
+ testing::Bool());
+
+INSTANTIATE_TEST_SUITE_P(ServiceWorkerURLLoaderThrottleTestOnMainThreadFetch,
+ ServiceWorkerURLLoaderThrottleTest,
+ testing::Bool());
+
+INSTANTIATE_TEST_SUITE_P(ServiceWorkerBlackBoxBrowserTestOnMainThreadFetch,
+ ServiceWorkerBlackBoxBrowserTest,
+ testing::Bool());
+
+INSTANTIATE_TEST_SUITE_P(
+ ServiceWorkerCodeCacheStrategyDontGenerateTestOnMainThreadFetch,
+ ServiceWorkerCodeCacheStrategyDontGenerateTest,
+ testing::Bool());
+
+INSTANTIATE_TEST_SUITE_P(
+ ServiceWorkerCodeCacheStrategyIdleTaskTestOnMainThreadFetch,
+ ServiceWorkerCodeCacheStrategyIdleTaskTest,
+ testing::Bool());
+
+INSTANTIATE_TEST_SUITE_P(
+ ServiceWorkerCodeCacheStrategyInstallEventTestOnMainThreadFetch,
+ ServiceWorkerCodeCacheStrategyInstallEventTest,
+ testing::Bool());
+
+INSTANTIATE_TEST_SUITE_P(
+ ServiceWorkerV8CodeCacheForCacheStorageNoneTestOnMainThreadFetch,
+ ServiceWorkerV8CodeCacheForCacheStorageNoneTest,
+ testing::Bool());
+
+INSTANTIATE_TEST_SUITE_P(
+ ServiceWorkerV8CodeCacheForCacheStorageTestOnMainThreadFetch,
+ ServiceWorkerV8CodeCacheForCacheStorageTest,
+ testing::Bool());
+
+INSTANTIATE_TEST_SUITE_P(
+ ServiceWorkerVersionBrowserV8FullCodeCacheTestOnMainThreadFetch,
+ ServiceWorkerVersionBrowserV8FullCodeCacheTest,
+ testing::Bool());
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_cache_writer.cc b/chromium/content/browser/service_worker/service_worker_cache_writer.cc
index 8e7e9f70f1a..1935f81e61c 100644
--- a/chromium/content/browser/service_worker/service_worker_cache_writer.cc
+++ b/chromium/content/browser/service_worker/service_worker_cache_writer.cc
@@ -597,8 +597,15 @@ int ServiceWorkerCacheWriter::WriteInfoToResponseWriter(
int ServiceWorkerCacheWriter::WriteInfo(
scoped_refptr<HttpResponseInfoIOBuffer> response_info) {
- if (write_observer_)
- write_observer_->WillWriteInfo(response_info);
+ if (!write_observer_)
+ return WriteInfoToResponseWriter(std::move(response_info));
+
+ int result = write_observer_->WillWriteInfo(response_info);
+ if (result != net::OK) {
+ DCHECK_NE(result, net::ERR_IO_PENDING);
+ state_ = STATE_DONE;
+ return result;
+ }
return WriteInfoToResponseWriter(std::move(response_info));
}
diff --git a/chromium/content/browser/service_worker/service_worker_cache_writer.h b/chromium/content/browser/service_worker/service_worker_cache_writer.h
index f4cb33f0f5c..d0b74fb8b47 100644
--- a/chromium/content/browser/service_worker/service_worker_cache_writer.h
+++ b/chromium/content/browser/service_worker/service_worker_cache_writer.h
@@ -45,7 +45,8 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter {
class WriteObserver {
public:
// Called before response info is written to storage.
- virtual void WillWriteInfo(
+ // Returns net::OK if success. Other values are treated as errors.
+ virtual int WillWriteInfo(
scoped_refptr<HttpResponseInfoIOBuffer> response_info) = 0;
// Called before response data is written to storage.
diff --git a/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc b/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc
index df863944d84..665db01662e 100644
--- a/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc
@@ -30,9 +30,10 @@ class MockServiceWorkerCacheWriterObserver
MockServiceWorkerCacheWriterObserver() : data_length_(0), result_(net::OK) {}
~MockServiceWorkerCacheWriterObserver() {}
- void WillWriteInfo(
+ int WillWriteInfo(
scoped_refptr<HttpResponseInfoIOBuffer> response_info) override {
response_info_ = std::move(response_info);
+ return net::OK;
}
int WillWriteData(scoped_refptr<net::IOBuffer> data,
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 a1dee2e6cb2..27620052d3b 100644
--- a/chromium/content/browser/service_worker/service_worker_client_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_client_utils.cc
@@ -37,7 +37,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/child_process_host.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
+#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom.h"
#include "ui/base/mojo/window_open_disposition.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -257,7 +257,7 @@ void OpenWindowOnUI(
GetContentClient()->browser()->OverrideNavigationParams(
site_instance, &params.transition, &params.is_renderer_initiated,
- &params.referrer);
+ &params.referrer, &params.initiator_origin);
// End of RequestOpenURL copy.
diff --git a/chromium/content/browser/service_worker/service_worker_clients_api_browsertest.cc b/chromium/content/browser/service_worker/service_worker_clients_api_browsertest.cc
index e24d7bd1558..1a4425adb8e 100644
--- a/chromium/content/browser/service_worker/service_worker_clients_api_browsertest.cc
+++ b/chromium/content/browser/service_worker/service_worker_clients_api_browsertest.cc
@@ -94,12 +94,11 @@ class ServiceWorkerClientsContentBrowserClient
return allow_open_url_;
}
- void OpenURL(
- SiteInstance* site_instance,
- const OpenURLParams& params,
- const base::RepeatingCallback<void(WebContents*)>& callback) override {
+ void OpenURL(SiteInstance* site_instance,
+ const OpenURLParams& params,
+ base::OnceCallback<void(WebContents*)> callback) override {
opened_url_ = params.url;
- callback.Run(nullptr);
+ std::move(callback).Run(nullptr);
if (opened_url_callback_)
std::move(opened_url_callback_).Run();
}
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 c4ab8921058..b053bdd49fa 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_core.cc
@@ -72,21 +72,49 @@ void CheckFetchHandlerOfInstalledServiceWorker(
: ServiceWorkerCapability::SERVICE_WORKER_NO_FETCH_HANDLER);
}
+// Waits until a |registration| is deleted and calls |callback|.
+class RegistrationDeletionListener
+ : public ServiceWorkerRegistration::Listener {
+ public:
+ RegistrationDeletionListener(
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ base::OnceClosure callback)
+ : registration_(std::move(registration)), callback_(std::move(callback)) {
+ DCHECK(!registration_->is_deleted());
+ registration_->AddListener(this);
+ }
+
+ virtual ~RegistrationDeletionListener() {
+ registration_->RemoveListener(this);
+ }
+
+ void OnRegistrationDeleted(ServiceWorkerRegistration* registration) override {
+ if (callback_)
+ std::move(callback_).Run();
+ }
+
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ base::OnceClosure callback_;
+};
+
// This function will call |callback| after |*expected_calls| reaches zero or
// when an error occurs. In case of an error, |*expected_calls| is set to -1
// to prevent calling |callback| again.
void SuccessReportingCallback(
int* expected_calls,
+ std::vector<std::unique_ptr<RegistrationDeletionListener>>* listeners,
const base::RepeatingCallback<void(blink::ServiceWorkerStatusCode)>&
callback,
blink::ServiceWorkerStatusCode status) {
if (status != blink::ServiceWorkerStatusCode::kOk) {
*expected_calls = -1;
+ listeners->clear();
callback.Run(blink::ServiceWorkerStatusCode::kErrorFailed);
return;
}
(*expected_calls)--;
if (*expected_calls == 0) {
+ listeners->clear();
callback.Run(blink::ServiceWorkerStatusCode::kOk);
}
}
@@ -172,36 +200,6 @@ class ClearAllServiceWorkersHelper
DISALLOW_COPY_AND_ASSIGN(ClearAllServiceWorkersHelper);
};
-class RegistrationDeletionListener
- : public ServiceWorkerRegistration::Listener {
- public:
- // Wait until a |registration| is deleted and call |callback|.
- static void WaitForDeletion(
- scoped_refptr<ServiceWorkerRegistration> registration,
- base::OnceClosure callback) {
- DCHECK(!registration->is_deleted());
- registration->AddListener(
- new RegistrationDeletionListener(registration, std::move(callback)));
- }
-
- void OnRegistrationDeleted(ServiceWorkerRegistration* registration) override {
- registration->RemoveListener(this);
- std::move(callback_).Run();
- delete this;
- }
-
- private:
- RegistrationDeletionListener(
- scoped_refptr<ServiceWorkerRegistration> registration,
- base::OnceClosure callback)
- : registration_(std::move(registration)),
- callback_(std::move(callback)) {}
- virtual ~RegistrationDeletionListener() = default;
-
- scoped_refptr<ServiceWorkerRegistration> registration_;
- base::OnceClosure callback_;
-};
-
} // namespace
const base::FilePath::CharType
@@ -459,20 +457,26 @@ void ServiceWorkerContextCore::DidGetRegistrationsForDeleteForOrigin(
}
int* expected_calls = new int(2 * registrations.size());
+ auto* listeners =
+ new std::vector<std::unique_ptr<RegistrationDeletionListener>>();
+
// The barrier must be executed twice for each registration: once for
// unregistration and once for deletion. It will call |callback| immediately
// if an error occurs.
base::RepeatingCallback<void(blink::ServiceWorkerStatusCode)> barrier =
base::BindRepeating(SuccessReportingCallback, base::Owned(expected_calls),
+ base::Owned(listeners),
base::AdaptCallbackForRepeating(std::move(callback)));
for (const auto& registration : registrations) {
DCHECK(registration);
- if (!registration->is_deleted()) {
- RegistrationDeletionListener::WaitForDeletion(
- registration,
- base::BindOnce(barrier, blink::ServiceWorkerStatusCode::kOk));
- } else {
- barrier.Run(blink::ServiceWorkerStatusCode::kOk);
+ if (*expected_calls != -1) {
+ if (!registration->is_deleted()) {
+ listeners->emplace_back(std::make_unique<RegistrationDeletionListener>(
+ registration,
+ base::BindOnce(barrier, blink::ServiceWorkerStatusCode::kOk)));
+ } else {
+ barrier.Run(blink::ServiceWorkerStatusCode::kOk);
+ }
}
job_coordinator_->Abort(registration->scope());
UnregisterServiceWorker(registration->scope(), barrier);
@@ -786,14 +790,14 @@ void ServiceWorkerContextCore::OnReportConsoleMessage(
const GURL& source_url) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// NOTE: This differs slightly from
- // RenderFrameHostImpl::OnDidAddMessageToConsole, which also asks the
+ // RenderFrameHostImpl::DidAddMessageToConsole, which also asks the
// content embedder whether to classify the message as a builtin component.
// This is called on the IO thread, though, so we can't easily get a
// BrowserContext and call ContentBrowserClient::IsBuiltinComponent().
const bool is_builtin_component = HasWebUIScheme(source_url);
- LogConsoleMessage(ConsoleMessageLevelToLogSeverity(message_level), message,
- line_number, is_builtin_component, wrapper_->is_incognito(),
+ LogConsoleMessage(message_level, message, line_number, is_builtin_component,
+ wrapper_->is_incognito(),
base::UTF8ToUTF16(source_url.spec()));
observer_list_->Notify(
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 063223cb663..b06af8e835c 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.h
+++ b/chromium/content/browser/service_worker/service_worker_context_core.h
@@ -45,7 +45,6 @@ class ServiceWorkerContextWrapper;
class ServiceWorkerJobCoordinator;
class ServiceWorkerProviderHost;
class ServiceWorkerRegistration;
-class ServiceWorkerStorage;
class URLLoaderFactoryGetter;
// This class manages data associated with service workers.
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 de8d4ac218a..54b8e3ec499 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
@@ -39,9 +39,6 @@ class ServiceWorkerContextCoreTest : public testing::Test,
ServiceWorkerContextCore* context() { return helper_->context(); }
- TestBrowserThreadBundle thread_bundle_;
- std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
-
// Runs until |registration| has an active version and it is activated.
void RunUntilActivatedVersion(ServiceWorkerRegistration* registration) {
if (registration->active_version() &&
@@ -127,6 +124,8 @@ class ServiceWorkerContextCoreTest : public testing::Test,
}
private:
+ TestBrowserThreadBundle thread_bundle_;
+ std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
GURL scope_for_wait_for_activated_;
base::OnceClosure quit_closure_for_wait_for_activated_;
bool is_observing_context_ = false;
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 1946997e486..28e6427eeeb 100644
--- a/chromium/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
@@ -375,6 +375,9 @@ TEST_F(ServiceWorkerContextTest, NoControlleesObserver) {
auto version = base::MakeRefCounted<ServiceWorkerVersion>(
registration.get(), script_url, blink::mojom::ScriptType::kClassic,
2l /* dummy version id */, context()->AsWeakPtr());
+ version->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version->SetStatus(ServiceWorkerVersion::ACTIVATED);
ServiceWorkerRemoteProviderEndpoint endpoint;
base::WeakPtr<ServiceWorkerProviderHost> host =
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 6be30b24cc3..dd17346abfc 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -22,6 +22,7 @@
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_process_manager.h"
#include "content/browser/service_worker/service_worker_quota_client.h"
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 7ca2858c412..a0fa38e235a 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
@@ -10,12 +10,12 @@
#include "base/bind.h"
#include "base/trace_event/trace_event.h"
#include "components/offline_pages/buildflags/buildflags.h"
+#include "content/browser/navigation_subresource_loader_params.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_navigation_loader.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_registration.h"
-#include "content/common/navigation_subresource_loader_params.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
@@ -98,7 +98,6 @@ ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
bool keepalive,
ResourceType resource_type,
blink::mojom::RequestContextType request_context_type,
- network::mojom::RequestContextFrameType frame_type,
scoped_refptr<network::ResourceRequestBody> body)
: context_(std::move(context)),
provider_host_(std::move(provider_host)),
@@ -109,7 +108,6 @@ ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
integrity_(integrity),
keepalive_(keepalive),
request_context_type_(request_context_type),
- frame_type_(frame_type),
body_(std::move(body)),
force_update_started_(false),
weak_factory_(this) {
@@ -255,6 +253,7 @@ void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
stripped_url_ = net::SimplifyUrlForRequest(url);
provider_host_->UpdateUrls(stripped_url_, site_for_cookies);
+ registration_lookup_start_time_ = base::TimeTicks::Now();
context_->storage()->FindRegistrationForDocument(
stripped_url_, base::BindOnce(&ServiceWorkerControlleeRequestHandler::
DidLookupRegistrationForMainResource,
@@ -272,6 +271,9 @@ void ServiceWorkerControlleeRequestHandler::
if (!loader())
return;
+ ServiceWorkerMetrics::RecordLookupRegistrationTime(
+ status, base::TimeTicks::Now() - registration_lookup_start_time_);
+
if (status != blink::ServiceWorkerStatusCode::kOk) {
loader()->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
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 65b2d92d3db..c6febed66e0 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
@@ -19,7 +19,6 @@
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/resource_type.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/mojom/fetch/fetch_api_request.mojom.h"
#include "url/gurl.h"
@@ -51,7 +50,6 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler final
bool keepalive,
ResourceType resource_type,
blink::mojom::RequestContextType request_context_type,
- network::mojom::RequestContextFrameType frame_type,
scoped_refptr<network::ResourceRequestBody> body);
~ServiceWorkerControlleeRequestHandler() override;
@@ -133,11 +131,11 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler final
std::string integrity_;
const bool keepalive_;
blink::mojom::RequestContextType request_context_type_;
- network::mojom::RequestContextFrameType frame_type_;
scoped_refptr<network::ResourceRequestBody> body_;
ResourceContext* resource_context_;
GURL stripped_url_;
bool force_update_started_;
+ base::TimeTicks registration_lookup_start_time_;
base::WeakPtrFactory<ServiceWorkerControlleeRequestHandler> weak_factory_;
diff --git a/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
index f14302dd4a6..a58aeeef92a 100644
--- a/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -12,6 +12,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/run_loop.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "components/offline_pages/buildflags/buildflags.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
@@ -29,7 +30,6 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/public/cpp/resource_request_body.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
@@ -63,7 +63,6 @@ class ServiceWorkerControlleeRequestHandlerTest : public testing::Test {
false /* keepalive */,
type,
blink::mojom::RequestContextType::HYPERLINK,
- network::mojom::RequestContextFrameType::kTopLevel,
scoped_refptr<network::ResourceRequestBody>())) {}
ServiceWorkerNavigationLoader* MaybeCreateLoader() {
@@ -164,6 +163,91 @@ class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
}
};
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, Basic) {
+ base::HistogramTester histogram_tester;
+
+ // Prepare a valid version and registration.
+ version_->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration_->SetActiveVersion(version_);
+ {
+ base::RunLoop loop;
+ context()->storage()->StoreRegistration(
+ registration_.get(), version_.get(),
+ base::BindOnce(
+ [](base::OnceClosure closure,
+ blink::ServiceWorkerStatusCode status) {
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
+ std::move(closure).Run();
+ },
+ loop.QuitClosure()));
+ loop.Run();
+ }
+
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LookupRegistration.MainResource.Time.Exists", 0);
+
+ // Conduct a main resource load.
+ ServiceWorkerRequestTestResources test_resources(
+ this, GURL("https://host/scope/doc"), ResourceType::kMainFrame);
+ ServiceWorkerNavigationLoader* loader = test_resources.MaybeCreateLoader();
+
+ EXPECT_FALSE(loader->ShouldFallbackToNetwork());
+ EXPECT_FALSE(loader->ShouldForwardToServiceWorker());
+ EXPECT_FALSE(version_->HasControllee());
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(loader->ShouldFallbackToNetwork());
+ EXPECT_TRUE(loader->ShouldForwardToServiceWorker());
+ EXPECT_TRUE(version_->HasControllee());
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LookupRegistration.MainResource.Time.Exists", 1);
+
+ test_resources.ResetHandler();
+}
+
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, DoesNotExist) {
+ base::HistogramTester histogram_tester;
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LookupRegistration.MainResource.Time.DoesNotExist", 0);
+
+ // No version and registration exists in the scope.
+
+ // Conduct a main resource load.
+ ServiceWorkerRequestTestResources test_resources(
+ this, GURL("https://host/scope/doc"), ResourceType::kMainFrame);
+ ServiceWorkerNavigationLoader* loader = test_resources.MaybeCreateLoader();
+ EXPECT_FALSE(loader);
+
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LookupRegistration.MainResource.Time.DoesNotExist", 1);
+
+ test_resources.ResetHandler();
+}
+
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, Error) {
+ base::HistogramTester histogram_tester;
+
+ // Disabling the storage makes looking up the registration return an error.
+ context()->storage()->Disable();
+
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LookupRegistration.MainResource.Time.Error", 0);
+
+ // Conduct a main resource load.
+ ServiceWorkerRequestTestResources test_resources(
+ this, GURL("https://host/scope/doc"), ResourceType::kMainFrame);
+ ServiceWorkerNavigationLoader* loader = test_resources.MaybeCreateLoader();
+ EXPECT_FALSE(loader);
+
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LookupRegistration.MainResource.Time.Error", 1);
+
+ test_resources.ResetHandler();
+}
+
TEST_F(ServiceWorkerControlleeRequestHandlerTest, DisallowServiceWorker) {
ServiceWorkerTestContentBrowserClient test_browser_client;
ContentBrowserClient* old_browser_client =
diff --git a/chromium/content/browser/service_worker/service_worker_database.cc b/chromium/content/browser/service_worker/service_worker_database.cc
index ba5c33ea409..da5dc494442 100644
--- a/chromium/content/browser/service_worker/service_worker_database.cc
+++ b/chromium/content/browser/service_worker/service_worker_database.cc
@@ -1506,8 +1506,15 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ParseRegistrationData(
out->navigation_preload_state.header = state.header();
}
- for (uint32_t feature : data.used_features())
- out->used_features.insert(feature);
+ for (uint32_t feature : data.used_features()) {
+ // Add features that are valid WebFeature values. Invalid values can
+ // legitimately exist on disk when a version of Chrome had the feature and
+ // wrote the data but the value was removed from the WebFeature enum in a
+ // later version of Chrome.
+ auto web_feature = static_cast<blink::mojom::WebFeature>(feature);
+ if (IsKnownEnumValue(web_feature))
+ out->used_features.insert(web_feature);
+ }
if (data.has_script_type()) {
auto value = data.script_type();
@@ -1574,8 +1581,8 @@ void ServiceWorkerDatabase::WriteRegistrationDataInBatch(
state->set_enabled(registration.navigation_preload_state.enabled);
state->set_header(registration.navigation_preload_state.header);
- for (uint32_t feature : registration.used_features)
- data.add_used_features(feature);
+ for (blink::mojom::WebFeature web_feature : registration.used_features)
+ data.add_used_features(static_cast<uint32_t>(web_feature));
data.set_script_type(
static_cast<ServiceWorkerRegistrationData_ServiceWorkerScriptType>(
diff --git a/chromium/content/browser/service_worker/service_worker_database.h b/chromium/content/browser/service_worker/service_worker_database.h
index 79f82fef3e7..0d2625803b5 100644
--- a/chromium/content/browser/service_worker/service_worker_database.h
+++ b/chromium/content/browser/service_worker/service_worker_database.h
@@ -24,6 +24,7 @@
#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 "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -82,7 +83,7 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
base::Optional<blink::TrialTokenValidator::FeatureToTokensMap>
origin_trial_tokens;
blink::mojom::NavigationPreloadState navigation_preload_state;
- std::set<uint32_t> used_features;
+ std::set<blink::mojom::WebFeature> used_features;
// Not populated until ServiceWorkerStorage::StoreRegistration is called.
int64_t resources_total_size_bytes;
@@ -430,6 +431,7 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest,
UserData_UninitializedDatabase);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, DestroyDatabase);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, InvalidWebFeature);
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDatabase);
};
diff --git a/chromium/content/browser/service_worker/service_worker_database_unittest.cc b/chromium/content/browser/service_worker/service_worker_database_unittest.cc
index 5cc0a66557c..4a7ec0bd3a5 100644
--- a/chromium/content/browser/service_worker/service_worker_database_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_database_unittest.cc
@@ -636,7 +636,9 @@ TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
data.script = URL(origin, "/resource1");
data.version_id = 200;
data.resources_total_size_bytes = 10939 + 200;
- data.used_features = {124, 901, 1019};
+ data.used_features = {blink::mojom::WebFeature::kNavigatorVendor,
+ blink::mojom::WebFeature::kLinkRelPreload,
+ blink::mojom::WebFeature::kCSSFilterInvert};
std::vector<Resource> resources;
resources.push_back(CreateResource(1, URL(origin, "/resource1"), 10939));
@@ -776,7 +778,9 @@ TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
data.script = URL(origin, "/resource1");
data.version_id = 200;
data.resources_total_size_bytes = 10 + 11;
- data.used_features = {124, 901, 1019};
+ data.used_features = {blink::mojom::WebFeature::kNavigatorVendor,
+ blink::mojom::WebFeature::kLinkRelPreload,
+ blink::mojom::WebFeature::kCSSFilterInvert};
std::vector<Resource> resources1;
resources1.push_back(CreateResource(1, URL(origin, "/resource1"), 10));
@@ -807,7 +811,10 @@ TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
updated_data.script = URL(origin, "/resource3");
updated_data.version_id = data.version_id + 1;
updated_data.resources_total_size_bytes = 12 + 13;
- updated_data.used_features = {109, 421, 9101};
+ updated_data.used_features = {
+ blink::mojom::WebFeature::kFormElement,
+ blink::mojom::WebFeature::kDocumentExitPointerLock,
+ blink::mojom::WebFeature::kAdClick};
updated_data.script_type = blink::mojom::ScriptType::kModule;
updated_data.update_via_cache =
blink::mojom::ServiceWorkerUpdateViaCache::kAll;
@@ -2191,4 +2198,49 @@ TEST(ServiceWorkerDatabaseTest, Corruption_GetRegistrationsForOrigin) {
ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED, 1);
}
+// Test that invalid WebFeatures on disk are ignored when reading a
+// registration. See https://crbug.com/965944.
+TEST(ServiceWorkerDatabaseTest, InvalidWebFeature) {
+ std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
+
+ // Prepare a registration proto that has invalid features.
+ ServiceWorkerRegistrationData data;
+ data.set_registration_id(1);
+ data.set_scope_url("https://example.com");
+ data.set_script_url("https://example.com/sw");
+ data.set_version_id(1);
+ data.set_is_active(true);
+ data.set_has_fetch_handler(true);
+ data.set_last_update_check_time(base::Time::Now().ToInternalValue());
+
+ data.add_used_features(
+ static_cast<uint32_t>(blink::mojom::WebFeature::kFetch));
+ // Add a removed feature.
+ data.add_used_features(2067);
+ data.add_used_features(
+ static_cast<uint32_t>(blink::mojom::WebFeature::kBackgroundSync));
+ // Add an out of range feature.
+ data.add_used_features(
+ static_cast<uint32_t>(blink::mojom::WebFeature::kNumberOfFeatures) + 11);
+ data.add_used_features(
+ static_cast<uint32_t>(blink::mojom::WebFeature::kNetInfoType));
+
+ database->next_avail_registration_id_ = 2;
+ database->next_avail_version_id_ = 2;
+
+ // Write the serialization.
+ std::string value;
+ ASSERT_TRUE(data.SerializeToString(&value));
+
+ // Parse the serialized data. The invalid features should be ignored.
+ RegistrationData registration;
+ ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->ParseRegistrationData(value, &registration));
+ std::set<blink::mojom::WebFeature> expect = {
+ blink::mojom::WebFeature::kFetch,
+ blink::mojom::WebFeature::kBackgroundSync,
+ blink::mojom::WebFeature::kNetInfoType};
+ EXPECT_EQ(expect, registration.used_features);
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index 5f8b5f3a96e..1cf8321cdf8 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -128,8 +128,8 @@ class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
client_->OnUploadProgress(current_position, total_size,
std::move(ack_callback));
}
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {
- client_->OnReceiveCachedMetadata(data);
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override {
+ client_->OnReceiveCachedMetadata(std::move(data));
}
void OnTransferSizeUpdated(int32_t transfer_size_diff) override {
client_->OnTransferSizeUpdated(transfer_size_diff);
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 033dea5e3e5..16232a7b365 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
@@ -85,10 +85,12 @@ void ServiceWorkerInstalledScriptLoader::OnHttpInfoRead(
*info);
}
- ServiceWorkerUtils::SendHttpResponseInfoToClient(
+ auto response = ServiceWorkerUtils::CreateResourceResponseHeadAndMetadata(
info, options_, request_start_, base::TimeTicks::Now(),
- http_info->response_data_size, client_.get());
-
+ http_info->response_data_size);
+ client_->OnReceiveResponse(std::move(response.head));
+ if (!response.metadata.empty())
+ client_->OnReceiveCachedMetadata(std::move(response.metadata));
client_->OnStartLoadingResponseBody(std::move(body_handle_));
// We continue in OnFinished().
}
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 7e35d7ae938..60f6c898e13 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
@@ -168,13 +168,21 @@ void ServiceWorkerInstalledScriptsSender::Abort(
kResponseReaderError:
owner_->SetStartWorkerStatusCode(
blink::ServiceWorkerStatusCode::kErrorDiskCache);
- // Abort the worker by deleting from the registration since the data was
- // corrupted.
+
+ // Break the Mojo connection with the renderer so the service worker knows
+ // to stop waiting for the script data to arrive and terminate. Note that
+ // DeleteVersion() below sends the Stop IPC, but without breaking the
+ // connection here, the service worker would be blocked waiting for the
+ // script data and won't respond to Stop.
+ manager_.reset();
+ binding_.Close();
+
+ // Delete the registration data since the data was corrupted.
if (owner_->context()) {
ServiceWorkerRegistration* registration =
owner_->context()->GetLiveRegistration(owner_->registration_id());
- // This ends up with destructing |this|.
- registration->DeleteVersion(owner_);
+ // This can destruct |this|.
+ registration->ForceDelete();
}
return;
case ServiceWorkerInstalledScriptReader::FinishedReason::
@@ -182,9 +190,9 @@ void ServiceWorkerInstalledScriptsSender::Abort(
case ServiceWorkerInstalledScriptReader::FinishedReason::kConnectionError:
case ServiceWorkerInstalledScriptReader::FinishedReason::
kMetaDataSenderError:
- // Notify the renderer that a connection failure happened. Usually the
- // failure means the renderer gets killed, and the error handler of
- // EmbeddedWorkerInstance is invoked soon.
+ // Break the Mojo connection with the renderer. This usually causes the
+ // service worker to stop, and the error handler of EmbeddedWorkerInstance
+ // is invoked soon.
manager_.reset();
binding_.Close();
return;
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 6339be13e72..dfea2133628 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
@@ -327,7 +327,6 @@ ServiceWorkerInternalsUI::ServiceWorkerInternalsUI(WebUI* web_ui)
IDR_SERVICE_WORKER_INTERNALS_CSS);
source->SetDefaultResource(IDR_SERVICE_WORKER_INTERNALS_HTML);
source->DisableDenyXFrameOptions();
- source->UseGzip();
BrowserContext* browser_context =
web_ui->GetWebContents()->GetBrowserContext();
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 fc6453214f1..1a1e55efabe 100644
--- a/chromium/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
@@ -14,6 +14,7 @@
#include "base/stl_util.h"
#include "base/test/test_simple_task_runner.h"
#include "base/time/time.h"
+#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/fake_embedded_worker_instance_client.h"
@@ -1387,7 +1388,7 @@ TEST_F(ServiceWorkerJobTest, Update_ScriptUrlChanged) {
EXPECT_EQ(nullptr, registration->installing_version());
}
-// Test that update succeeds if the incumbent worker was evicted
+// Test that update fails if the incumbent worker was evicted
// during the update job (this can happen on disk cache failure).
TEST_F(ServiceWorkerJobTest, Update_EvictedIncumbent) {
UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
@@ -1407,24 +1408,19 @@ TEST_F(ServiceWorkerJobTest, Update_EvictedIncumbent) {
// Evict the incumbent during that time.
first_version->StartUpdate();
instance_client->RunUntilStartWorker();
- registration->DeleteVersion(first_version);
+ registration->ForceDelete();
// Finish the update job.
instance_client->UnblockStartWorker();
base::RunLoop().RunUntilIdle();
// Verify results.
- ASSERT_TRUE(registration->active_version());
- EXPECT_NE(first_version.get(), registration->active_version());
- EXPECT_FALSE(registration->installing_version());
- EXPECT_FALSE(registration->waiting_version());
+ EXPECT_FALSE(registration->GetNewestVersion());
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, first_version->status());
- EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
- registration->active_version()->status());
- ASSERT_EQ(4u, update_helper->attribute_change_log_.size());
- EXPECT_TRUE(update_helper->update_found_);
+ EXPECT_TRUE(update_helper->attribute_change_log_.empty());
+ EXPECT_FALSE(update_helper->update_found_);
EXPECT_TRUE(update_helper->registration_failed_);
- EXPECT_FALSE(registration->is_uninstalled());
+ EXPECT_TRUE(registration->is_uninstalled());
}
TEST_F(ServiceWorkerJobTest, Update_UninstallingRegistration) {
@@ -1860,7 +1856,7 @@ TEST_F(ServiceWorkerJobTest, AddRegistrationToMatchingProviderHosts) {
base::WeakPtr<ServiceWorkerProviderHost> reserved_client =
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */,
- {} /* web_contents_getter */, &provider_info);
+ FrameTreeNode::kFrameTreeNodeInvalidId, &provider_info);
reserved_client->UpdateUrls(in_scope, in_scope);
// Make an out-scope client.
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.cc b/chromium/content/browser/service_worker/service_worker_metrics.cc
index d091c7f9154..c64213082ef 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.cc
+++ b/chromium/content/browser/service_worker/service_worker_metrics.cc
@@ -124,6 +124,8 @@ const char* EventTypeToSuffix(ServiceWorkerMetrics::EventType event_type) {
return "_LONG_RUNNING_MESSAGE";
case ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_SUCCESS:
return "_BACKGROUND_FETCH_SUCCESS";
+ case ServiceWorkerMetrics::EventType::PERIODIC_SYNC:
+ return "_PERIODIC_SYNC";
}
return "_UNKNOWN";
}
@@ -238,6 +240,8 @@ const char* ServiceWorkerMetrics::EventTypeToString(EventType event_type) {
return "Long Running Message";
case EventType::BACKGROUND_FETCH_SUCCESS:
return "Background Fetch Success";
+ case EventType::PERIODIC_SYNC:
+ return "Periodic Sync";
}
NOTREACHED() << "Got unexpected event type: " << static_cast<int>(event_type);
return "error";
@@ -572,6 +576,10 @@ void ServiceWorkerMetrics::RecordEventDuration(EventType event,
// Since this event is expected to last indefinitely we don't need to log
// how long they actually last.
break;
+ case EventType::PERIODIC_SYNC:
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "ServiceWorker.PeriodicBackgroundSyncEvent.Time", time);
+ break;
case EventType::NAVIGATION_HINT:
// The navigation hint should not be sent as an event.
@@ -630,6 +638,14 @@ void ServiceWorkerMetrics::RecordProcessCreated(bool is_new_process) {
void ServiceWorkerMetrics::RecordStartWorkerTiming(const StartTimes& times,
StartSituation situation) {
+ // This is in-process timing, so process consistency doesn't matter.
+ constexpr base::TimeDelta kMinTime = base::TimeDelta::FromMicroseconds(1);
+ constexpr base::TimeDelta kMaxTime = base::TimeDelta::FromMilliseconds(100);
+ constexpr int kBuckets = 50;
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "ServiceWorker.StartTiming.BrowserThreadHopTime", times.thread_hop_time,
+ kMinTime, kMaxTime, kBuckets);
+
// Bail if the timings across processes weren't consistent.
if (!base::TimeTicks::IsHighResolution() ||
!base::TimeTicks::IsConsistentAcrossProcesses()) {
@@ -811,4 +827,20 @@ void ServiceWorkerMetrics::RecordRegisteredOriginCount(size_t origin_count) {
UMA_HISTOGRAM_COUNTS_1M("ServiceWorker.RegisteredOriginCount", origin_count);
}
+void ServiceWorkerMetrics::RecordLookupRegistrationTime(
+ blink::ServiceWorkerStatusCode status,
+ base::TimeDelta duration) {
+ if (status == blink::ServiceWorkerStatusCode::kOk) {
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.LookupRegistration.MainResource.Time.Exists", duration);
+ } else if (status == blink::ServiceWorkerStatusCode::kErrorNotFound) {
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.LookupRegistration.MainResource.Time.DoesNotExist",
+ duration);
+ } else {
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.LookupRegistration.MainResource.Time.Error", duration);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.h b/chromium/content/browser/service_worker/service_worker_metrics.h
index 98328875887..e09b037866f 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.h
+++ b/chromium/content/browser/service_worker/service_worker_metrics.h
@@ -175,8 +175,9 @@ class ServiceWorkerMetrics {
COOKIE_CHANGE = 30,
LONG_RUNNING_MESSAGE = 31,
BACKGROUND_FETCH_SUCCESS = 32,
+ PERIODIC_SYNC = 33,
// Add new events to record here.
- kMaxValue = BACKGROUND_FETCH_SUCCESS,
+ kMaxValue = PERIODIC_SYNC,
};
// Used for UMA. Append only.
@@ -269,6 +270,9 @@ class ServiceWorkerMetrics {
// The browser received the worker started IPC.
base::TimeTicks local_end;
+
+ // Counts the time overhead of UI/IO thread hops during startup.
+ base::TimeDelta thread_hop_time;
};
// Records worker activities. Currently this only records
@@ -427,6 +431,15 @@ class ServiceWorkerMetrics {
// Records the number of origins with a registered service worker.
static void RecordRegisteredOriginCount(size_t origin_count);
+ // Records the duration of looking up an existing registration.
+ // |status| is the result of lookup. The records for the cases where
+ // the registration is found (kOk), not found (kErrorNotFound), or an error
+ // happens (other errors) are saved separately into a relevant suffixed
+ // histogram.
+ static void RecordLookupRegistrationTime(
+ blink::ServiceWorkerStatusCode status,
+ base::TimeDelta duration);
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ServiceWorkerMetrics);
};
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 87b928ffb77..709976745e1 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
@@ -123,10 +123,9 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
// 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()) ||
- time_since_last_check > kServiceWorkerScriptMaxCacheAge ||
- version_->force_bypass_cache_for_scripts()) {
+ if (ServiceWorkerUtils::ShouldValidateBrowserCacheForScript(
+ is_main_script, version_->force_bypass_cache_for_scripts(),
+ registration->update_via_cache(), time_since_last_check)) {
resource_request.load_flags |= net::LOAD_VALIDATE_CACHE;
}
@@ -368,7 +367,7 @@ void ServiceWorkerNewScriptLoader::OnReceiveRedirect(
DCHECK_EQ(type_, Type::kNetworkOnly);
// Resource requests for service worker scripts should not follow redirects.
//
- // Step 7.5: "Set request's redirect mode to "error"."
+ // Step 9.5: "Set request's redirect mode to "error"."
// https://w3c.github.io/ServiceWorker/#update-algorithm
CommitCompleted(network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT),
kServiceWorkerRedirectError);
@@ -384,8 +383,8 @@ void ServiceWorkerNewScriptLoader::OnUploadProgress(
}
void ServiceWorkerNewScriptLoader::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
- client_->OnReceiveCachedMetadata(data);
+ mojo_base::BigBuffer data) {
+ client_->OnReceiveCachedMetadata(std::move(data));
}
void ServiceWorkerNewScriptLoader::OnTransferSizeUpdated(
@@ -478,7 +477,7 @@ void ServiceWorkerNewScriptLoader::OnComplete(
// End of URLLoaderClient ------------------------------------------------------
-void ServiceWorkerNewScriptLoader::WillWriteInfo(
+int ServiceWorkerNewScriptLoader::WillWriteInfo(
scoped_refptr<HttpResponseInfoIOBuffer> response_info) {
DCHECK_EQ(type_, Type::kResume);
DCHECK(response_info);
@@ -489,9 +488,28 @@ void ServiceWorkerNewScriptLoader::WillWriteInfo(
version_->SetMainScriptHttpResponseInfo(*info);
}
- ServiceWorkerUtils::SendHttpResponseInfoToClient(
+ auto response = ServiceWorkerUtils::CreateResourceResponseHeadAndMetadata(
info, original_options_, request_start_, base::TimeTicks::Now(),
- response_info->response_data_size, client_.get());
+ response_info->response_data_size);
+ client_->OnReceiveResponse(std::move(response.head));
+ if (!response.metadata.empty())
+ client_->OnReceiveCachedMetadata(std::move(response.metadata));
+
+ mojo::ScopedDataPipeConsumerHandle client_consumer;
+ if (mojo::CreateDataPipe(nullptr, &client_producer_, &client_consumer) !=
+ MOJO_RESULT_OK) {
+ // Reports error to cache writer and finally the loader would process this
+ // failure in OnCacheWriterResumed()
+ return net::ERR_INSUFFICIENT_RESOURCES;
+ }
+
+ // Pass the consumer handle to the client.
+ client_->OnStartLoadingResponseBody(std::move(client_consumer));
+ client_producer_watcher_.Watch(
+ client_producer_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
+ base::BindRepeating(&ServiceWorkerNewScriptLoader::OnClientWritable,
+ weak_factory_.GetWeakPtr()));
+ return net::OK;
}
void ServiceWorkerNewScriptLoader::OnClientWritable(MojoResult) {
@@ -539,28 +557,12 @@ int ServiceWorkerNewScriptLoader::WillWriteData(
base::OnceCallback<void(net::Error)> callback) {
DCHECK_EQ(type_, Type::kResume);
DCHECK(!write_observer_complete_callback_);
+ DCHECK(client_producer_);
+
data_to_send_ = std::move(data);
data_length_ = length;
bytes_sent_to_client_ = 0;
write_observer_complete_callback_ = std::move(callback);
-
- // Send a data pipe to the client if it's the first call of WillWriteData().
- if (!client_producer_) {
- mojo::ScopedDataPipeConsumerHandle client_consumer;
- if (mojo::CreateDataPipe(nullptr, &client_producer_, &client_consumer) !=
- MOJO_RESULT_OK) {
- // Report error to cache writer and finally the loader would process this
- // failure in OnCacheWriterResumed().
- return net::ERR_INSUFFICIENT_RESOURCES;
- }
-
- // Pass the consumer handle for responding with the response to the client.
- client_->OnStartLoadingResponseBody(std::move(client_consumer));
- client_producer_watcher_.Watch(
- client_producer_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
- base::BindRepeating(&ServiceWorkerNewScriptLoader::OnClientWritable,
- weak_factory_.GetWeakPtr()));
- }
client_producer_watcher_.ArmOrNotify();
return net::ERR_IO_PENDING;
}
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 424cd8e219e..ec46abaa3d0 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
@@ -149,7 +149,7 @@ class CONTENT_EXPORT ServiceWorkerNewScriptLoader
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
@@ -157,7 +157,7 @@ class CONTENT_EXPORT ServiceWorkerNewScriptLoader
// Implements ServiceWorkerCacheWriter::WriteObserver.
// These two methods are only used for resume loaders.
- void WillWriteInfo(
+ int WillWriteInfo(
scoped_refptr<HttpResponseInfoIOBuffer> response_info) override;
int WillWriteData(scoped_refptr<net::IOBuffer> data,
int length,
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 152efa9a87c..b6bab747ee1 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
@@ -93,8 +93,7 @@ class MockNetworkURLLoaderFactory final
// Pass the response header to the client.
net::HttpResponseInfo info;
info.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
- net::HttpUtil::AssembleRawHeaders(response.headers.c_str(),
- response.headers.size()));
+ net::HttpUtil::AssembleRawHeaders(response.headers));
network::ResourceResponseHead response_head;
response_head.headers = info.headers;
response_head.headers->GetMimeType(&response_head.mime_type);
@@ -920,17 +919,13 @@ class ServiceWorkerNewScriptLoaderResumeTest
}
// Verify the received response.
- void CheckReceivedResponse(bool has_body, const std::string& expected_body) {
+ void CheckReceivedResponse(const std::string& expected_body) {
EXPECT_TRUE(client_->has_received_response());
- EXPECT_EQ(has_body, client_->response_body().is_valid());
+ EXPECT_TRUE(client_->response_body().is_valid());
// The response should also be stored in the storage.
EXPECT_TRUE(ServiceWorkerUpdateCheckTestUtils::VerifyStoredResponse(
- LookupResourceId(kScriptURL), context()->storage(),
- has_body ? expected_body : ""));
-
- if (!has_body)
- return;
+ LookupResourceId(kScriptURL), context()->storage(), expected_body));
std::string response;
EXPECT_TRUE(mojo::BlockingCopyToString(client_->response_body_release(),
@@ -980,7 +975,7 @@ TEST_F(ServiceWorkerNewScriptLoaderResumeTest, FirstBlockDifferent) {
EXPECT_EQ(net::OK, client_->completion_status().error_code);
// The client should have received the response.
- CheckReceivedResponse(true, kNewData);
+ CheckReceivedResponse(kNewData);
}
// Tests resume type loader when the script data block in the middle is
@@ -1012,7 +1007,7 @@ TEST_F(ServiceWorkerNewScriptLoaderResumeTest, MiddleBlockDifferent) {
EXPECT_EQ(net::OK, client_->completion_status().error_code);
// The client should have received the response.
- CheckReceivedResponse(true, kNewData);
+ CheckReceivedResponse(kNewData);
}
// Tests resume type loader when the last script data block is different.
@@ -1039,7 +1034,7 @@ TEST_F(ServiceWorkerNewScriptLoaderResumeTest, LastBlockDifferent) {
EXPECT_EQ(net::OK, client_->completion_status().error_code);
// The client should have received the response.
- CheckReceivedResponse(true, kNewData);
+ CheckReceivedResponse(kNewData);
}
// Tests resume type loader when the last script data block is different and
@@ -1064,7 +1059,7 @@ TEST_F(ServiceWorkerNewScriptLoaderResumeTest, LastBlockDifferentCompleted) {
EXPECT_EQ(net::OK, client_->completion_status().error_code);
// The client should have received the response.
- CheckReceivedResponse(true, kNewData);
+ CheckReceivedResponse(kNewData);
}
// Tests resume type loader when the new script has more data appended.
@@ -1095,7 +1090,7 @@ TEST_F(ServiceWorkerNewScriptLoaderResumeTest, NewScriptLargerThanOld) {
EXPECT_EQ(net::OK, client_->completion_status().error_code);
// The client should have received the response.
- CheckReceivedResponse(true, kNewData);
+ CheckReceivedResponse(kNewData);
}
// Tests resume type loader when the script changed to have no body.
@@ -1117,7 +1112,7 @@ TEST_F(ServiceWorkerNewScriptLoaderResumeTest, NewScriptEmptyBody) {
EXPECT_EQ(net::OK, client_->completion_status().error_code);
- CheckReceivedResponse(false, kNewData);
+ CheckReceivedResponse(kNewData);
}
// Tests resume type loader could report error when the resumed network
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 68718d4f55e..603434ac2e1 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager.cc
+++ b/chromium/content/browser/service_worker/service_worker_process_manager.cc
@@ -114,23 +114,12 @@ ServiceWorkerProcessManager::AllocateWorkerProcess(
storage_partition_ &&
!storage_partition_->site_for_service_worker().is_empty();
scoped_refptr<SiteInstanceImpl> site_instance =
- SiteInstanceImpl::CreateForURL(
- browser_context_, use_url_from_storage_partition
- ? storage_partition_->site_for_service_worker()
- : script_url);
- site_instance->set_is_for_service_worker();
-
- // Attempt to reuse a renderer process if possible. Note that in the
- // <webview> case, process reuse isn't currently supported and a new
- // process will always be created (https://crbug.com/752667).
- DCHECK(site_instance->process_reuse_policy() ==
- SiteInstanceImpl::ProcessReusePolicy::DEFAULT ||
- site_instance->process_reuse_policy() ==
- SiteInstanceImpl::ProcessReusePolicy::PROCESS_PER_SITE);
- if (can_use_existing_process) {
- site_instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
- }
+ SiteInstanceImpl::CreateForServiceWorker(
+ browser_context_,
+ use_url_from_storage_partition
+ ? storage_partition_->site_for_service_worker()
+ : script_url,
+ can_use_existing_process);
// Get the process from the SiteInstance.
RenderProcessHost* rph = site_instance->GetProcess();
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 27d80a29a14..4bb7524421b 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/debug/alias.h"
#include "base/guid.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
@@ -27,7 +28,7 @@
#include "content/browser/service_worker/service_worker_type_converters.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/url_loader_factory_getter.h"
-#include "content/browser/web_contents/web_contents_getter_registry.h"
+#include "content/browser/web_contents/frame_tree_node_id_registry.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
@@ -161,17 +162,16 @@ base::WeakPtr<ServiceWorkerProviderHost>
ServiceWorkerProviderHost::PreCreateNavigationHost(
base::WeakPtr<ServiceWorkerContextCore> context,
bool are_ancestors_secure,
- WebContentsGetter web_contents_getter,
+ int frame_tree_node_id,
blink::mojom::ServiceWorkerProviderInfoForWindowPtr* out_provider_info) {
DCHECK(context);
blink::mojom::ServiceWorkerContainerAssociatedPtrInfo client_ptr_info;
(*out_provider_info)->client_request = mojo::MakeRequest(&client_ptr_info);
auto host = base::WrapUnique(new ServiceWorkerProviderHost(
blink::mojom::ServiceWorkerProviderType::kForWindow, are_ancestors_secure,
+ frame_tree_node_id,
mojo::MakeRequest(&((*out_provider_info)->host_ptr_info)),
std::move(client_ptr_info), context));
- host->web_contents_getter_ = std::move(web_contents_getter);
-
auto weak_ptr = host->AsWeakPtr();
RegisterToContextCore(context, std::move(host));
return weak_ptr;
@@ -188,7 +188,7 @@ ServiceWorkerProviderHost::PreCreateForController(
(*out_provider_info)->client_request = mojo::MakeRequest(&client_ptr_info);
auto host = base::WrapUnique(new ServiceWorkerProviderHost(
blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
- true /* is_parent_frame_secure */,
+ true /* is_parent_frame_secure */, FrameTreeNode::kFrameTreeNodeInvalidId,
mojo::MakeRequest(&((*out_provider_info)->host_ptr_info)),
std::move(client_ptr_info), context));
host->running_hosted_version_ = std::move(version);
@@ -208,7 +208,7 @@ ServiceWorkerProviderHost::PreCreateForSharedWorker(
(*out_provider_info)->client_request = mojo::MakeRequest(&client_ptr_info);
auto host = base::WrapUnique(new ServiceWorkerProviderHost(
blink::mojom::ServiceWorkerProviderType::kForSharedWorker,
- true /* is_parent_frame_secure */,
+ true /* is_parent_frame_secure */, FrameTreeNode::kFrameTreeNodeInvalidId,
mojo::MakeRequest(&((*out_provider_info)->host_ptr_info)),
std::move(client_ptr_info), context));
host->SetRenderProcessId(process_id);
@@ -232,6 +232,7 @@ void ServiceWorkerProviderHost::RegisterToContextCore(
ServiceWorkerProviderHost::ServiceWorkerProviderHost(
blink::mojom::ServiceWorkerProviderType type,
bool is_parent_frame_secure,
+ int frame_tree_node_id,
blink::mojom::ServiceWorkerContainerHostAssociatedRequest host_request,
blink::mojom::ServiceWorkerContainerAssociatedPtrInfo client_ptr_info,
base::WeakPtr<ServiceWorkerContextCore> context)
@@ -243,6 +244,12 @@ ServiceWorkerProviderHost::ServiceWorkerProviderHost(
render_thread_id_(kDocumentMainThreadId),
frame_id_(MSG_ROUTING_NONE),
is_parent_frame_secure_(is_parent_frame_secure),
+ frame_tree_node_id_(frame_tree_node_id),
+ web_contents_getter_(
+ frame_tree_node_id == FrameTreeNode::kFrameTreeNodeInvalidId
+ ? base::NullCallback()
+ : base::BindRepeating(&WebContents::FromFrameTreeNodeId,
+ frame_tree_node_id_)),
context_(context),
binding_(this),
interface_provider_binding_(this) {
@@ -270,7 +277,7 @@ ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
if (controller_)
controller_->RemoveControllee(client_uuid_);
if (fetch_request_window_id_)
- WebContentsGetterRegistry::GetInstance()->Remove(fetch_request_window_id_);
+ FrameTreeNodeIdRegistry::GetInstance()->Remove(fetch_request_window_id_);
// Remove |this| as an observer of ServiceWorkerRegistrations.
// TODO(falken): Use ScopedObserver instead of this explicit call.
@@ -309,6 +316,13 @@ bool ServiceWorkerProviderHost::IsContextSecureForServiceWorker() const {
return schemes.find(url_.scheme()) != schemes.end();
}
+ServiceWorkerVersion* ServiceWorkerProviderHost::controller() const {
+#if DCHECK_IS_ON()
+ CheckControllerConsistency(false);
+#endif // DCHECK_IS_ON()
+ return controller_.get();
+}
+
blink::mojom::ControllerServiceWorkerMode
ServiceWorkerProviderHost::GetControllerMode() const {
if (!controller_)
@@ -357,10 +371,10 @@ void ServiceWorkerProviderHost::OnSkippedWaiting(
if (controller_registration_ != registration)
return;
- DCHECK(controller());
+ DCHECK(controller_);
ServiceWorkerVersion* active = controller_registration_->active_version();
DCHECK(active);
- DCHECK_NE(active, controller());
+ DCHECK_NE(active, controller_.get());
DCHECK_EQ(active->status(), ServiceWorkerVersion::ACTIVATING);
UpdateController(true /* notify_controllerchange */);
}
@@ -391,10 +405,10 @@ void ServiceWorkerProviderHost::UpdateUrls(const GURL& url,
// may no longer be the potential controller of this frame and shouldn't
// have the power to display SSL dialogs for it.
if (type_ == blink::mojom::ServiceWorkerProviderType::kForWindow) {
- auto* registry = WebContentsGetterRegistry::GetInstance();
+ auto* registry = FrameTreeNodeIdRegistry::GetInstance();
registry->Remove(fetch_request_window_id_);
fetch_request_window_id_ = base::UnguessableToken::Create();
- registry->Add(fetch_request_window_id_, web_contents_getter());
+ registry->Add(fetch_request_window_id_, frame_tree_node_id_);
}
}
@@ -593,7 +607,6 @@ ServiceWorkerProviderHost::CreateLoaderInterceptor(
bool keepalive,
ResourceType resource_type,
blink::mojom::RequestContextType request_context_type,
- network::mojom::RequestContextFrameType frame_type,
scoped_refptr<network::ResourceRequestBody> body,
bool skip_service_worker) {
if (skip_service_worker) {
@@ -604,7 +617,7 @@ ServiceWorkerProviderHost::CreateLoaderInterceptor(
return std::make_unique<ServiceWorkerControlleeRequestHandler>(
context_, AsWeakPtr(), request_mode, credentials_mode, redirect_mode,
- integrity, keepalive, resource_type, request_context_type, frame_type,
+ integrity, keepalive, resource_type, request_context_type,
std::move(body));
}
@@ -776,7 +789,12 @@ void ServiceWorkerProviderHost::SendSetControllerServiceWorker(
auto controller_info = blink::mojom::ControllerServiceWorkerInfo::New();
controller_info->client_id = client_uuid();
- if (fetch_request_window_id_) {
+ // Set fetch_request_window_id only when |controller_| is available. Setting
+ // |fetch_request_window_id| should not affect correctness, however, we have
+ // the extensions bug, https://crbug.com/963748, which we don't yet
+ // understand. That is why we don't set |fetch_request_window_id| if there
+ // is no controller, at least, until we can fix the extension bug.
+ if (controller_ && fetch_request_window_id_) {
controller_info->fetch_request_window_id =
base::make_optional(fetch_request_window_id_);
}
@@ -844,16 +862,44 @@ bool ServiceWorkerProviderHost::IsControllerDecided() const {
}
#if DCHECK_IS_ON()
-void ServiceWorkerProviderHost::CheckControllerConsistency() const {
+void ServiceWorkerProviderHost::CheckControllerConsistency(
+ bool should_crash) const {
if (!controller_) {
DCHECK(!controller_registration_);
return;
}
+
DCHECK(IsProviderForClient());
DCHECK(controller_registration_);
DCHECK_EQ(controller_->registration_id(), controller_registration_->id());
+
+ switch (controller_->status()) {
+ case ServiceWorkerVersion::NEW:
+ case ServiceWorkerVersion::INSTALLING:
+ case ServiceWorkerVersion::INSTALLED:
+ if (should_crash) {
+ ServiceWorkerVersion::Status status = controller_->status();
+ base::debug::Alias(&status);
+ CHECK(false) << "Controller service worker has a bad status: "
+ << ServiceWorkerVersion::VersionStatusToString(status);
+ }
+ break;
+ case ServiceWorkerVersion::REDUNDANT: {
+ if (should_crash) {
+ DEBUG_ALIAS_FOR_CSTR(
+ redundant_callstack_str,
+ controller_->redundant_state_callstack().ToString().c_str(), 1024);
+ CHECK(false);
+ }
+ break;
+ }
+ case ServiceWorkerVersion::ACTIVATING:
+ case ServiceWorkerVersion::ACTIVATED:
+ // Valid status, controller is being activated.
+ break;
+ }
}
-#endif
+#endif // DCHECK_IS_ON()
void ServiceWorkerProviderHost::Register(
const GURL& script_url,
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 039a8f352b6..5629bdbc216 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.h
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.h
@@ -29,7 +29,6 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/binding_set.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/mojom/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_container.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
@@ -115,8 +114,9 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// ServiceWorkerProviderContext will later be created in the renderer, should
// the navigation succeed. |are_ancestors_secure| should be true for main
// frames. Otherwise it is true iff all ancestor frames of this frame have a
- // secure origin. |web_contents_getter| indicates the tab where the navigation
- // is occurring.
+ // secure origin. |frame_tree_node_id| is FrameTreeNode
+ // id. |web_contents_getter| indicates the tab where the navigation is
+ // occurring.
//
// The returned host stays alive as long as the filled |out_provider_info|
// stays alive (namely, as long as |out_provider_info->host_ptr_info| stays
@@ -125,7 +125,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
static base::WeakPtr<ServiceWorkerProviderHost> PreCreateNavigationHost(
base::WeakPtr<ServiceWorkerContextCore> context,
bool are_ancestors_secure,
- WebContentsGetter web_contents_getter,
+ int frame_tree_node_id,
blink::mojom::ServiceWorkerProviderInfoForWindowPtr* out_provider_info);
// Used for starting a service worker. Returns a provider host for the service
@@ -180,17 +180,11 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
blink::mojom::ControllerServiceWorkerMode GetControllerMode() const;
// For service worker clients. Returns this client's controller.
- ServiceWorkerVersion* controller() const {
-#if DCHECK_IS_ON()
- CheckControllerConsistency();
-#endif // DCHECK_IS_ON()
-
- return controller_.get();
- }
+ ServiceWorkerVersion* controller() const;
ServiceWorkerRegistration* controller_registration() const {
#if DCHECK_IS_ON()
- CheckControllerConsistency();
+ CheckControllerConsistency(false);
#endif // DCHECK_IS_ON()
return controller_registration_.get();
@@ -305,7 +299,6 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
bool keepalive,
ResourceType resource_type,
blink::mojom::RequestContextType request_context_type,
- network::mojom::RequestContextFrameType frame_type,
scoped_refptr<network::ResourceRequestBody> body,
bool skip_service_worker);
@@ -470,6 +463,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
ServiceWorkerProviderHost(
blink::mojom::ServiceWorkerProviderType type,
bool is_parent_frame_secure,
+ int frame_tree_node_id,
blink::mojom::ServiceWorkerContainerHostAssociatedRequest host_request,
blink::mojom::ServiceWorkerContainerAssociatedPtrInfo client_ptr_info,
base::WeakPtr<ServiceWorkerContextCore> context);
@@ -515,7 +509,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
bool IsControllerDecided() const;
#if DCHECK_IS_ON()
- void CheckControllerConsistency() const;
+ void CheckControllerConsistency(bool should_crash) const;
#endif // DCHECK_IS_ON()
// Implements blink::mojom::ServiceWorkerContainerHost.
@@ -633,9 +627,13 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// change its value.
bool is_parent_frame_secure_;
+ // FrameTreeNode id if this is a service worker window client.
+ // Otherwise, |FrameTreeNode::kFrameTreeNodeInvalidId|.
+ const int frame_tree_node_id_;
+
// Only set when this object is pre-created for a navigation. It indicates the
- // tab where the navigation occurs.
- WebContentsGetter web_contents_getter_;
+ // tab where the navigation occurs. Otherwise, a null callback.
+ const WebContentsGetter web_contents_getter_;
// For service worker clients. See comments for the getter functions.
GURL url_;
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 85a7408bfc3..b704261323d 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
@@ -14,6 +14,7 @@
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/frame_host/frame_tree_node.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_register_job.h"
@@ -457,7 +458,7 @@ TEST_F(ServiceWorkerProviderHostTest, Controller) {
base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */,
- base::NullCallback(), &provider_info);
+ FrameTreeNode::kFrameTreeNodeInvalidId, &provider_info);
remote_endpoints_.emplace_back();
remote_endpoints_.back().BindForWindow(std::move(provider_info));
auto container = std::make_unique<MockServiceWorkerContainer>(
@@ -493,7 +494,7 @@ TEST_F(ServiceWorkerProviderHostTest, UncontrolledWithMatchingRegistration) {
base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */,
- base::NullCallback(), &provider_info);
+ FrameTreeNode::kFrameTreeNodeInvalidId, &provider_info);
remote_endpoints_.emplace_back();
remote_endpoints_.back().BindForWindow(std::move(provider_info));
auto container = std::make_unique<MockServiceWorkerContainer>(
@@ -870,7 +871,7 @@ TEST_F(ServiceWorkerProviderHostTest,
base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true,
- base::RepeatingCallback<WebContents*(void)>(), &provider_info);
+ FrameTreeNode::kFrameTreeNodeInvalidId, &provider_info);
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
remote_endpoint.BindForWindow(std::move(provider_info));
FinishNavigation(host.get());
@@ -890,7 +891,7 @@ TEST_F(ServiceWorkerProviderHostTest, ClientPhaseForWindow) {
base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true,
- base::RepeatingCallback<WebContents*(void)>(), &provider_info);
+ FrameTreeNode::kFrameTreeNodeInvalidId, &provider_info);
EXPECT_FALSE(host->is_response_committed());
EXPECT_FALSE(host->is_execution_ready());
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 41e82056d0c..67059c64ace 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_register_job.cc
@@ -69,15 +69,9 @@ ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
is_promise_resolved_(false),
should_uninstall_on_failure_(false),
force_bypass_cache_(force_bypass_cache),
+ skip_script_comparison_(skip_script_comparison),
promise_resolved_status_(blink::ServiceWorkerStatusCode::kOk),
weak_factory_(this) {
- // |skip_script_comparison_| should be true when
- // ServiceWorkerImportedScriptUpdateCheck is enabled, because then script
- // comparison happens before starting a worker and it doesn't need to happen
- // during the worker startup.
- skip_script_comparison_ =
- blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled() ||
- skip_script_comparison;
internal_.registration = registration;
}
@@ -178,7 +172,7 @@ void ServiceWorkerRegisterJob::set_registration(
internal_.registration = std::move(registration);
}
-ServiceWorkerRegistration* ServiceWorkerRegisterJob::registration() {
+ServiceWorkerRegistration* ServiceWorkerRegisterJob::registration() const {
DCHECK(phase_ >= REGISTER || job_type_ == UPDATE_JOB) << phase_;
return internal_.registration.get();
}
@@ -305,37 +299,62 @@ void ServiceWorkerRegisterJob::ContinueWithUpdate(
// ago, depending on the freshness of the cached worker script we
// may be able to complete the update job right here.
- if (blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled()) {
- ServiceWorkerVersion* version_to_update =
- registration()->GetNewestVersion();
- std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
- version_to_update->script_cache_map()->GetResources(&resources);
- int64_t script_resource_id =
- version_to_update->script_cache_map()->LookupResourceId(script_url_);
- DCHECK_NE(kInvalidServiceWorkerResourceId, script_resource_id);
- update_checker_ = std::make_unique<ServiceWorkerUpdateChecker>(
- std::move(resources), script_url_, script_resource_id,
- version_to_update,
- context_->loader_factory_getter()->GetNetworkFactory());
- update_checker_->Start(
- base::BindOnce(&ServiceWorkerRegisterJob::OnUpdateCheckFinished,
- weak_factory_.GetWeakPtr()));
- return;
+ UpdateAndContinue();
+}
+
+bool ServiceWorkerRegisterJob::IsUpdateCheckNeeded() const {
+ ServiceWorkerVersion* newest_version = registration()->GetNewestVersion();
+
+ // Skip the update check if there is no newest service worker, which means
+ // that a new registration is created.
+ if (!newest_version)
+ return false;
+
+ // Skip the byte-to-byte comparison when either of the script type or the
+ // script url is updated.
+ if (newest_version->script_url() != script_url_ ||
+ newest_version->script_type() != worker_script_type_) {
+ DCHECK_EQ(job_type_, REGISTRATION_JOB);
+ return false;
}
+ // Need byte-to-byte comparison unless it should be forcefully skipped.
+ return !skip_script_comparison_;
+}
- UpdateAndContinue();
+void ServiceWorkerRegisterJob::TriggerUpdateCheckInBrowser(
+ ServiceWorkerUpdateChecker::UpdateStatusCallback callback) {
+ DCHECK_EQ(GetUpdateCheckType(),
+ UpdateCheckType::kAllScriptsBeforeStartWorker);
+ ServiceWorkerVersion* version_to_update = registration()->GetNewestVersion();
+ base::TimeDelta time_since_last_check =
+ base::Time::Now() - registration()->last_update_check();
+ std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
+ version_to_update->script_cache_map()->GetResources(&resources);
+ int64_t script_resource_id =
+ version_to_update->script_cache_map()->LookupResourceId(script_url_);
+ DCHECK_NE(script_resource_id, kInvalidServiceWorkerResourceId);
+
+ update_checker_ = std::make_unique<ServiceWorkerUpdateChecker>(
+ std::move(resources), script_url_, script_resource_id, version_to_update,
+ context_->loader_factory_getter()->GetNetworkFactory(),
+ force_bypass_cache_, registration()->update_via_cache(),
+ time_since_last_check);
+ update_checker_->Start(std::move(callback));
+}
+
+ServiceWorkerRegisterJob::UpdateCheckType
+ServiceWorkerRegisterJob::GetUpdateCheckType() const {
+ return blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled()
+ ? UpdateCheckType::kAllScriptsBeforeStartWorker
+ : UpdateCheckType::kMainScriptDuringStartWorker;
}
void ServiceWorkerRegisterJob::OnUpdateCheckFinished(bool script_changed) {
- DCHECK(blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled());
+ DCHECK_EQ(GetUpdateCheckType(),
+ UpdateCheckType::kAllScriptsBeforeStartWorker);
+ BumpLastUpdateCheckTimeIfNeeded();
if (!script_changed) {
// TODO(momohatt): Set phase correctly.
- // TODO(momohatt): Update the last update check time correctly.
- ServiceWorkerVersion* newest_version = registration()->GetNewestVersion();
- if (newest_version->force_bypass_cache_for_scripts()) {
- registration()->set_last_update_check(base::Time::Now());
- }
- context_->storage()->UpdateLastUpdateCheckTime(registration());
ResolvePromise(blink::ServiceWorkerStatusCode::kOk, std::string(),
registration());
// This terminates the current job (|this|).
@@ -346,7 +365,7 @@ void ServiceWorkerRegisterJob::OnUpdateCheckFinished(bool script_changed) {
compared_script_info_map_ = update_checker_->TakeComparedResults();
update_checker_.reset();
- UpdateAndContinue();
+ StartWorkerForUpdate();
}
// Creates a new ServiceWorkerRegistration.
@@ -408,9 +427,7 @@ void ServiceWorkerRegisterJob::ContinueWithRegistrationForSameScriptUrl(
UpdateAndContinue();
}
-// This function corresponds to the spec's [[Update]] algorithm.
-void ServiceWorkerRegisterJob::UpdateAndContinue() {
- SetPhase(UPDATE);
+void ServiceWorkerRegisterJob::StartWorkerForUpdate() {
context_->storage()->NotifyInstallingRegistration(registration());
int64_t version_id = context_->storage()->NewVersionId();
@@ -419,18 +436,16 @@ void ServiceWorkerRegisterJob::UpdateAndContinue() {
return;
}
+ // PauseAfterDownload is used for an update check during start worker.
+ bool need_to_pause_after_download =
+ GetUpdateCheckType() == UpdateCheckType::kMainScriptDuringStartWorker &&
+ IsUpdateCheckNeeded();
+
// Module service workers don't support pause after download so we can't
// perform script comparison.
// TODO(asamidoi): Support pause after download in module workers.
if (worker_script_type_ == blink::mojom::ScriptType::kModule) {
- skip_script_comparison_ = true;
- }
-
- // Skip the byte-for-byte comparison when the script type is updated.
- if (registration()->newest_installed_version() &&
- registration()->newest_installed_version()->script_type() !=
- worker_script_type_) {
- skip_script_comparison_ = true;
+ need_to_pause_after_download = false;
}
// "Let worker be a new ServiceWorker object..." and start the worker.
@@ -438,7 +453,7 @@ void ServiceWorkerRegisterJob::UpdateAndContinue() {
registration(), script_url_, worker_script_type_, version_id, context_));
new_version()->set_force_bypass_cache_for_scripts(force_bypass_cache_);
- if (registration()->newest_installed_version() && !skip_script_comparison_) {
+ if (need_to_pause_after_download) {
new_version()->SetToPauseAfterDownload(
base::BindOnce(&ServiceWorkerRegisterJob::OnPausedAfterDownload,
weak_factory_.GetWeakPtr()));
@@ -455,6 +470,25 @@ void ServiceWorkerRegisterJob::UpdateAndContinue() {
weak_factory_.GetWeakPtr()));
}
+// This function corresponds to the spec's [[Update]] algorithm.
+void ServiceWorkerRegisterJob::UpdateAndContinue() {
+ SetPhase(UPDATE);
+ switch (GetUpdateCheckType()) {
+ case UpdateCheckType::kAllScriptsBeforeStartWorker:
+ if (!IsUpdateCheckNeeded()) {
+ StartWorkerForUpdate();
+ return;
+ }
+ TriggerUpdateCheckInBrowser(
+ base::BindOnce(&ServiceWorkerRegisterJob::OnUpdateCheckFinished,
+ weak_factory_.GetWeakPtr()));
+ return;
+ case UpdateCheckType::kMainScriptDuringStartWorker:
+ StartWorkerForUpdate();
+ return;
+ }
+}
+
void ServiceWorkerRegisterJob::OnStartWorkerFinished(
blink::ServiceWorkerStatusCode status) {
BumpLastUpdateCheckTimeIfNeeded();
@@ -640,12 +674,15 @@ void ServiceWorkerRegisterJob::CompleteInternal(
registration()->UnsetVersion(new_version());
new_version()->Doom();
}
- if (!registration()->waiting_version() &&
- !registration()->active_version()) {
+ if (!registration()->newest_installed_version()) {
registration()->NotifyRegistrationFailed();
- context_->storage()->DeleteRegistration(
- registration()->id(), registration()->scope().GetOrigin(),
- base::DoNothing());
+ if (!registration()->is_deleted()) {
+ context_->storage()->DeleteRegistration(
+ registration(), registration()->scope().GetOrigin(),
+ base::DoNothing());
+ context_->storage()->NotifyDoneUninstallingRegistration(
+ registration(), ServiceWorkerRegistration::Status::kUninstalled);
+ }
}
}
if (!is_promise_resolved_)
@@ -655,8 +692,26 @@ void ServiceWorkerRegisterJob::CompleteInternal(
if (registration()) {
context_->storage()->NotifyDoneInstallingRegistration(
registration(), new_version(), status);
- if (registration()->newest_installed_version())
- registration()->set_is_uninstalled(false);
+#if DCHECK_IS_ON()
+ switch (registration()->status()) {
+ case ServiceWorkerRegistration::Status::kIntact:
+ // The registration must have a version installed, but this job may or
+ // may not have succeeded (i.e., may have failed to update).
+ DCHECK(registration()->newest_installed_version());
+ break;
+ case ServiceWorkerRegistration::Status::kUninstalling:
+ // This job must have failed. One case this happens is when the
+ // registration was already uninstalling when the job started, so it
+ // aborted.
+ DCHECK_NE(status, blink::ServiceWorkerStatusCode::kOk);
+ break;
+ case ServiceWorkerRegistration::Status::kUninstalled:
+ // This job must have failed.
+ DCHECK(!registration()->newest_installed_version());
+ DCHECK_NE(status, blink::ServiceWorkerStatusCode::kOk);
+ break;
+ }
+#endif // DCHECK_IS_ON()
}
}
@@ -692,7 +747,8 @@ void ServiceWorkerRegisterJob::AddRegistrationToMatchingProviderHosts(
}
void ServiceWorkerRegisterJob::OnPausedAfterDownload() {
- DCHECK(!blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled());
+ DCHECK_EQ(GetUpdateCheckType(),
+ UpdateCheckType::kMainScriptDuringStartWorker);
net::URLRequestStatus status =
new_version()->script_cache_map()->main_script_status();
if (!status.is_success()) {
@@ -720,13 +776,33 @@ void ServiceWorkerRegisterJob::OnPausedAfterDownload() {
}
void ServiceWorkerRegisterJob::BumpLastUpdateCheckTimeIfNeeded() {
+ bool network_accessed = false;
+ bool force_bypass_cache = false;
+
+ // Get |network_accessed| from |update_checker_| and |force_bypass_cache|
+ // from the current job when the update checker tried to fetch the worker
+ // script.
+ // |update_checker_| is not available when installing a new
+ // service worker without update checking (e.g. a new registration), or
+ // non-ServiceWorkerImportedScriptUpdateCheck. In this case, get
+ // |network_accessed| and |force_bypass_cache| from the new version.
+ if (update_checker_) {
+ DCHECK_EQ(GetUpdateCheckType(),
+ UpdateCheckType::kAllScriptsBeforeStartWorker);
+ network_accessed = update_checker_->network_accessed();
+ force_bypass_cache = force_bypass_cache_;
+ } else {
+ network_accessed =
+ new_version()->embedded_worker()->network_accessed_for_script();
+ force_bypass_cache = new_version()->force_bypass_cache_for_scripts();
+ }
+
// Bump the last update check time only when the register/update job fetched
// the version having bypassed the network cache. We assume that the
// BYPASS_CACHE flag evicts an existing cache entry, so even if the install
// ultimately failed for whatever reason, we know the version in the HTTP
// cache is not stale, so it's OK to bump the update check time.
- if (new_version()->embedded_worker()->network_accessed_for_script() ||
- new_version()->force_bypass_cache_for_scripts() ||
+ if (network_accessed || force_bypass_cache ||
registration()->last_update_check().is_null()) {
registration()->set_last_update_check(base::Time::Now());
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 d76e4c7696b..4f6dc40abfb 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.h
+++ b/chromium/content/browser/service_worker/service_worker_register_job.h
@@ -80,6 +80,11 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
ABORT,
};
+ enum class UpdateCheckType {
+ kMainScriptDuringStartWorker, // Only check main script.
+ kAllScriptsBeforeStartWorker, // Check all scripts.
+ };
+
// Holds internal state of ServiceWorkerRegistrationJob, to compel use of the
// getter/setter functions.
struct Internal {
@@ -93,7 +98,7 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
};
void set_registration(scoped_refptr<ServiceWorkerRegistration> registration);
- ServiceWorkerRegistration* registration();
+ ServiceWorkerRegistration* registration() const;
void set_new_version(ServiceWorkerVersion* version);
ServiceWorkerVersion* new_version();
@@ -107,6 +112,18 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
+ bool IsUpdateCheckNeeded() const;
+
+ // Trigger the UpdateCheckType::kAllScriptsBeforeStartWorker type check if
+ // ServiceWorkerImportedScriptUpdateCheck is enabled.
+ void TriggerUpdateCheckInBrowser(
+ ServiceWorkerUpdateChecker::UpdateStatusCallback callback);
+
+ // When ServiceWorkerImportedScriptUpdateCheck is enabled, returns
+ // UpdateCheckType::kAllScriptsBeforeStartWorker, otherwise, returns
+ // UpdateCheckType::kMainScriptDuringStartWorker.
+ UpdateCheckType GetUpdateCheckType() const;
+
// This method is only called when ServiceWorkerImportedScriptUpdateCheck is
// enabled. When some script changed, the parameter |script_changed| is set
// to true.
@@ -120,6 +137,13 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
scoped_refptr<ServiceWorkerRegistration> existing_registration,
blink::ServiceWorkerStatusCode status);
void UpdateAndContinue();
+
+ // Starts a service worker for [[Update]].
+ // For Non-ServiceWorkerImportedScriptUpdateCheck: it includes byte-for-byte
+ // checking for main script.
+ // For ServiceWorkerImportedScriptUpdateCheck: the script comparison has
+ // finished at this point. It starts install phase.
+ void StartWorkerForUpdate();
void OnStartWorkerFinished(blink::ServiceWorkerStatusCode status);
void OnStoreRegistrationComplete(blink::ServiceWorkerStatusCode status);
void InstallAndContinue();
diff --git a/chromium/content/browser/service_worker/service_worker_registration.cc b/chromium/content/browser/service_worker/service_worker_registration.cc
index c9c8cb6645a..290d6e3cdf2 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration.cc
@@ -13,6 +13,7 @@
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_info.h"
+#include "content/browser/service_worker/service_worker_job_coordinator.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_register_job.h"
#include "content/public/browser/browser_thread.h"
@@ -45,9 +46,7 @@ ServiceWorkerRegistration::ServiceWorkerRegistration(
: scope_(options.scope),
update_via_cache_(options.update_via_cache),
registration_id_(registration_id),
- is_deleted_(false),
- is_uninstalling_(false),
- is_uninstalled_(false),
+ status_(Status::kIntact),
should_activate_when_ready_(false),
resources_total_size_bytes_(0),
context_(context),
@@ -67,6 +66,28 @@ ServiceWorkerRegistration::~ServiceWorkerRegistration() {
active_version()->RemoveObserver(this);
}
+void ServiceWorkerRegistration::SetStatus(Status status) {
+ if (status_ == status)
+ return;
+#if DCHECK_IS_ON()
+ switch (status_) {
+ case Status::kIntact:
+ DCHECK_EQ(status, Status::kUninstalling);
+ break;
+ case Status::kUninstalling:
+ // All transitions are allowed:
+ // - To kIntact: resurrected.
+ // - To kUninstalled: finished uninstalling.
+ break;
+ case Status::kUninstalled:
+ NOTREACHED();
+ break;
+ }
+#endif // DCHECK_IS_ON()
+
+ status_ = status;
+}
+
ServiceWorkerVersion* ServiceWorkerRegistration::GetNewestVersion() const {
if (installing_version())
return installing_version();
@@ -106,8 +127,8 @@ ServiceWorkerRegistrationInfo ServiceWorkerRegistration::GetInfo() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return ServiceWorkerRegistrationInfo(
scope(), update_via_cache(), registration_id_,
- is_deleted_ ? ServiceWorkerRegistrationInfo::IS_DELETED
- : ServiceWorkerRegistrationInfo::IS_NOT_DELETED,
+ is_deleted() ? ServiceWorkerRegistrationInfo::IS_DELETED
+ : ServiceWorkerRegistrationInfo::IS_NOT_DELETED,
GetVersionInfo(active_version_.get()),
GetVersionInfo(waiting_version_.get()),
GetVersionInfo(installing_version_.get()), resources_total_size_bytes_,
@@ -245,13 +266,13 @@ void ServiceWorkerRegistration::ClaimClients() {
void ServiceWorkerRegistration::ClearWhenReady() {
DCHECK(context_);
- if (is_uninstalling_)
+ if (is_deleted()) {
+ // We already deleted and are waiting to clear, or the registration is
+ // already cleared.
return;
- is_uninstalling_ = true;
-
- context_->storage()->NotifyUninstallingRegistration(this);
+ }
context_->storage()->DeleteRegistration(
- id(), scope().GetOrigin(),
+ this, scope().GetOrigin(),
AdaptCallbackForRepeating(
base::BindOnce(&ServiceWorkerRegistration::OnDeleteFinished, this)));
@@ -261,12 +282,21 @@ void ServiceWorkerRegistration::ClearWhenReady() {
void ServiceWorkerRegistration::AbortPendingClear(StatusCallback callback) {
DCHECK(context_);
- if (!is_uninstalling()) {
- std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk);
- return;
+
+ switch (status_) {
+ case Status::kIntact:
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk);
+ return;
+ case Status::kUninstalling:
+ break;
+ case Status::kUninstalled:
+ NOTREACHED()
+ << "attempt to resurrect a completely uninstalled registration";
+ break;
}
- is_uninstalling_ = false;
- context_->storage()->NotifyDoneUninstallingRegistration(this);
+
+ context_->storage()->NotifyDoneUninstallingRegistration(this,
+ Status::kIntact);
scoped_refptr<ServiceWorkerVersion> most_recent_version =
waiting_version() ? waiting_version() : active_version();
@@ -282,7 +312,7 @@ void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) {
if (!context_)
return;
DCHECK_EQ(active_version(), version);
- if (is_uninstalling_) {
+ if (is_uninstalling()) {
// TODO(falken): This can destroy the caller during this observer function
// call, which is impolite and dangerous. Try to make this async, or make
// OnNoControllees not an observer function.
@@ -435,33 +465,54 @@ void ServiceWorkerRegistration::ContinueActivation(
activating_version));
}
-void ServiceWorkerRegistration::DeleteVersion(
- const scoped_refptr<ServiceWorkerVersion>& version) {
- DCHECK_EQ(id(), version->registration_id());
+void ServiceWorkerRegistration::ForceDelete() {
+ DCHECK(context_);
+ DCHECK(!is_uninstalled()) << "attempt to delete registration twice";
// Protect the registration since version->Doom() can stop |version|, which
// destroys start worker callbacks, which might be the only things holding a
// reference to |this|.
scoped_refptr<ServiceWorkerRegistration> protect(this);
- UnsetVersion(version.get());
- version->Doom();
+ // Abort any queued or running jobs for this registration.
+ context_->job_coordinator()->Abort(scope());
- if (!active_version() && !waiting_version()) {
- // Delete the records from the db.
+ // The rest of this function is similar to Clear() but is slightly different
+ // because this emergency deletion isn't part of the spec and happens
+ // outside of the normal job coordinator.
+ // TODO(falken): Consider merging the two.
+ should_activate_when_ready_ = false;
+
+ // Doom versions. This sets the versions to redundant and tells the
+ // controllees that they are gone.
+ //
+ // There can't be an installing version since we aborted any register job.
+ DCHECK(!installing_version_);
+ auto mask =
+ blink::mojom::ChangedServiceWorkerObjectsMask::New(false, false, false);
+ // Unset the version first so we stop listening to the version as it might
+ // invoke listener methods during Doom().
+ if (scoped_refptr<ServiceWorkerVersion> waiting_version = waiting_version_) {
+ UnsetVersionInternal(waiting_version.get(), mask.get());
+ waiting_version->Doom();
+ }
+ if (scoped_refptr<ServiceWorkerVersion> active_version = active_version_) {
+ UnsetVersionInternal(active_version.get(), mask.get());
+ active_version->Doom();
+ }
+
+ // Delete the registration and its state from storage.
+ if (status() == Status::kIntact) {
context_->storage()->DeleteRegistration(
- id(), scope().GetOrigin(),
+ this, scope().GetOrigin(),
base::BindOnce(&ServiceWorkerRegistration::OnDeleteFinished, protect));
- // But not from memory if there is a version in the pipeline.
- // TODO(falken): Fix this logic. There could be a running register job for
- // this registration that hasn't set installing_version() yet.
- if (installing_version()) {
- is_deleted_ = false;
- } else {
- is_uninstalled_ = true;
- NotifyRegistrationFailed();
- }
}
+ DCHECK(is_uninstalling());
+ context_->storage()->NotifyDoneUninstallingRegistration(this,
+ Status::kUninstalled);
+
+ // Tell observers that this registration is gone.
+ NotifyRegistrationFailed();
}
void ServiceWorkerRegistration::NotifyRegistrationFinished() {
@@ -556,8 +607,8 @@ void ServiceWorkerRegistration::OnDeleteFinished(
}
void ServiceWorkerRegistration::Clear() {
- is_uninstalling_ = false;
- is_uninstalled_ = true;
+ DCHECK(is_uninstalling());
+ SetStatus(Status::kUninstalled);
should_activate_when_ready_ = false;
// Some callbacks, at least OnRegistrationFinishedUninstalling and
@@ -567,8 +618,10 @@ void ServiceWorkerRegistration::Clear() {
// or make the observers more polite?
auto protect = base::WrapRefCounted(this);
- if (context_)
- context_->storage()->NotifyDoneUninstallingRegistration(this);
+ if (context_) {
+ context_->storage()->NotifyDoneUninstallingRegistration(
+ this, Status::kUninstalled);
+ }
std::vector<scoped_refptr<ServiceWorkerVersion>> versions_to_doom;
auto mask =
diff --git a/chromium/content/browser/service_worker/service_worker_registration.h b/chromium/content/browser/service_worker/service_worker_registration.h
index 12b64524716..770fec5a361 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.h
+++ b/chromium/content/browser/service_worker/service_worker_registration.h
@@ -62,6 +62,20 @@ class CONTENT_EXPORT ServiceWorkerRegistration
virtual void OnSkippedWaiting(ServiceWorkerRegistration* registation) {}
};
+ enum class Status {
+ // This registration has not been deleted.
+ kIntact,
+ // The registration data has been deleted from the database, but it's still
+ // usable: if a page has an existing controller from this registration, the
+ // controller will continue to function until all such pages are unloaded.
+ // The registration may also be resurrected if register() is called while in
+ // this state.
+ kUninstalling,
+ // This registration is completely uninstalled. It cannot be resurrected or
+ // used.
+ kUninstalled,
+ };
+
ServiceWorkerRegistration(
const blink::mojom::ServiceWorkerRegistrationOptions& options,
int64_t registration_id,
@@ -73,13 +87,11 @@ class CONTENT_EXPORT ServiceWorkerRegistration
return update_via_cache_;
}
- bool is_deleted() const { return is_deleted_; }
- void set_is_deleted(bool deleted) { is_deleted_ = deleted; }
-
- bool is_uninstalling() const { return is_uninstalling_; }
-
- void set_is_uninstalled(bool uninstalled) { is_uninstalled_ = uninstalled; }
- bool is_uninstalled() const { return is_uninstalled_; }
+ bool is_deleted() const { return status_ != Status::kIntact; }
+ bool is_uninstalling() const { return status_ == Status::kUninstalling; }
+ bool is_uninstalled() const { return status_ == Status::kUninstalled; }
+ Status status() const { return status_; }
+ void SetStatus(Status status);
int64_t resources_total_size_bytes() const {
return resources_total_size_bytes_;
@@ -172,9 +184,11 @@ class CONTENT_EXPORT ServiceWorkerRegistration
self_update_delay_ = delay;
}
- // Unsets the version and deletes its resources. Also deletes this
- // registration from storage if there is no longer a stored version.
- void DeleteVersion(const scoped_refptr<ServiceWorkerVersion>& version);
+ // An emergency measure to forcibly delete the registration even if it has
+ // controllees. The controllees will stop using the registration. Called when
+ // a service worker can't be read from disk, a potentially sticky failure
+ // that would prevent the site from being loaded.
+ void ForceDelete();
void RegisterRegistrationFinishedCallback(base::OnceClosure callback);
void NotifyRegistrationFinished();
@@ -231,9 +245,7 @@ class CONTENT_EXPORT ServiceWorkerRegistration
const GURL scope_;
blink::mojom::ServiceWorkerUpdateViaCache update_via_cache_;
const int64_t registration_id_;
- bool is_deleted_;
- bool is_uninstalling_;
- bool is_uninstalled_;
+ Status status_;
bool should_activate_when_ready_;
blink::mojom::NavigationPreloadState navigation_preload_state_;
base::Time last_update_check_;
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 9b7944f36e1..f0903c6b8f2 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
@@ -151,9 +151,21 @@ void ServiceWorkerRegistrationObjectHost::Update(UpdateCallback callback) {
return;
}
- if (!registration_->GetNewestVersion()) {
+ // Run steps according to section 3.2.7:
+ // https://w3c.github.io/ServiceWorker/#service-worker-registration-update
+
+ // 1. Let |registration| be the service worker registration.
+ ServiceWorkerRegistration* registration = registration_.get();
+ DCHECK(registration);
+
+ // 2. Let |newest_worker| be the result of running Get Newest Worker algorithm
+ // passing |registration| as its argument.
+ ServiceWorkerVersion* newest_worker = registration->GetNewestVersion();
+
+ // 3. If |newest_worker| is null, return a promise rejected with an
+ // "InvalidStateError" DOMException and abort these steps.
+ if (!newest_worker) {
// This can happen if update() is called during initial script evaluation.
- // Abort the following steps according to the spec.
std::move(callback).Run(
blink::mojom::ServiceWorkerErrorType::kState,
std::string(kServiceWorkerUpdateErrorPrefix) +
@@ -161,11 +173,29 @@ void ServiceWorkerRegistrationObjectHost::Update(UpdateCallback callback) {
return;
}
+ // 4. If the context object’s relevant settings object’s global object
+ // globalObject is a ServiceWorkerGlobalScope object, and globalObject’s
+ // associated service worker's state is installing, return a promise rejected
+ // with an "InvalidStateError" DOMException and abort these steps.
+ if (provider_host_->IsProviderForServiceWorker()) {
+ ServiceWorkerVersion* version = provider_host_->running_hosted_version();
+ DCHECK(version);
+ if (ServiceWorkerVersion::Status::INSTALLING == version->status()) {
+ // This can happen if update() is called during execution of the
+ // install-event-handler.
+ std::move(callback).Run(
+ blink::mojom::ServiceWorkerErrorType::kState,
+ std::string(kServiceWorkerUpdateErrorPrefix) +
+ std::string(ServiceWorkerConsts::kInvalidStateErrorMessage));
+ return;
+ }
+ }
+
DelayUpdate(
- provider_host_->provider_type(), registration_.get(),
+ provider_host_->provider_type(), registration,
provider_host_->running_hosted_version(),
base::BindOnce(
- &ExecuteUpdate, context_, registration_->id(),
+ &ExecuteUpdate, context_, registration->id(),
false /* force_bypass_cache */, false /* skip_script_comparison */,
base::BindOnce(&ServiceWorkerRegistrationObjectHost::UpdateComplete,
weak_ptr_factory_.GetWeakPtr(), std::move(callback))));
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 028b022a040..0ae1d4201f4 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -373,6 +373,7 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest,
void SetUp() override {
ServiceWorkerRegistrationTest::SetUp();
+ const GURL kUrl("https://www.example.not/");
const GURL kScope("https://www.example.not/");
const GURL kScript("https://www.example.not/service_worker.js");
@@ -414,7 +415,9 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest,
context()->AsWeakPtr(), &remote_endpoint_);
DCHECK(remote_endpoint_.client_request()->is_pending());
DCHECK(remote_endpoint_.host_ptr()->is_bound());
- version_1->AddControllee(host_.get());
+ host_->UpdateUrls(kUrl, kUrl);
+ host_->SetControllerRegistration(registration_,
+ false /* notify_controllerchange */);
// Setup the Mojo implementation fakes for the renderer-side service worker.
// These will be bound once the service worker starts.
@@ -480,6 +483,16 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest,
ServiceWorkerProviderHost* controllee() { return host_.get(); }
int inflight_request_id() const { return inflight_request_id_; }
+ void AddControllee() {
+ controllee()->SetControllerRegistration(
+ registration(), false /* notify_controllerchange */);
+ }
+
+ void RemoveControllee() {
+ controllee()->SetControllerRegistration(
+ nullptr, false /* notify_controllerchange */);
+ }
+
bool IsLameDuckTimerRunning() {
return registration_->lame_duck_timer_.IsRunning();
}
@@ -549,7 +562,7 @@ TEST_P(ServiceWorkerActivationTest, NoInflightRequest) {
// Remove the controllee. Since there is an in-flight request,
// activation should not yet happen.
- version_1->RemoveControllee(controllee()->client_uuid());
+ RemoveControllee();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(version_1.get(), reg->active_version());
// The idle timer living in the renderer is requested to notify the idle state
@@ -694,6 +707,12 @@ TEST_P(ServiceWorkerActivationTest, LameDuckTime_SkipWaiting) {
EXPECT_TRUE(*result);
EXPECT_EQ(version_2.get(), reg->active_version());
EXPECT_FALSE(IsLameDuckTimerRunning());
+
+ // Restore the TickClock to the default. This is required because the dtor
+ // of ServiceWorkerVersions can access the TickClock and it should outlive
+ // ServiceWorkerVersion.
+ version_1->SetTickClockForTesting(base::DefaultTickClock::GetInstance());
+ version_2->SetTickClockForTesting(base::DefaultTickClock::GetInstance());
}
// Test lame duck timer triggered by loss of controllee.
@@ -711,7 +730,7 @@ TEST_P(ServiceWorkerActivationTest, LameDuckTime_NoControllee) {
// Remove the controllee. Since there is still an in-flight request,
// activation should not happen. But the lame duck timer should start.
EXPECT_FALSE(IsLameDuckTimerRunning());
- version_1->RemoveControllee(controllee()->client_uuid());
+ RemoveControllee();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(version_1.get(), reg->active_version());
EXPECT_TRUE(IsLameDuckTimerRunning());
@@ -721,12 +740,12 @@ TEST_P(ServiceWorkerActivationTest, LameDuckTime_NoControllee) {
clock_1.Advance(kLittleBit);
// Add a controllee again to reset the lame duck period.
- version_1->AddControllee(controllee());
+ AddControllee();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsLameDuckTimerRunning());
// Remove the controllee.
- version_1->RemoveControllee(controllee()->client_uuid());
+ RemoveControllee();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsLameDuckTimerRunning());
@@ -1078,8 +1097,11 @@ TEST_F(ServiceWorkerRegistrationObjectHostTest,
const GURL kScriptUrl("https://www.example.com/sw.js");
scoped_refptr<ServiceWorkerRegistration> registration =
CreateRegistration(kScope);
+
scoped_refptr<ServiceWorkerVersion> version =
CreateVersion(registration.get(), kScriptUrl);
+ version->SetStatus(ServiceWorkerVersion::ACTIVATED);
+
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
base::WeakPtr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow(
helper_->mock_render_process_id(), true /* is_parent_frame_secure */,
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 95c9697fac6..427094f5e31 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.cc
@@ -43,7 +43,6 @@ ServiceWorkerRequestHandler::CreateForNavigation(
ResourceContext* resource_context,
ServiceWorkerNavigationHandleCore* navigation_handle_core,
const NavigationRequestInfo& request_info,
- base::RepeatingCallback<WebContents*()> web_contents_getter,
base::WeakPtr<ServiceWorkerProviderHost>* out_provider_host) {
DCHECK(navigation_handle_core);
@@ -65,26 +64,22 @@ ServiceWorkerRequestHandler::CreateForNavigation(
// Initialize the SWProviderHost.
*out_provider_host = ServiceWorkerProviderHost::PreCreateNavigationHost(
context->AsWeakPtr(), request_info.are_ancestors_secure,
- std::move(web_contents_getter), &provider_info);
+ request_info.frame_tree_node_id, &provider_info);
navigation_handle_core->OnCreatedProviderHost(*out_provider_host,
std::move(provider_info));
const ResourceType resource_type = request_info.is_main_frame
? ResourceType::kMainFrame
: ResourceType::kSubFrame;
- const network::mojom::RequestContextFrameType frame_type =
- request_info.is_main_frame
- ? network::mojom::RequestContextFrameType::kTopLevel
- : network::mojom::RequestContextFrameType::kNested;
return (*out_provider_host)
- ->CreateLoaderInterceptor(
- network::mojom::FetchRequestMode::kNavigate,
- network::mojom::FetchCredentialsMode::kInclude,
- network::mojom::FetchRedirectMode::kManual,
- std::string() /* integrity */, false /* keepalive */, resource_type,
- request_info.begin_params->request_context_type, frame_type,
- request_info.common_params.post_data,
- request_info.begin_params->skip_service_worker);
+ ->CreateLoaderInterceptor(network::mojom::FetchRequestMode::kNavigate,
+ network::mojom::FetchCredentialsMode::kInclude,
+ network::mojom::FetchRedirectMode::kManual,
+ std::string() /* integrity */,
+ false /* keepalive */, resource_type,
+ request_info.begin_params->request_context_type,
+ request_info.common_params.post_data,
+ request_info.begin_params->skip_service_worker);
}
// static
@@ -115,8 +110,7 @@ ServiceWorkerRequestHandler::CreateForWorker(
resource_request.resource_type == static_cast<int>(ResourceType::kWorker)
? blink::mojom::RequestContextType::WORKER
: blink::mojom::RequestContextType::SHARED_WORKER,
- resource_request.fetch_frame_type, resource_request.request_body,
- resource_request.skip_service_worker);
+ resource_request.request_body, resource_request.skip_service_worker);
}
} // namespace content
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 ba977507e54..b7824f7de40 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.h
@@ -20,7 +20,6 @@ namespace content {
class ResourceContext;
class ServiceWorkerNavigationHandleCore;
class ServiceWorkerProviderHost;
-class WebContents;
struct NavigationRequestInfo;
// Contains factory methods for creating the NavigationLoaderInterceptors for
@@ -36,7 +35,6 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler {
ResourceContext* resource_context,
ServiceWorkerNavigationHandleCore* navigation_handle_core,
const NavigationRequestInfo& request_info,
- base::RepeatingCallback<WebContents*()> web_contents_getter,
base::WeakPtr<ServiceWorkerProviderHost>* out_provider_host);
// Same as above but for a dedicated worker or shared worker.
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 ed644348f67..39e4c6cdce4 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
@@ -27,7 +27,6 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_test_util.h"
-#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"
@@ -97,7 +96,6 @@ class ServiceWorkerRequestHandlerTest : public testing::Test {
ServiceWorkerRequestHandler::CreateForNavigation(
GURL(url), nullptr /* resource_context */,
navigation_handle_core.get(), request_info,
- base::RepeatingCallback<WebContents*(void)>(),
&service_worker_provider_host);
EXPECT_EQ(expected_handler_created, !!interceptor.get());
}
diff --git a/chromium/content/browser/service_worker/service_worker_script_cache_map.h b/chromium/content/browser/service_worker/service_worker_script_cache_map.h
index f1c83992830..23c9ee3cffd 100644
--- a/chromium/content/browser/service_worker/service_worker_script_cache_map.h
+++ b/chromium/content/browser/service_worker/service_worker_script_cache_map.h
@@ -70,8 +70,7 @@ class CONTENT_EXPORT ServiceWorkerScriptCacheMap {
// The version objects owns its script cache and provides a rawptr to it.
friend class ServiceWorkerVersion;
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionBrowserTest,
- ReadResourceFailure_WaitingWorker);
+ friend class ServiceWorkerVersionBrowserTest;
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerReadFromCacheJobTest, ResourceNotFound);
ServiceWorkerScriptCacheMap(
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 41214ad03eb..9cc85191ce4 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
@@ -72,8 +72,9 @@ void ServiceWorkerScriptLoaderFactory::CreateLoaderAndStart(
// ServiceWorkerInstalledScriptLoader.
// 2) If compared script info exists and specifies that the script is
// installed in an old service worker but content has changed, then
- // resume the paused state in the compared script info to load the
- // script.
+ // ServiceWorkerNewScriptLoader::CreateForResume() is called to create
+ // a ServiceWorkerNewScriptLoader to resume the paused state in the
+ // compared script info.
// 3) For other cases or if ServiceWorkerImportedScriptsUpdateCheck is not
// enabled, serve from network with installing the script
// (use ServiceWorkerNewScriptLoader::CreateForNetworkOnly() to
@@ -126,11 +127,11 @@ void ServiceWorkerScriptLoaderFactory::CreateLoaderAndStart(
return;
case ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent:
// Case D.2:
- // TODO(https://crbug.com/648295): Currently, this case is treated
- // the same as case D.3. In future, the paused state in compared
- // script info should be resumed instead of a fresh download.
- NOTIMPLEMENTED();
- break;
+ mojo::MakeStrongBinding(
+ ServiceWorkerNewScriptLoader::CreateForResume(
+ options, resource_request, std::move(client), version),
+ std::move(request));
+ return;
case ServiceWorkerSingleScriptUpdateChecker::Result::kNotCompared:
// This is invalid, as scripts in compared script info must have been
// compared.
diff --git a/chromium/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc b/chromium/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
index 0f0ddcd1331..3e2a5674fae 100644
--- a/chromium/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
@@ -12,67 +12,15 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/http/http_util.h"
+#include "content/test/fake_network_url_loader_factory.h"
+#include "mojo/public/cpp/system/data_pipe_utils.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
namespace content {
-namespace {
-
-// A URLLoaderFactory that returns 200 OK with an empty javascript to any
-// request.
-// TODO(bashi): Avoid duplicated MockNetworkURLLoaderFactory. This is almost the
-// same as EmbeddedWorkerTestHelper::MockNetworkURLLoaderFactory.
-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 {
- const std::string headers =
- "HTTP/1.1 200 OK\n"
- "Content-Type: application/javascript\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);
-
- const 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);
-};
-
-} // namespace
-
class ServiceWorkerScriptLoaderFactoryTest : public testing::Test {
public:
ServiceWorkerScriptLoaderFactoryTest()
@@ -86,21 +34,21 @@ class ServiceWorkerScriptLoaderFactoryTest : public testing::Test {
base::RunLoop().RunUntilIdle();
scope_ = GURL("https://host/scope");
+ script_url_ = GURL("https://host/script.js");
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = scope_;
registration_ = base::MakeRefCounted<ServiceWorkerRegistration>(
options, 1L /* registration_id */, context->AsWeakPtr());
version_ = base::MakeRefCounted<ServiceWorkerVersion>(
- registration_.get(), GURL("https://host/script.js"),
- blink::mojom::ScriptType::kClassic, context->storage()->NewVersionId(),
- context->AsWeakPtr());
+ registration_.get(), script_url_, blink::mojom::ScriptType::kClassic,
+ context->storage()->NewVersionId(), context->AsWeakPtr());
provider_host_ = CreateProviderHostForServiceWorkerContext(
helper_->mock_render_process_id(), true /* is_parent_frame_secure */,
version_.get(), context->AsWeakPtr(), &remote_endpoint_);
- network_loader_factory_ = std::make_unique<MockNetworkURLLoaderFactory>();
+ network_loader_factory_ = std::make_unique<FakeNetworkURLLoaderFactory>();
helper_->SetNetworkFactory(network_loader_factory_.get());
factory_ = std::make_unique<ServiceWorkerScriptLoaderFactory>(
@@ -113,7 +61,7 @@ class ServiceWorkerScriptLoaderFactoryTest : public testing::Test {
network::TestURLLoaderClient* client) {
network::mojom::URLLoaderPtr loader;
network::ResourceRequest resource_request;
- resource_request.url = scope_;
+ resource_request.url = script_url_;
resource_request.resource_type =
static_cast<int>(ResourceType::kServiceWorker);
factory_->CreateLoaderAndStart(
@@ -127,11 +75,12 @@ class ServiceWorkerScriptLoaderFactoryTest : public testing::Test {
TestBrowserThreadBundle browser_thread_bundle_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
GURL scope_;
+ GURL script_url_;
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> version_;
base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
ServiceWorkerRemoteProviderEndpoint remote_endpoint_;
- std::unique_ptr<MockNetworkURLLoaderFactory> network_loader_factory_;
+ std::unique_ptr<FakeNetworkURLLoaderFactory> network_loader_factory_;
std::unique_ptr<ServiceWorkerScriptLoaderFactory> factory_;
};
@@ -170,4 +119,97 @@ TEST_F(ServiceWorkerScriptLoaderFactoryTest, ContextDestroyed) {
EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
}
+// This tests copying script and creating resume type
+// ServiceWorkerNewScriptLoaders when ServiceWorkerImportedScriptUpdateCheck
+// is enabled.
+class ServiceWorkerScriptLoaderFactoryCopyResumeTest
+ : public ServiceWorkerScriptLoaderFactoryTest {
+ public:
+ ServiceWorkerScriptLoaderFactoryCopyResumeTest() {
+ feature_list_.InitAndEnableFeature(
+ blink::features::kServiceWorkerImportedScriptUpdateCheck);
+ }
+ ~ServiceWorkerScriptLoaderFactoryCopyResumeTest() override = default;
+
+ void SetUp() override {
+ ServiceWorkerScriptLoaderFactoryTest::SetUp();
+ WriteToDiskCacheSync(helper_->context()->storage(), script_url_,
+ kOldResourceId, kOldHeaders, kOldData, std::string());
+ }
+
+ void CheckResponse(const std::string& expected_body) {
+ // The response should also be stored in the storage.
+ EXPECT_TRUE(ServiceWorkerUpdateCheckTestUtils::VerifyStoredResponse(
+ version_->script_cache_map()->LookupResourceId(script_url_),
+ helper_->context()->storage(), expected_body));
+
+ 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_EQ(expected_body, response);
+ }
+
+ protected:
+ base::test::ScopedFeatureList feature_list_;
+ network::TestURLLoaderClient client_;
+ const std::vector<std::pair<std::string, std::string>> kOldHeaders = {
+ {"Content-Type", "text/javascript"},
+ {"Content-Length", "15"}};
+ const std::string kOldData = "old-script-data";
+ const int64_t kOldResourceId = 1;
+ const int64_t kNewResourceId = 2;
+};
+
+// Tests scripts are copied and loaded locally when compared to be
+// identical in update check.
+TEST_F(ServiceWorkerScriptLoaderFactoryCopyResumeTest, CopyScript) {
+ ServiceWorkerUpdateCheckTestUtils::SetComparedScriptInfoForVersion(
+ script_url_, kOldResourceId,
+ ServiceWorkerSingleScriptUpdateChecker::Result::kIdentical, nullptr,
+ version_.get());
+
+ network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client_);
+ client_.RunUntilComplete();
+
+ EXPECT_EQ(net::OK, client_.completion_status().error_code);
+
+ // Checks the received response data.
+ CheckResponse(kOldData);
+}
+
+// Tests loader factory creates resume type ServiceWorkerNewScriptLoader to
+// continue paused download in update check.
+TEST_F(ServiceWorkerScriptLoaderFactoryCopyResumeTest,
+ CreateResumeTypeScriptLoader) {
+ const std::string kNewHeaders =
+ "HTTP/1.0 200 OK\0Content-Type: text/javascript\0Content-Length: 0\0\0";
+ const std::string kNewData = "";
+
+ mojo::ScopedDataPipeProducerHandle network_producer;
+ mojo::ScopedDataPipeConsumerHandle network_consumer;
+
+ ASSERT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(nullptr, &network_producer,
+ &network_consumer));
+ ServiceWorkerUpdateCheckTestUtils::CreateAndSetComparedScriptInfoForVersion(
+ script_url_, 0, kNewHeaders, kNewData, kOldResourceId, kNewResourceId,
+ helper_.get(),
+ ServiceWorkerNewScriptLoader::NetworkLoaderState::kCompleted,
+ ServiceWorkerNewScriptLoader::WriterState::kCompleted,
+ std::move(network_consumer),
+ ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent,
+ version_.get());
+
+ network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client_);
+ network_producer.reset();
+ client_.RunUntilComplete();
+
+ EXPECT_EQ(net::OK, client_.completion_status().error_code);
+
+ // The received response has no body because kNewData is empty.
+ CheckResponse(kNewData);
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_single_script_update_checker.cc b/chromium/content/browser/service_worker/service_worker_single_script_update_checker.cc
index 41f8621408e..959664eff92 100644
--- a/chromium/content/browser/service_worker/service_worker_single_script_update_checker.cc
+++ b/chromium/content/browser/service_worker/service_worker_single_script_update_checker.cc
@@ -9,9 +9,11 @@
#include "base/bind.h"
#include "content/browser/appcache/appcache_response.h"
#include "content/browser/service_worker/service_worker_cache_writer.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/resource_type.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/ip_endpoint.h"
+#include "net/base/load_flags.h"
#include "services/network/public/cpp/net_adapters.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
@@ -68,12 +70,18 @@ namespace content {
ServiceWorkerSingleScriptUpdateChecker::ServiceWorkerSingleScriptUpdateChecker(
const GURL& url,
bool is_main_script,
+ bool force_bypass_cache,
+ blink::mojom::ServiceWorkerUpdateViaCache update_via_cache,
+ base::TimeDelta time_since_last_check,
scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
std::unique_ptr<ServiceWorkerResponseReader> compare_reader,
std::unique_ptr<ServiceWorkerResponseReader> copy_reader,
std::unique_ptr<ServiceWorkerResponseWriter> writer,
ResultCallback callback)
: script_url_(url),
+ force_bypass_cache_(force_bypass_cache),
+ update_via_cache_(update_via_cache),
+ time_since_last_check_(time_since_last_check),
network_client_binding_(this),
network_watcher_(FROM_HERE,
mojo::SimpleWatcher::ArmingPolicy::MANUAL,
@@ -88,7 +96,11 @@ ServiceWorkerSingleScriptUpdateChecker::ServiceWorkerSingleScriptUpdateChecker(
if (is_main_script)
resource_request.headers.SetHeader("Service-Worker", "script");
- // TODO(momohatt): Handle cases where force_bypass_cache is enabled.
+ if (ServiceWorkerUtils::ShouldValidateBrowserCacheForScript(
+ is_main_script, force_bypass_cache_, update_via_cache_,
+ time_since_last_check_)) {
+ resource_request.load_flags |= net::LOAD_VALIDATE_CACHE;
+ }
cache_writer_ = ServiceWorkerCacheWriter::CreateForComparison(
std::move(compare_reader), std::move(copy_reader), std::move(writer),
@@ -135,7 +147,7 @@ void ServiceWorkerSingleScriptUpdateChecker::OnReceiveResponse(
network_loader_state_ =
ServiceWorkerNewScriptLoader::NetworkLoaderState::kWaitingForBody;
-
+ network_accessed_ = response_head.network_accessed;
WriteHeaders(
base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(response_info)));
}
@@ -157,7 +169,7 @@ void ServiceWorkerSingleScriptUpdateChecker::OnUploadProgress(
}
void ServiceWorkerSingleScriptUpdateChecker::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {}
+ mojo_base::BigBuffer data) {}
void ServiceWorkerSingleScriptUpdateChecker::OnTransferSizeUpdated(
int32_t transfer_size_diff) {}
diff --git a/chromium/content/browser/service_worker/service_worker_single_script_update_checker.h b/chromium/content/browser/service_worker/service_worker_single_script_update_checker.h
index 391123f2071..49dee2d9bde 100644
--- a/chromium/content/browser/service_worker/service_worker_single_script_update_checker.h
+++ b/chromium/content/browser/service_worker/service_worker_single_script_update_checker.h
@@ -10,6 +10,7 @@
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/network/public/mojom/url_loader.mojom.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
namespace network {
class MojoToNetPendingBuffer;
@@ -75,6 +76,9 @@ class CONTENT_EXPORT ServiceWorkerSingleScriptUpdateChecker
ServiceWorkerSingleScriptUpdateChecker(
const GURL& url,
bool is_main_script,
+ bool force_bypass_cache,
+ blink::mojom::ServiceWorkerUpdateViaCache update_via_cache,
+ base::TimeDelta time_since_last_check,
scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
std::unique_ptr<ServiceWorkerResponseReader> compare_reader,
std::unique_ptr<ServiceWorkerResponseReader> copy_reader,
@@ -92,12 +96,14 @@ class CONTENT_EXPORT ServiceWorkerSingleScriptUpdateChecker
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle consumer) override;
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
+ bool network_accessed() const { return network_accessed_; }
+
private:
void WriteHeaders(scoped_refptr<HttpResponseInfoIOBuffer> info_buffer);
void OnWriteHeadersComplete(net::Error error);
@@ -115,6 +121,10 @@ class CONTENT_EXPORT ServiceWorkerSingleScriptUpdateChecker
void Finish(Result result);
const GURL script_url_;
+ const bool force_bypass_cache_;
+ const blink::mojom::ServiceWorkerUpdateViaCache update_via_cache_;
+ const base::TimeDelta time_since_last_check_;
+ bool network_accessed_ = false;
network::mojom::URLLoaderPtr network_loader_;
mojo::Binding<network::mojom::URLLoaderClient> network_client_binding_;
diff --git a/chromium/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc b/chromium/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
index 38c55e65361..3dd1a988503 100644
--- a/chromium/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
@@ -13,6 +13,7 @@
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/load_flags.h"
#include "net/http/http_util.h"
#include "services/network/test/test_url_loader_factory.h"
@@ -20,6 +21,7 @@ namespace content {
namespace {
constexpr char kScriptURL[] = "https://example.com/script.js";
+constexpr char kImportedScriptURL[] = "https://example.com/imported-script.js";
constexpr char kSuccessHeader[] =
"HTTP/1.1 200 OK\n"
"Content-Type: text/javascript\n\n";
@@ -68,9 +70,30 @@ class ServiceWorkerSingleScriptUpdateCheckerTest : public testing::Test {
return bytes;
}
+ // Create an update checker which will always ask HTTP cache validation.
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker>
+ CreateSingleScriptUpdateCheckerWithoutHttpCache(
+ const char* url,
+ std::unique_ptr<ServiceWorkerResponseReader> compare_reader,
+ std::unique_ptr<ServiceWorkerResponseReader> copy_reader,
+ std::unique_ptr<ServiceWorkerResponseWriter> writer,
+ network::TestURLLoaderFactory* loader_factory,
+ base::Optional<CheckResult>* out_check_result) {
+ return CreateSingleScriptUpdateChecker(
+ url, true /* is_main_script */, false /* force_bypass_cache */,
+ blink::mojom::ServiceWorkerUpdateViaCache::kNone,
+ base::TimeDelta() /* time_since_last_check */,
+ std::move(compare_reader), std::move(copy_reader), std::move(writer),
+ loader_factory, out_check_result);
+ }
+
std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker>
CreateSingleScriptUpdateChecker(
const char* url,
+ bool is_main_script,
+ bool force_bypass_cache,
+ blink::mojom::ServiceWorkerUpdateViaCache update_via_cache,
+ base::TimeDelta time_since_last_check,
std::unique_ptr<ServiceWorkerResponseReader> compare_reader,
std::unique_ptr<ServiceWorkerResponseReader> copy_reader,
std::unique_ptr<ServiceWorkerResponseWriter> writer,
@@ -78,7 +101,8 @@ class ServiceWorkerSingleScriptUpdateCheckerTest : public testing::Test {
base::Optional<CheckResult>* out_check_result) {
helper_->SetNetworkFactory(loader_factory);
return std::make_unique<ServiceWorkerSingleScriptUpdateChecker>(
- GURL(url), true /* is_main_script */,
+ GURL(url), is_main_script, force_bypass_cache, update_via_cache,
+ time_since_last_check,
helper_->url_loader_factory_getter()->GetNetworkFactory(),
std::move(compare_reader), std::move(copy_reader), std::move(writer),
base::BindOnce(
@@ -102,7 +126,7 @@ class ServiceWorkerSingleScriptUpdateCheckerTest : public testing::Test {
auto loader_factory = std::make_unique<network::TestURLLoaderFactory>();
network::ResourceResponseHead head;
head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
- net::HttpUtil::AssembleRawHeaders(header.c_str(), header.size()));
+ net::HttpUtil::AssembleRawHeaders(header));
network::URLLoaderCompletionStatus status(error);
status.decoded_body_length = body.size();
loader_factory->AddResponse(url, head, body, status);
@@ -137,9 +161,9 @@ TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Identical_SingleSyncRead) {
base::Optional<CheckResult> check_result;
std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
- CreateSingleScriptUpdateChecker(kScriptURL, std::move(compare_reader),
- std::move(copy_reader), std::move(writer),
- loader_factory.get(), &check_result);
+ CreateSingleScriptUpdateCheckerWithoutHttpCache(
+ kScriptURL, std::move(compare_reader), std::move(copy_reader),
+ std::move(writer), loader_factory.get(), &check_result);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(check_result.has_value());
EXPECT_EQ(check_result.value().result,
@@ -168,9 +192,9 @@ TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Different_SingleSyncRead) {
base::Optional<CheckResult> check_result;
std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
- CreateSingleScriptUpdateChecker(kScriptURL, std::move(compare_reader),
- std::move(copy_reader), std::move(writer),
- loader_factory.get(), &check_result);
+ CreateSingleScriptUpdateCheckerWithoutHttpCache(
+ kScriptURL, std::move(compare_reader), std::move(copy_reader),
+ std::move(writer), loader_factory.get(), &check_result);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(check_result.has_value());
@@ -201,9 +225,9 @@ TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Different_MultipleSyncRead) {
base::Optional<CheckResult> check_result;
std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
- CreateSingleScriptUpdateChecker(kScriptURL, std::move(compare_reader),
- std::move(copy_reader), std::move(writer),
- loader_factory.get(), &check_result);
+ CreateSingleScriptUpdateCheckerWithoutHttpCache(
+ kScriptURL, std::move(compare_reader), std::move(copy_reader),
+ std::move(writer), loader_factory.get(), &check_result);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(check_result.has_value());
@@ -233,9 +257,9 @@ TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, NetworkDataLong_SyncRead) {
base::Optional<CheckResult> check_result;
std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
- CreateSingleScriptUpdateChecker(kScriptURL, std::move(compare_reader),
- std::move(copy_reader), std::move(writer),
- loader_factory.get(), &check_result);
+ CreateSingleScriptUpdateCheckerWithoutHttpCache(
+ kScriptURL, std::move(compare_reader), std::move(copy_reader),
+ std::move(writer), loader_factory.get(), &check_result);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(check_result.has_value());
EXPECT_EQ(check_result.value().result,
@@ -268,9 +292,9 @@ TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, NetworkDataShort_SyncRead) {
base::Optional<CheckResult> check_result;
std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
- CreateSingleScriptUpdateChecker(kScriptURL, std::move(compare_reader),
- std::move(copy_reader), std::move(writer),
- loader_factory.get(), &check_result);
+ CreateSingleScriptUpdateCheckerWithoutHttpCache(
+ kScriptURL, std::move(compare_reader), std::move(copy_reader),
+ std::move(writer), loader_factory.get(), &check_result);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(check_result.has_value());
EXPECT_EQ(check_result.value().result,
@@ -299,9 +323,9 @@ TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Identical_SingleAsyncRead) {
base::Optional<CheckResult> check_result;
std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
- CreateSingleScriptUpdateChecker(kScriptURL, std::move(compare_reader),
- std::move(copy_reader), std::move(writer),
- loader_factory.get(), &check_result);
+ CreateSingleScriptUpdateCheckerWithoutHttpCache(
+ kScriptURL, std::move(compare_reader), std::move(copy_reader),
+ std::move(writer), loader_factory.get(), &check_result);
// Update check stops in WriteHeader() due to the asynchronous read of the
// |compare_reader|.
@@ -326,5 +350,174 @@ TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Identical_SingleAsyncRead) {
EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone());
}
+// Tests cache validation behavior when updateViaCache is 'all'.
+TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, UpdateViaCache_All) {
+ auto loader_factory = std::make_unique<network::TestURLLoaderFactory>();
+ base::Optional<CheckResult> check_result;
+
+ // Load the main script. Should not validate the cache.
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
+ CreateSingleScriptUpdateChecker(
+ kScriptURL, true /* is_main_script */, false /* force_bypass_cache */,
+ blink::mojom::ServiceWorkerUpdateViaCache::kAll, base::TimeDelta(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseWriter>(),
+ loader_factory.get(), &check_result);
+
+ const network::ResourceRequest* request = nullptr;
+ ASSERT_TRUE(loader_factory->IsPending(kScriptURL, &request));
+ EXPECT_FALSE(request->load_flags & net::LOAD_VALIDATE_CACHE);
+
+ // Load imported script. Should not validate the cache.
+ checker = CreateSingleScriptUpdateChecker(
+ kImportedScriptURL, false /* is_main_script */,
+ false /* force_bypass_cache */,
+ blink::mojom::ServiceWorkerUpdateViaCache::kAll, base::TimeDelta(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseWriter>(), loader_factory.get(),
+ &check_result);
+
+ ASSERT_TRUE(loader_factory->IsPending(kImportedScriptURL, &request));
+ EXPECT_FALSE(request->load_flags & net::LOAD_VALIDATE_CACHE);
+}
+
+// Tests cache validation behavior when updateViaCache is 'none'.
+TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, UpdateViaCache_None) {
+ auto loader_factory = std::make_unique<network::TestURLLoaderFactory>();
+ base::Optional<CheckResult> check_result;
+
+ // Load the main script. Should validate the cache.
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
+ CreateSingleScriptUpdateChecker(
+ kScriptURL, true /* is_main_script */, false /* force_bypass_cache */,
+ blink::mojom::ServiceWorkerUpdateViaCache::kNone, base::TimeDelta(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseWriter>(),
+ loader_factory.get(), &check_result);
+
+ const network::ResourceRequest* request = nullptr;
+ ASSERT_TRUE(loader_factory->IsPending(kScriptURL, &request));
+ EXPECT_TRUE(request->load_flags & net::LOAD_VALIDATE_CACHE);
+
+ // Load imported script. Should validate the cache.
+ checker = CreateSingleScriptUpdateChecker(
+ kImportedScriptURL, false /* is_main_script */,
+ false /* force_bypass_cache */,
+ blink::mojom::ServiceWorkerUpdateViaCache::kNone, base::TimeDelta(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseWriter>(), loader_factory.get(),
+ &check_result);
+
+ ASSERT_TRUE(loader_factory->IsPending(kImportedScriptURL, &request));
+ EXPECT_TRUE(request->load_flags & net::LOAD_VALIDATE_CACHE);
+}
+
+// Tests cache validation behavior when updateViaCache is 'imports'.
+TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, UpdateViaCache_Imports) {
+ auto loader_factory = std::make_unique<network::TestURLLoaderFactory>();
+ base::Optional<CheckResult> check_result;
+
+ // Load main script. Should validate the cache.
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
+ CreateSingleScriptUpdateChecker(
+ kScriptURL, true /* is_main_script */, false /* force_bypass_cache */,
+ blink::mojom::ServiceWorkerUpdateViaCache::kImports,
+ base::TimeDelta(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseWriter>(),
+ loader_factory.get(), &check_result);
+
+ const network::ResourceRequest* request = nullptr;
+ ASSERT_TRUE(loader_factory->IsPending(kScriptURL, &request));
+ EXPECT_TRUE(request->load_flags & net::LOAD_VALIDATE_CACHE);
+
+ // Load imported script. Should not validate the cache.
+ checker = CreateSingleScriptUpdateChecker(
+ kImportedScriptURL, false /* is_main_script */,
+ false /* force_bypass_cache */,
+ blink::mojom::ServiceWorkerUpdateViaCache::kImports, base::TimeDelta(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseWriter>(), loader_factory.get(),
+ &check_result);
+
+ ASSERT_TRUE(loader_factory->IsPending(kImportedScriptURL, &request));
+ EXPECT_FALSE(request->load_flags & net::LOAD_VALIDATE_CACHE);
+}
+
+// Tests cache validation behavior when version's
+// |force_bypass_cache_for_scripts_| is true.
+TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, ForceBypassCache) {
+ auto loader_factory = std::make_unique<network::TestURLLoaderFactory>();
+ base::Optional<CheckResult> check_result;
+
+ // Load main script. Should validate the cache.
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
+ CreateSingleScriptUpdateChecker(
+ kScriptURL, true /* is_main_script */, true /* force_bypass_cache */,
+ blink::mojom::ServiceWorkerUpdateViaCache::kAll, base::TimeDelta(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseWriter>(),
+ loader_factory.get(), &check_result);
+
+ const network::ResourceRequest* request = nullptr;
+ ASSERT_TRUE(loader_factory->IsPending(kScriptURL, &request));
+ EXPECT_TRUE(request->load_flags & net::LOAD_VALIDATE_CACHE);
+
+ // Load imported script. Should validate the cache.
+ checker = CreateSingleScriptUpdateChecker(
+ kImportedScriptURL, false /* is_main_script */,
+ true /* force_bypass_cache */,
+ blink::mojom::ServiceWorkerUpdateViaCache::kAll, base::TimeDelta(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseWriter>(), loader_factory.get(),
+ &check_result);
+
+ ASSERT_TRUE(loader_factory->IsPending(kImportedScriptURL, &request));
+ EXPECT_TRUE(request->load_flags & net::LOAD_VALIDATE_CACHE);
+}
+
+// Tests cache validation behavior when more than 24 hours passed.
+TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, MoreThan24Hours) {
+ auto loader_factory = std::make_unique<network::TestURLLoaderFactory>();
+ base::Optional<CheckResult> check_result;
+
+ // Load main script. Should validate the cache.
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
+ CreateSingleScriptUpdateChecker(
+ kScriptURL, true /* is_main_script */, false /* force_bypass_cache */,
+ blink::mojom::ServiceWorkerUpdateViaCache::kAll,
+ base::TimeDelta::FromDays(1) + base::TimeDelta::FromHours(1),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseWriter>(),
+ loader_factory.get(), &check_result);
+
+ const network::ResourceRequest* request = nullptr;
+ ASSERT_TRUE(loader_factory->IsPending(kScriptURL, &request));
+ EXPECT_TRUE(request->load_flags & net::LOAD_VALIDATE_CACHE);
+
+ // Load imported script. Should validate the cache.
+ checker = CreateSingleScriptUpdateChecker(
+ kImportedScriptURL, false /* is_main_script */,
+ false /* force_bypass_cache */,
+ blink::mojom::ServiceWorkerUpdateViaCache::kAll,
+ base::TimeDelta::FromDays(1) + base::TimeDelta::FromHours(1),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseReader>(),
+ std::make_unique<MockServiceWorkerResponseWriter>(), loader_factory.get(),
+ &check_result);
+
+ ASSERT_TRUE(loader_factory->IsPending(kImportedScriptURL, &request));
+ EXPECT_TRUE(request->load_flags & net::LOAD_VALIDATE_CACHE);
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_storage.cc b/chromium/content/browser/service_worker/service_worker_storage.cc
index 6c0de46d5f1..7c8be28cb61 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage.cc
@@ -33,8 +33,6 @@
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
-using std::swap;
-
namespace content {
namespace {
@@ -68,8 +66,8 @@ const base::FilePath::CharType kDatabaseName[] =
const base::FilePath::CharType kDiskCacheName[] =
FILE_PATH_LITERAL("ScriptCache");
+// Taken from AppCache's in-memory cache size.
const int kMaxServiceWorkerStorageMemDiskCacheSize = 10 * 1024 * 1024;
-const int kMaxServiceWorkerStorageDiskCacheSize = 250 * 1024 * 1024;
blink::ServiceWorkerStatusCode DatabaseStatusToStatusCode(
ServiceWorkerDatabase::Status status) {
@@ -429,6 +427,7 @@ void ServiceWorkerStorage::StoreRegistration(
DCHECK_NE(version->fetch_handler_existence(),
ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN);
+ DCHECK_EQ(registration->status(), ServiceWorkerRegistration::Status::kIntact);
ServiceWorkerDatabase::RegistrationData data;
data.registration_id = registration->id();
@@ -446,7 +445,7 @@ void ServiceWorkerStorage::StoreRegistration(
data.navigation_preload_state = registration->navigation_preload_state();
data.script_response_time = version->GetInfo().script_response_time;
for (const blink::mojom::WebFeature feature : version->used_features())
- data.used_features.insert(static_cast<uint32_t>(feature));
+ data.used_features.insert(feature);
ResourceList resources;
version->script_cache_map()->GetResources(&resources);
@@ -474,8 +473,6 @@ void ServiceWorkerStorage::StoreRegistration(
base::BindOnce(&ServiceWorkerStorage::DidStoreRegistration,
weak_factory_.GetWeakPtr(),
std::move(callback), data)));
-
- registration->set_is_deleted(false);
}
void ServiceWorkerStorage::UpdateToActiveState(
@@ -562,9 +559,10 @@ void ServiceWorkerStorage::UpdateNavigationPreloadHeader(
base::BindOnce(&DidUpdateNavigationPreloadState, std::move(callback)));
}
-void ServiceWorkerStorage::DeleteRegistration(int64_t registration_id,
- const GURL& origin,
- StatusCallback callback) {
+void ServiceWorkerStorage::DeleteRegistration(
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ const GURL& origin,
+ StatusCallback callback) {
DCHECK(state_ == STORAGE_STATE_INITIALIZED ||
state_ == STORAGE_STATE_DISABLED)
<< state_;
@@ -578,23 +576,22 @@ void ServiceWorkerStorage::DeleteRegistration(int64_t registration_id,
if (!has_checked_for_stale_resources_)
DeleteStaleResources();
+ DCHECK(!registration->is_deleted())
+ << "attempt to delete a registration twice";
+
auto params = std::make_unique<DidDeleteRegistrationParams>(
- registration_id, origin, std::move(callback));
+ registration->id(), origin, std::move(callback));
database_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&DeleteRegistrationFromDB, database_.get(),
- base::ThreadTaskRunnerHandle::Get(), registration_id, origin,
+ base::ThreadTaskRunnerHandle::Get(), registration->id(), origin,
base::BindOnce(&ServiceWorkerStorage::DidDeleteRegistration,
weak_factory_.GetWeakPtr(), std::move(params))));
- // The registration should no longer be findable.
- pending_deletions_.insert(registration_id);
- ServiceWorkerRegistration* registration =
- context_->GetLiveRegistration(registration_id);
- if (registration)
- registration->set_is_deleted(true);
+ uninstalling_registrations_[registration->id()] = registration;
+ registration->SetStatus(ServiceWorkerRegistration::Status::kUninstalling);
}
void ServiceWorkerStorage::PerformStorageCleanup(base::OnceClosure callback) {
@@ -1121,15 +1118,10 @@ void ServiceWorkerStorage::NotifyDoneInstallingRegistration(
}
}
-void ServiceWorkerStorage::NotifyUninstallingRegistration(
- ServiceWorkerRegistration* registration) {
- DCHECK(uninstalling_registrations_.find(registration->id()) ==
- uninstalling_registrations_.end());
- uninstalling_registrations_[registration->id()] = registration;
-}
-
void ServiceWorkerStorage::NotifyDoneUninstallingRegistration(
- ServiceWorkerRegistration* registration) {
+ ServiceWorkerRegistration* registration,
+ ServiceWorkerRegistration::Status new_status) {
+ registration->SetStatus(new_status);
uninstalling_registrations_.erase(registration->id());
}
@@ -1493,12 +1485,25 @@ void ServiceWorkerStorage::DidStoreRegistration(
deleted_version.resources_total_size_bytes);
}
+ // Purge the deleted version's resources now if needed. This is subtle. The
+ // version might still be used for a long time even after it's deleted. We can
+ // only purge safely once the version is REDUNDANT, since it will never be
+ // used again.
+ //
+ // If the deleted version's ServiceWorkerVersion doesn't exist, we can assume
+ // it's effectively REDUNDANT so it's safe to purge now. This is because the
+ // caller is assumed to promote the new version to active unless the deleted
+ // version is doing work, and it can't be doing work if it's not live.
+ //
+ // If the ServiceWorkerVersion does exist, it triggers purging once it reaches
+ // REDUNDANT. Otherwise, purging happens on the next browser session (via
+ // DeleteStaleResources).
+ if (!context_->GetLiveVersion(deleted_version.version_id))
+ StartPurgingResources(newly_purgeable_resources);
+
context_->NotifyRegistrationStored(new_version.registration_id,
new_version.scope);
std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk);
-
- if (!context_->GetLiveVersion(deleted_version.version_id))
- StartPurgingResources(newly_purgeable_resources);
}
void ServiceWorkerStorage::DidUpdateToActiveState(
@@ -1517,7 +1522,6 @@ void ServiceWorkerStorage::DidDeleteRegistration(
const ServiceWorkerDatabase::RegistrationData& deleted_version,
const std::vector<int64_t>& newly_purgeable_resources,
ServiceWorkerDatabase::Status status) {
- pending_deletions_.erase(params->registration_id);
if (status != ServiceWorkerDatabase::STATUS_OK) {
ScheduleDeleteAndStartOver();
std::move(params->callback).Run(DatabaseStatusToStatusCode(status));
@@ -1622,10 +1626,9 @@ ServiceWorkerStorage::GetOrCreateRegistration(
new ServiceWorkerRegistration(options, data.registration_id, context_);
registration->set_resources_total_size_bytes(data.resources_total_size_bytes);
registration->set_last_update_check(data.last_update_check);
- if (pending_deletions_.find(data.registration_id) !=
- pending_deletions_.end()) {
- registration->set_is_deleted(true);
- }
+ DCHECK(uninstalling_registrations_.find(data.registration_id) ==
+ uninstalling_registrations_.end());
+
scoped_refptr<ServiceWorkerVersion> version =
context_->GetLiveVersion(data.version_id);
if (!version) {
@@ -1642,20 +1645,7 @@ ServiceWorkerStorage::GetOrCreateRegistration(
if (data.origin_trial_tokens)
version->SetValidOriginTrialTokens(*data.origin_trial_tokens);
- // Some features may be outside the valid range of features, if the data on
- // disk was written by a later version of Chrome than currently running
- // (crbug.com/758419).
- // TODO(falken): Maybe Chrome should have a generic mechanism to detect
- // profile downgrade and just abort? Or we could just crash here, but that
- // seems extreme and difficult for a user to escape.
- std::set<blink::mojom::WebFeature> used_features;
- for (const uint32_t feature : data.used_features) {
- if (feature <
- static_cast<uint32_t>(blink::mojom::WebFeature::kNumberOfFeatures)) {
- used_features.insert(static_cast<blink::mojom::WebFeature>(feature));
- }
- }
- version->set_used_features(std::move(used_features));
+ version->set_used_features(data.used_features);
}
version->set_script_response_time_for_devtools(data.script_response_time);
@@ -1735,7 +1725,7 @@ void ServiceWorkerStorage::InitializeDiskCache() {
disk_cache_->set_is_waiting_to_initialize(false);
expecting_done_with_disk_on_disable_ = true;
int rv = disk_cache_->InitWithDiskBackend(
- GetDiskCachePath(), kMaxServiceWorkerStorageDiskCacheSize, false,
+ GetDiskCachePath(), false,
base::BindOnce(&ServiceWorkerStorage::DiskCacheImplDoneWithDisk,
weak_factory_.GetWeakPtr()),
base::BindOnce(&ServiceWorkerStorage::OnDiskCacheInitialized,
@@ -1805,6 +1795,9 @@ void ServiceWorkerStorage::OnResourcePurged(int64_t id, int rv) {
ServiceWorkerMetrics::RecordPurgeResourceResult(rv);
+ // TODO(falken): Is it always OK to ClearPurgeableResourceIds if |rv| is
+ // failure? The disk cache entry might still remain and once we remove its
+ // purgeable id, we will never retry deleting it.
std::set<int64_t> ids = {id};
database_task_runner_->PostTask(
FROM_HERE,
diff --git a/chromium/content/browser/service_worker/service_worker_storage.h b/chromium/content/browser/service_worker/service_worker_storage.h
index 9a69a5fa4cb..02177be3e60 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.h
+++ b/chromium/content/browser/service_worker/service_worker_storage.h
@@ -23,6 +23,7 @@
#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_database.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_version.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
@@ -41,7 +42,6 @@ namespace content {
class ServiceWorkerContextCore;
class ServiceWorkerDiskCache;
-class ServiceWorkerRegistration;
class ServiceWorkerResponseMetadataWriter;
class ServiceWorkerResponseReader;
class ServiceWorkerResponseWriter;
@@ -166,10 +166,16 @@ class CONTENT_EXPORT ServiceWorkerStorage
const std::string& value,
StatusCallback callback);
- // Deletes the registration data for |registration_id|. If the registration's
- // version is live, its script resources will remain available.
- // PurgeResources should be called when it's OK to delete them.
- void DeleteRegistration(int64_t registration_id,
+ // Deletes the registration data for |registration|. The live registration is
+ // still findable via GetUninstallingRegistration(), and versions are usable
+ // because their script resources have not been deleted. After calling this,
+ // the caller should later:
+ // - Call NotifyDoneUninstallingRegistration() to let storage know the
+ // uninstalling operation is done.
+ // - If it no longer wants versions to be usable, call PurgeResources() to
+ // delete their script resources.
+ // If these aren't called, on the next profile session the cleanup occurs.
+ void DeleteRegistration(scoped_refptr<ServiceWorkerRegistration> registration,
const GURL& origin,
StatusCallback callback);
@@ -267,13 +273,17 @@ class CONTENT_EXPORT ServiceWorkerStorage
void NotifyDoneInstallingRegistration(ServiceWorkerRegistration* registration,
ServiceWorkerVersion* version,
blink::ServiceWorkerStatusCode status);
- void NotifyUninstallingRegistration(ServiceWorkerRegistration* registration);
void NotifyDoneUninstallingRegistration(
- ServiceWorkerRegistration* registration);
+ ServiceWorkerRegistration* registration,
+ ServiceWorkerRegistration::Status new_status);
void Disable();
- // |resources| must already be on the purgeable list.
+ // Schedules deleting |resources| from the disk cache and removing their keys
+ // as purgeable resources from the service worker database. It's OK to call
+ // this for resources that don't have purgeable resource keys, like
+ // uncommitted resources, as long as the caller does its own cleanup to remove
+ // the uncommitted resource keys.
void PurgeResources(const ResourceList& resources);
bool LazyInitializeForTest(base::OnceClosure callback);
@@ -603,7 +613,6 @@ class CONTENT_EXPORT ServiceWorkerStorage
base::circular_deque<int64_t> purgeable_resource_ids_;
bool is_purge_pending_;
bool has_checked_for_stale_resources_;
- std::set<int64_t> pending_deletions_;
base::WeakPtrFactory<ServiceWorkerStorage> weak_factory_;
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 f2d3426438d..3289028b233 100644
--- a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -399,12 +399,13 @@ class ServiceWorkerStorageTest : public testing::Test {
return result.value();
}
- blink::ServiceWorkerStatusCode DeleteRegistration(int64_t registration_id,
- const GURL& origin) {
+ blink::ServiceWorkerStatusCode DeleteRegistration(
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ const GURL& origin) {
bool was_called = false;
base::Optional<blink::ServiceWorkerStatusCode> result;
- storage()->DeleteRegistration(
- registration_id, origin, MakeStatusCallback(&was_called, &result));
+ storage()->DeleteRegistration(registration, origin,
+ MakeStatusCallback(&was_called, &result));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
@@ -672,7 +673,7 @@ TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
UpdateToActiveState(live_registration));
EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
- DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
+ DeleteRegistration(live_registration, kScope.GetOrigin()));
// Response reader and writer created by the disabled storage should fail to
// access the disk cache.
@@ -888,25 +889,6 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
found_registration->active_version()->status());
EXPECT_EQ(kToday, found_registration->last_update_check());
-
- // Delete from storage but with a instance still live.
- EXPECT_TRUE(context()->GetLiveVersion(kRegistrationId));
- EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
- DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
- EXPECT_TRUE(context()->GetLiveVersion(kRegistrationId));
-
- // Should no longer be found.
- EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
- FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
- &found_registration));
- EXPECT_FALSE(found_registration.get());
- EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
- FindRegistrationForIdOnly(kRegistrationId, &found_registration));
- EXPECT_FALSE(found_registration.get());
-
- // Deleting an unstored registration should succeed.
- EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
- DeleteRegistration(kRegistrationId + 1, kScope.GetOrigin()));
}
TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
@@ -1154,7 +1136,7 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
ASSERT_EQ("data", data_out[0]);
EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
- DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
+ DeleteRegistration(live_registration, kScope.GetOrigin()));
EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
GetUserData(kRegistrationId, {"key"}, &data_out));
data_list_out.clear();
@@ -1399,13 +1381,12 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
std::set<int64_t> verify_ids;
registration_->SetWaitingVersion(nullptr);
- registration_ = nullptr;
// Deleting the registration should result in the resources being added to the
// purgeable list and then doomed in the disk cache and removed from that
// list.
storage()->DeleteRegistration(
- registration_id_, scope_.GetOrigin(),
+ registration_, scope_.GetOrigin(),
base::BindOnce(&VerifyPurgeableListStatusCallback,
base::Unretained(database()), &verify_ids, &was_called,
&result));
@@ -1432,7 +1413,7 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
// purgeable list and then doomed in the disk cache and removed from that
// list.
storage()->DeleteRegistration(
- registration_->id(), scope_.GetOrigin(),
+ registration_, scope_.GetOrigin(),
base::BindOnce(&VerifyPurgeableListStatusCallback,
base::Unretained(database()), &verify_ids, &was_called,
&result));
@@ -1448,11 +1429,9 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, false));
EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, false));
- // Doom the version, now it happens.
+ // Doom the version. The resources should be purged.
registration_->waiting_version()->Doom();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
- EXPECT_EQ(2u, verify_ids.size());
verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
database()->GetPurgeableResourceIds(&verify_ids));
@@ -1465,6 +1444,7 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
// Promote the worker to active and add a controllee.
registration_->SetActiveVersion(registration_->waiting_version());
+ registration_->active_version()->SetStatus(ServiceWorkerVersion::ACTIVATED);
storage()->UpdateToActiveState(registration_.get(), base::DoNothing());
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
base::WeakPtr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow(
@@ -1480,7 +1460,7 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
// Deleting the registration should move the resources to the purgeable list
// but keep them available.
storage()->DeleteRegistration(
- registration_->id(), scope_.GetOrigin(),
+ registration_, scope_.GetOrigin(),
base::BindOnce(&VerifyPurgeableListStatusCallback,
base::Unretained(database()), &verify_ids, &was_called,
&result));
@@ -1496,10 +1476,11 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
- // Removing the controllee should cause the resources to be deleted.
+ // Dooming the version should cause the resources to be deleted.
registration_->active_version()->RemoveControllee(host->client_uuid());
registration_->active_version()->Doom();
base::RunLoop().RunUntilIdle();
+
verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
database()->GetPurgeableResourceIds(&verify_ids));
@@ -1512,6 +1493,7 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
TEST_F(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
// Promote the worker to active and add a controllee.
registration_->SetActiveVersion(registration_->waiting_version());
+ registration_->active_version()->SetStatus(ServiceWorkerVersion::ACTIVATED);
registration_->SetWaitingVersion(nullptr);
storage()->UpdateToActiveState(registration_.get(), base::DoNothing());
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
@@ -1528,7 +1510,7 @@ TEST_F(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
// Deleting the registration should move the resources to the purgeable list
// but keep them available.
storage()->DeleteRegistration(
- registration_->id(), scope_.GetOrigin(),
+ registration_, scope_.GetOrigin(),
base::BindOnce(&VerifyPurgeableListStatusCallback,
base::Unretained(database()), &verify_ids, &was_called,
&result));
@@ -1672,6 +1654,7 @@ TEST_F(ServiceWorkerResourceStorageDiskTest,
TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
// Promote the worker to active worker and add a controllee.
registration_->SetActiveVersion(registration_->waiting_version());
+ registration_->active_version()->SetStatus(ServiceWorkerVersion::ACTIVATED);
storage()->UpdateToActiveState(registration_.get(), base::DoNothing());
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
base::WeakPtr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow(
@@ -1715,10 +1698,15 @@ TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, false));
EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, false));
- // Removing the controllee should cause the old version's resources to be
- // deleted.
- registration_->active_version()->RemoveControllee(host->client_uuid());
- registration_->active_version()->Doom();
+ // Remove the controllee to allow the new version to become active, making the
+ // old version redundant.
+ scoped_refptr<ServiceWorkerVersion> old_version(
+ registration_->active_version());
+ old_version->RemoveControllee(host->client_uuid());
+ registration_->ActivateWaitingVersionWhenReady();
+ EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
+
+ // Its resources should be purged.
base::RunLoop().RunUntilIdle();
verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -1729,6 +1717,52 @@ TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
}
+TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration_NoLiveVersion) {
+ // Promote the worker to active worker and add a controllee.
+ registration_->SetActiveVersion(registration_->waiting_version());
+ storage()->UpdateToActiveState(registration_.get(), base::DoNothing());
+
+ // Make an updated registration.
+ scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
+ registration_.get(), script_, blink::mojom::ScriptType::kClassic,
+ storage()->NewVersionId(), context()->AsWeakPtr());
+ live_version->SetStatus(ServiceWorkerVersion::NEW);
+ registration_->SetWaitingVersion(live_version);
+ std::vector<ResourceRecord> records;
+ records.push_back(ResourceRecord(10, live_version->script_url(), 100));
+ live_version->script_cache_map()->SetResources(records);
+ live_version->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+
+ // Destroy the active version.
+ registration_->UnsetVersion(registration_->active_version());
+
+ // Writing the registration should purge the old version's resources,
+ // since it's not live.
+ std::set<int64_t> verify_ids;
+ bool was_called = false;
+ auto result = blink::ServiceWorkerStatusCode::kErrorFailed;
+ storage()->StoreRegistration(
+ registration_.get(), registration_->waiting_version(),
+ base::BindOnce(&VerifyPurgeableListStatusCallback,
+ base::Unretained(database()), &verify_ids, &was_called,
+ &result));
+ base::RunLoop().RunUntilIdle();
+
+ // The StoreRegistration callback was called with the purgeable list.
+ ASSERT_TRUE(was_called);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
+ EXPECT_EQ(2u, verify_ids.size());
+
+ // The resources have already been purged.
+ verify_ids.clear();
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database()->GetPurgeableResourceIds(&verify_ids));
+ EXPECT_TRUE(verify_ids.empty());
+ EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
+ EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
+}
+
TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
LazyInitialize();
const GURL kDocumentUrl("http://www.example.com/scope/foo");
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 e7367dd9fa1..9ae72b78a37 100644
--- a/chromium/content/browser/service_worker/service_worker_test_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_test_utils.cc
@@ -10,6 +10,7 @@
#include "base/barrier_closure.h"
#include "base/run_loop.h"
#include "base/time/time.h"
+#include "content/browser/frame_host/frame_tree_node.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_database.h"
@@ -240,8 +241,8 @@ base::WeakPtr<ServiceWorkerProviderHost> CreateProviderHostForWindow(
auto provider_info = blink::mojom::ServiceWorkerProviderInfoForWindow::New();
base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
- context, is_parent_frame_secure, base::NullCallback(),
- &provider_info);
+ context, is_parent_frame_secure,
+ FrameTreeNode::kFrameTreeNodeInvalidId, &provider_info);
output_endpoint->BindForWindow(std::move(provider_info));
// In production code this is called from NavigationRequest in the browser
diff --git a/chromium/content/browser/service_worker/service_worker_tls_browsertest.cc b/chromium/content/browser/service_worker/service_worker_tls_browsertest.cc
index 1c6b1dce58d..ecda2912292 100644
--- a/chromium/content/browser/service_worker/service_worker_tls_browsertest.cc
+++ b/chromium/content/browser/service_worker/service_worker_tls_browsertest.cc
@@ -25,16 +25,11 @@ class ServiceWorkerTlsTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
ShellContentBrowserClient::Get()->set_select_client_certificate_callback(
- base::BindRepeating(&ServiceWorkerTlsTest::OnSelectClientCertificate,
- base::Unretained(this)));
+ base::BindOnce(&ServiceWorkerTlsTest::OnSelectClientCertificate,
+ base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
}
- void TearDownOnMainThread() override {
- ShellContentBrowserClient::Get()->set_select_client_certificate_callback(
- base::RepeatingClosure());
- }
-
int select_certificate_count() const { return select_certificate_count_; }
GURL GetTestURL(const std::string& test_case, const std::string& query) {
diff --git a/chromium/content/browser/service_worker/service_worker_update_checker.cc b/chromium/content/browser/service_worker/service_worker_update_checker.cc
index 2626e09c089..c28bc034c92 100644
--- a/chromium/content/browser/service_worker/service_worker_update_checker.cc
+++ b/chromium/content/browser/service_worker/service_worker_update_checker.cc
@@ -16,12 +16,18 @@ ServiceWorkerUpdateChecker::ServiceWorkerUpdateChecker(
const GURL& main_script_url,
int64_t main_script_resource_id,
scoped_refptr<ServiceWorkerVersion> version_to_update,
- scoped_refptr<network::SharedURLLoaderFactory> loader_factory)
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
+ bool force_bypass_cache,
+ blink::mojom::ServiceWorkerUpdateViaCache update_via_cache,
+ base::TimeDelta time_since_last_check)
: scripts_to_compare_(std::move(scripts_to_compare)),
main_script_url_(main_script_url),
main_script_resource_id_(main_script_resource_id),
version_to_update_(std::move(version_to_update)),
loader_factory_(std::move(loader_factory)),
+ force_bypass_cache_(force_bypass_cache),
+ update_via_cache_(update_via_cache),
+ time_since_last_check_(time_since_last_check),
weak_factory_(this) {}
ServiceWorkerUpdateChecker::~ServiceWorkerUpdateChecker() = default;
@@ -40,6 +46,9 @@ void ServiceWorkerUpdateChecker::OnOneUpdateCheckFinished(
paused_state) {
script_check_results_[script_url] =
ComparedScriptInfo(old_resource_id, result, std::move(paused_state));
+ if (running_checker_->network_accessed())
+ network_accessed_ = true;
+
running_checker_.reset();
if (ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent == result) {
@@ -96,7 +105,8 @@ void ServiceWorkerUpdateChecker::CheckOneScript(const GURL& url,
auto writer = storage->CreateResponseWriter(storage->NewResourceId());
running_checker_ = std::make_unique<ServiceWorkerSingleScriptUpdateChecker>(
- url, is_main_script, loader_factory_, std::move(compare_reader),
+ url, is_main_script, force_bypass_cache_, update_via_cache_,
+ time_since_last_check_, loader_factory_, std::move(compare_reader),
std::move(copy_reader), std::move(writer),
base::BindOnce(&ServiceWorkerUpdateChecker::OnOneUpdateCheckFinished,
weak_factory_.GetWeakPtr(), resource_id));
diff --git a/chromium/content/browser/service_worker/service_worker_update_checker.h b/chromium/content/browser/service_worker/service_worker_update_checker.h
index 6c8c3142159..3b60357bd3a 100644
--- a/chromium/content/browser/service_worker/service_worker_update_checker.h
+++ b/chromium/content/browser/service_worker/service_worker_update_checker.h
@@ -51,7 +51,10 @@ class CONTENT_EXPORT ServiceWorkerUpdateChecker {
const GURL& main_script_url,
int64_t main_script_resource_id,
scoped_refptr<ServiceWorkerVersion> version_to_update,
- scoped_refptr<network::SharedURLLoaderFactory> loader_factory);
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
+ bool force_bypass_cache,
+ blink::mojom::ServiceWorkerUpdateViaCache update_via_cache,
+ base::TimeDelta time_since_last_check);
~ServiceWorkerUpdateChecker();
// |callback| is always triggered when Start() finishes. If the scripts are
@@ -70,6 +73,8 @@ class CONTENT_EXPORT ServiceWorkerUpdateChecker {
std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker::PausedState>
paused_state);
+ bool network_accessed() const { return network_accessed_; }
+
private:
void CheckOneScript(const GURL& url, const int64_t resource_id);
@@ -87,6 +92,14 @@ class CONTENT_EXPORT ServiceWorkerUpdateChecker {
UpdateStatusCallback callback_;
scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
+
+ const bool force_bypass_cache_;
+ const blink::mojom::ServiceWorkerUpdateViaCache update_via_cache_;
+ const base::TimeDelta time_since_last_check_;
+
+ // True if any at least one of the scripts is fetched by network.
+ bool network_accessed_ = false;
+
base::WeakPtrFactory<ServiceWorkerUpdateChecker> weak_factory_;
DISALLOW_IMPLICIT_CONSTRUCTORS(ServiceWorkerUpdateChecker);
diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc
index 18155b1ce63..132d9ef8db3 100644
--- a/chromium/content/browser/service_worker/service_worker_version.cc
+++ b/chromium/content/browser/service_worker/service_worker_version.cc
@@ -37,7 +37,6 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/common/content_client.h"
-#include "content/public/common/content_features.h"
#include "content/public/common/result_codes.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
@@ -349,8 +348,19 @@ void ServiceWorkerVersion::SetStatus(Status status) {
if (status == INSTALLED)
embedded_worker_->OnWorkerVersionInstalled();
- else if (status == REDUNDANT)
+ else if (status == REDUNDANT) {
embedded_worker_->OnWorkerVersionDoomed();
+
+ // TODO(crbug.com/951571): Remove this once we figured out the cause of
+ // invalid controller status.
+ redundant_state_callstack_ = base::debug::StackTrace();
+
+ // Tell the storage system that this worker's script resources can now be
+ // deleted.
+ std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
+ script_cache_map_.GetResources(&resources);
+ context_->storage()->PurgeResources(resources);
+ }
}
void ServiceWorkerVersion::RegisterStatusChangeCallback(
@@ -702,6 +712,9 @@ void ServiceWorkerVersion::AddControllee(
const std::string& uuid = provider_host->client_uuid();
CHECK(!provider_host->client_uuid().empty());
DCHECK(!base::ContainsKey(controllee_map_, uuid));
+ // TODO(crbug.com/951571): Change to DCHECK once we figured out the cause of
+ // invalid controller status.
+ CHECK(status_ == ACTIVATING || status_ == ACTIVATED);
controllee_map_[uuid] = provider_host;
embedded_worker_->UpdateForegroundPriority();
@@ -787,16 +800,23 @@ void ServiceWorkerVersion::Doom() {
SetStatus(REDUNDANT);
if (running_status() == EmbeddedWorkerStatus::STARTING ||
running_status() == EmbeddedWorkerStatus::RUNNING) {
- if (embedded_worker()->devtools_attached())
- stop_when_devtools_detached_ = true;
- else
+ // |start_worker_status_| == kErrorExists means that this version was
+ // created for update but the script was identical to the incumbent version.
+ // In this case we should stop the worker immediately even when DevTools is
+ // attached. Otherwise the redundant worker stays as a selectable context
+ // in DevTools' console.
+ // TODO(bashi): Remove this workaround when byte-for-byte update check is
+ // shipped.
+ bool stop_immediately =
+ base::FeatureList::IsEnabled(
+ blink::features::kOffMainThreadServiceWorkerScriptFetch) &&
+ start_worker_status_ == blink::ServiceWorkerStatusCode::kErrorExists;
+ if (stop_immediately || !embedded_worker()->devtools_attached()) {
embedded_worker_->Stop();
+ } else {
+ stop_when_devtools_detached_ = true;
+ }
}
- if (!context_)
- return;
- std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
- script_cache_map_.GetResources(&resources);
- context_->storage()->PurgeResources(resources);
}
void ServiceWorkerVersion::SetToPauseAfterDownload(base::OnceClosure callback) {
@@ -1508,7 +1528,7 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
// registration. To handle the case, check the live registrations here.
protect = context_->GetLiveRegistration(registration_id_);
if (protect) {
- DCHECK(protect->is_deleted());
+ DCHECK(protect->is_uninstalling());
status = blink::ServiceWorkerStatusCode::kOk;
}
}
@@ -2105,8 +2125,6 @@ ServiceWorkerVersion::TakePausedStateOfChangedScript(const GURL& script_url) {
bool ServiceWorkerVersion::ShouldRequireForegroundPriority(
int worker_process_id) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!base::FeatureList::IsEnabled(features::kServiceWorkerForegroundPriority))
- return false;
// Currently FetchEvents are the only type of event we need to really process
// at foreground priority. If the service worker does not have a FetchEvent
diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h
index eb0c076103a..63b14a4ccb6 100644
--- a/chromium/content/browser/service_worker/service_worker_version.h
+++ b/chromium/content/browser/service_worker/service_worker_version.h
@@ -17,6 +17,7 @@
#include "base/callback.h"
#include "base/containers/id_map.h"
+#include "base/debug/stack_trace.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -515,6 +516,11 @@ class CONTENT_EXPORT ServiceWorkerVersion
// whether the service worker should be kept at foreground priority.
void UpdateForegroundPriority();
+ // TODO(crbug.com/951571): Remove once the bug is debugged.
+ const base::debug::StackTrace& redundant_state_callstack() const {
+ return redundant_state_callstack_;
+ }
+
private:
friend class base::RefCounted<ServiceWorkerVersion>;
friend class EmbeddedWorkerInstanceTest;
@@ -965,6 +971,10 @@ class CONTENT_EXPORT ServiceWorkerVersion
// InitializeGlobalScope() is called.
blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host_;
+ // TODO(crbug.com/951571): Remove once the bug is debugged.
+ // This is set when this service worker becomes redundant.
+ base::debug::StackTrace redundant_state_callstack_;
+
base::WeakPtrFactory<ServiceWorkerVersion> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersion);
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 cc10f39e3cc..dd70b9703b5 100644
--- a/chromium/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
@@ -18,6 +18,7 @@
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/time.h"
+#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/fake_embedded_worker_instance_client.h"
@@ -27,7 +28,6 @@
#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"
-#include "content/public/common/content_features.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_service.mojom.h"
@@ -397,13 +397,13 @@ TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop run_loop;
helper_->context()->storage()->DeleteRegistration(
- registration_->id(), registration_->scope().GetOrigin(),
+ registration_, registration_->scope().GetOrigin(),
ReceiveServiceWorkerStatus(&status, run_loop.QuitClosure()));
run_loop.Run();
ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
- // The live registration is marked as deleted, but still exists.
- ASSERT_TRUE(registration_->is_deleted());
+ // The live registration is marked as uninstalling, but still exists.
+ ASSERT_TRUE(registration_->is_uninstalling());
{
// Stop the worker.
@@ -1191,9 +1191,6 @@ TEST_F(ServiceWorkerVersionTest, BadOrigin) {
TEST_F(ServiceWorkerVersionTest,
ForegroundServiceWorkerCountUpdatedByControllee) {
- base::test::ScopedFeatureList scoped_list;
- scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority);
-
// Start the worker before we have a controllee.
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop run_loop;
@@ -1229,9 +1226,6 @@ TEST_F(ServiceWorkerVersionTest,
TEST_F(ServiceWorkerVersionTest,
ForegroundServiceWorkerCountNotUpdatedBySameProcessControllee) {
- base::test::ScopedFeatureList scoped_list;
- scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority);
-
// Start the worker before we have a controllee.
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop run_loop;
@@ -1257,9 +1251,6 @@ TEST_F(ServiceWorkerVersionTest,
TEST_F(ServiceWorkerVersionTest,
ForegroundServiceWorkerCountUpdatedByControlleeProcessIdChange) {
- base::test::ScopedFeatureList scoped_list;
- scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority);
-
// Start the worker before we have a controllee.
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop run_loop;
@@ -1282,7 +1273,7 @@ TEST_F(ServiceWorkerVersionTest,
base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true /* is_parent_frame_secure */,
- base::NullCallback(), &provider_info);
+ FrameTreeNode::kFrameTreeNodeInvalidId, &provider_info);
remote_endpoint.BindForWindow(std::move(provider_info));
host->UpdateUrls(registration_->scope(), registration_->scope());
host->SetControllerRegistration(registration_,
@@ -1311,9 +1302,6 @@ TEST_F(ServiceWorkerVersionTest,
TEST_F(ServiceWorkerVersionTest,
ForegroundServiceWorkerCountUpdatedByWorkerStatus) {
- base::test::ScopedFeatureList scoped_list;
- scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority);
-
// Add a controllee in a different process from the service worker.
auto remote_endpoint = ActivateWithControllee();
@@ -1356,9 +1344,6 @@ class ServiceWorkerVersionNoFetchHandlerTest : public ServiceWorkerVersionTest {
TEST_F(ServiceWorkerVersionNoFetchHandlerTest,
ForegroundServiceWorkerCountNotUpdated) {
- base::test::ScopedFeatureList scoped_list;
- scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority);
-
// Start the worker before we have a controllee.
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop run_loop;
diff --git a/chromium/content/browser/site_instance_impl.cc b/chromium/content/browser/site_instance_impl.cc
index 3e288465ccf..f7cffe3b5bc 100644
--- a/chromium/content/browser/site_instance_impl.cc
+++ b/chromium/content/browser/site_instance_impl.cc
@@ -8,6 +8,7 @@
#include "base/command_line.h"
#include "base/debug/crash_logging.h"
+#include "base/lazy_instance.h"
#include "base/macros.h"
#include "content/browser/browsing_instance.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -32,6 +33,17 @@ namespace content {
int32_t SiteInstanceImpl::next_site_instance_id_ = 1;
+// static
+const GURL& SiteInstanceImpl::GetDefaultSiteURL() {
+ struct DefaultSiteURL {
+ const GURL url = GURL("http://unisolated.invalid");
+ };
+ static base::LazyInstance<DefaultSiteURL>::Leaky default_site_url =
+ LAZY_INSTANCE_INITIALIZER;
+
+ return default_site_url.Get().url;
+}
+
SiteInstanceImpl::SiteInstanceImpl(BrowsingInstance* browsing_instance)
: id_(next_site_instance_id_++),
active_frame_count_(0),
@@ -83,10 +95,56 @@ scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForURL(
}
// static
+scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForServiceWorker(
+ BrowserContext* browser_context,
+ const GURL& url,
+ bool can_reuse_process) {
+ // This will create a new SiteInstance and BrowsingInstance.
+ scoped_refptr<BrowsingInstance> instance(
+ new BrowsingInstance(browser_context));
+
+ // We do NOT want to allow the default site instance here because workers
+ // need to be kept separate from other sites.
+ scoped_refptr<SiteInstanceImpl> site_instance =
+ instance->GetSiteInstanceForURL(url, /* allow_default_instance */ false);
+ site_instance->is_for_service_worker_ = true;
+
+ // Attempt to reuse a renderer process if possible. Note that in the
+ // <webview> case, process reuse isn't currently supported and a new
+ // process will always be created (https://crbug.com/752667).
+ DCHECK(site_instance->process_reuse_policy() ==
+ SiteInstanceImpl::ProcessReusePolicy::DEFAULT ||
+ site_instance->process_reuse_policy() ==
+ SiteInstanceImpl::ProcessReusePolicy::PROCESS_PER_SITE);
+ if (can_reuse_process) {
+ site_instance->set_process_reuse_policy(
+ SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ }
+ return site_instance;
+}
+
+// static
+scoped_refptr<SiteInstanceImpl>
+SiteInstanceImpl::CreateReusableInstanceForTesting(
+ BrowserContext* browser_context,
+ const GURL& url) {
+ DCHECK(browser_context);
+ // This will create a new SiteInstance and BrowsingInstance.
+ scoped_refptr<BrowsingInstance> instance(
+ new BrowsingInstance(browser_context));
+ auto site_instance =
+ instance->GetSiteInstanceForURL(url,
+ /* allow_default_instance */ false);
+ site_instance->set_process_reuse_policy(
+ SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ return site_instance;
+}
+
+// static
bool SiteInstanceImpl::ShouldAssignSiteForURL(const GURL& url) {
// about:blank should not "use up" a new SiteInstance. The SiteInstance can
// still be used for a normal web site.
- if (url == url::kAboutBlankURL)
+ if (url.IsAboutBlank())
return false;
// The embedder will then have the opportunity to determine if the URL
@@ -103,6 +161,15 @@ int32_t SiteInstanceImpl::GetId() {
return id_;
}
+int32_t SiteInstanceImpl::GetBrowsingInstanceId() {
+ // This is being vended out as an opaque ID, and it is always defined for
+ // a BrowsingInstance affiliated IsolationContext, so it's safe to call
+ // "GetUnsafeValue" and expose the inner value directly.
+ return browsing_instance_->isolation_context()
+ .browsing_instance_id()
+ .GetUnsafeValue();
+}
+
const IsolationContext& SiteInstanceImpl::GetIsolationContext() {
return browsing_instance_->isolation_context();
}
@@ -263,7 +330,7 @@ void SiteInstanceImpl::SetSite(const GURL& url) {
}
}
-const GURL& SiteInstanceImpl::GetSiteURL() const {
+const GURL& SiteInstanceImpl::GetSiteURL() {
return site_;
}
@@ -338,7 +405,7 @@ bool SiteInstanceImpl::HasWrongProcessForURL(const GURL& url) {
// destination site_url require dedicated processes, then it is safe to use
// this SiteInstance.
if (!RequiresDedicatedProcess() &&
- !DoesSiteRequireDedicatedProcess(GetIsolationContext(), site_url)) {
+ !DoesSiteURLRequireDedicatedProcess(GetIsolationContext(), site_url)) {
return false;
}
@@ -357,7 +424,7 @@ bool SiteInstanceImpl::RequiresDedicatedProcess() {
if (!has_site_)
return false;
- return DoesSiteRequireDedicatedProcess(GetIsolationContext(), site_);
+ return DoesSiteURLRequireDedicatedProcess(GetIsolationContext(), site_);
}
void SiteInstanceImpl::IncrementActiveFrameCount() {
@@ -387,7 +454,7 @@ void SiteInstanceImpl::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
-BrowserContext* SiteInstanceImpl::GetBrowserContext() const {
+BrowserContext* SiteInstanceImpl::GetBrowserContext() {
return browsing_instance_->GetBrowserContext();
}
@@ -412,11 +479,35 @@ bool SiteInstance::ShouldAssignSiteForURL(const GURL& url) {
}
bool SiteInstanceImpl::IsSameSiteWithURL(const GURL& url) {
+ if (IsDefaultSiteInstance()) {
+ // Consider |url| the same site if it could be handled by the
+ // default SiteInstance and we don't already have a SiteInstance for
+ // this URL.
+ // TODO(acolwell): Remove HasSiteInstance() call once we have a way to
+ // prevent SiteInstances with no site URL from being used for URLs
+ // that should be routed to the default SiteInstance.
+ DCHECK_EQ(site_, GetDefaultSiteURL());
+ return site_ == GetSiteForURLInternal(GetIsolationContext(), url,
+ true /* should_use_effective_urls */,
+ true /* allow_default_site_url */) &&
+ !browsing_instance_->HasSiteInstance(url);
+ }
+
return SiteInstanceImpl::IsSameWebSite(
GetIsolationContext(), site_, url,
true /* should_compare_effective_urls */);
}
+bool SiteInstanceImpl::IsOriginalUrlSameSite(
+ const GURL& dest_url,
+ bool should_compare_effective_urls) {
+ if (IsDefaultSiteInstance())
+ return IsSameSiteWithURL(dest_url);
+
+ return IsSameWebSite(GetIsolationContext(), original_url_, dest_url,
+ should_compare_effective_urls);
+}
+
// static
bool SiteInstanceImpl::IsSameWebSite(const IsolationContext& isolation_context,
const GURL& real_src_url,
@@ -426,6 +517,7 @@ bool SiteInstanceImpl::IsSameWebSite(const IsolationContext& isolation_context,
BrowserContext* browser_context =
isolation_context.browser_or_resource_context().ToBrowserContext();
DCHECK(browser_context);
+ DCHECK_NE(real_src_url, GetDefaultSiteURL());
GURL src_url =
should_compare_effective_urls
@@ -453,8 +545,7 @@ bool SiteInstanceImpl::IsSameWebSite(const IsolationContext& isolation_context,
// If the destination url is just a blank page, we treat them as part of the
// same site.
- GURL blank_page(url::kAboutBlankURL);
- if (dest_url == blank_page)
+ if (dest_url.IsAboutBlank())
return true;
// If the source and destination URLs are equal excluding the hash, they have
@@ -470,6 +561,9 @@ bool SiteInstanceImpl::IsSameWebSite(const IsolationContext& isolation_context,
if (src_origin.scheme() != dest_origin.scheme())
return false;
+ if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled())
+ return src_origin == dest_origin;
+
if (!net::registry_controlled_domains::SameDomainOrHost(
src_origin, dest_origin,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
@@ -505,8 +599,8 @@ GURL SiteInstance::GetSiteForURL(BrowserContext* browser_context,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(browser_context);
- // By default, GetSiteForURL will resolve |real_url| to an effective URL
- // before computing its site, so set |should_use_effective_urls| to true.
+ // By default, GetSiteForURL will resolve |url| to an effective URL
+ // before computing its site.
//
// TODO(alexmos): Callers inside content/ should already be using the
// internal SiteInstanceImpl version and providing a proper IsolationContext.
@@ -514,9 +608,8 @@ GURL SiteInstance::GetSiteForURL(BrowserContext* browser_context,
// where needed. Eventually, GetSiteForURL should always require an
// IsolationContext to be passed in, and this implementation should just
// become SiteInstanceImpl::GetSiteForURL.
- return SiteInstanceImpl::GetSiteForURL(
- IsolationContext(browser_context), url,
- true /* should_use_effective_urls */);
+ return SiteInstanceImpl::GetSiteForURL(IsolationContext(browser_context),
+ url);
}
// static
@@ -525,14 +618,25 @@ GURL SiteInstanceImpl::DetermineProcessLockURL(
const GURL& url) {
// For the process lock URL, convert |url| to a site without resolving |url|
// to an effective URL.
- return SiteInstanceImpl::GetSiteForURL(isolation_context, url,
- false /* should_use_effective_urls */);
+ return SiteInstanceImpl::GetSiteForURLInternal(
+ isolation_context, url, false /* should_use_effective_urls */,
+ false /* allow_default_site_url */);
}
// static
GURL SiteInstanceImpl::GetSiteForURL(const IsolationContext& isolation_context,
- const GURL& real_url,
- bool should_use_effective_urls) {
+ const GURL& real_url) {
+ return GetSiteForURLInternal(isolation_context, real_url,
+ true /* should_use_effective_urls */,
+ false /* allow_default_site_url */);
+}
+
+// static
+GURL SiteInstanceImpl::GetSiteForURLInternal(
+ const IsolationContext& isolation_context,
+ const GURL& real_url,
+ bool should_use_effective_urls,
+ bool allow_default_site_url) {
// TODO(fsamuel, creis): For some reason appID is not recognized as a host.
if (real_url.SchemeIs(kGuestScheme))
return real_url;
@@ -551,8 +655,18 @@ GURL SiteInstanceImpl::GetSiteForURL(const IsolationContext& isolation_context,
// If the url has a host, then determine the site. Skip file URLs to avoid a
// situation where site URL of file://localhost/ would mismatch Blink's origin
// (which ignores the hostname in this case - see https://crbug.com/776160).
+ GURL site_url;
if (!origin.host().empty() && origin.scheme() != url::kFileScheme) {
- GURL site_url(GetSiteForOrigin(origin));
+ // For Strict Origin Isolation, use the full origin instead of site for all
+ // HTTP/HTTPS URLs. Note that the HTTP/HTTPS restriction guarantees that
+ // we won't hit this for hosted app effective URLs, which would otherwise
+ // need to append a non-translated site URL to the hash below (see
+ // https://crbug.com/961386).
+ if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled() &&
+ origin.GetURL().SchemeIsHTTPOrHTTPS())
+ return origin.GetURL();
+
+ site_url = GetSiteForOrigin(origin);
// Isolated origins should use the full origin as their site URL. A
// subdomain of an isolated origin should also use that isolated origin's
@@ -574,63 +688,71 @@ GURL SiteInstanceImpl::GetSiteForURL(const IsolationContext& isolation_context,
// a proper security principal.
if (should_use_effective_urls && url != real_url) {
std::string non_translated_site_url(
- GetSiteForURL(isolation_context, real_url,
- false /* should_use_effective_urls */)
+ GetSiteForURLInternal(isolation_context, real_url,
+ false /* should_use_effective_urls */,
+ allow_default_site_url)
.spec());
GURL::Replacements replacements;
replacements.SetRefStr(non_translated_site_url.c_str());
site_url = site_url.ReplaceComponents(replacements);
}
-
- return site_url;
- }
-
- // If there is no host but there is a scheme, return the scheme.
- // This is useful for cases like file URLs.
- if (!origin.opaque()) {
- // Prefer to use the scheme of |origin| rather than |url|, to correctly
- // 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);
+ } else {
+ // If there is no host but there is a scheme, return the scheme.
+ // This is useful for cases like file URLs.
+ if (!origin.opaque()) {
+ // Prefer to use the scheme of |origin| rather than |url|, to correctly
+ // cover blob:file: and filesystem:file: URIs (see also
+ // https://crbug.com/697111).
+ DCHECK(!origin.scheme().empty());
+ site_url = 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);
+ }
+ site_url = url;
+ } else {
+ DCHECK(!url.scheme().empty());
+ site_url = GURL(url.scheme() + ":");
}
- return url;
+ } else {
+ // Otherwise the URL should be invalid; return an empty site.
+ DCHECK(!url.is_valid()) << url;
+ return GURL();
}
-
- DCHECK(!url.scheme().empty());
- return GURL(url.scheme() + ":");
}
- // Otherwise the URL should be invalid; return an empty site.
- DCHECK(!url.is_valid()) << url;
- return GURL();
+ if (allow_default_site_url &&
+ !base::FeatureList::IsEnabled(
+ features::kProcessSharingWithStrictSiteInstances) &&
+ SiteInstanceImpl::ShouldAssignSiteForURL(url) &&
+ !DoesSiteURLRequireDedicatedProcess(isolation_context, site_url)) {
+ return GetDefaultSiteURL();
+ }
+ return site_url;
}
// static
@@ -662,6 +784,16 @@ bool SiteInstanceImpl::HasEffectiveURL(BrowserContext* browser_context,
bool SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
const IsolationContext& isolation_context,
const GURL& url) {
+ return SiteIsolationPolicy::UseDedicatedProcessesForAllSites() ||
+ DoesSiteURLRequireDedicatedProcess(
+ isolation_context,
+ SiteInstanceImpl::GetSiteForURL(isolation_context, url));
+}
+
+// static
+bool SiteInstanceImpl::DoesSiteURLRequireDedicatedProcess(
+ const IsolationContext& isolation_context,
+ const GURL& site_url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(isolation_context.browser_or_resource_context());
@@ -671,8 +803,6 @@ bool SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
return true;
// Always require a dedicated process for isolated origins.
- GURL site_url = SiteInstanceImpl::GetSiteForURL(
- isolation_context, url, true /* should_compare_effective_urls */);
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
if (policy->IsIsolatedOrigin(isolation_context,
url::Origin::Create(site_url)))
@@ -714,7 +844,7 @@ bool SiteInstanceImpl::ShouldLockToOrigin(
if (RenderProcessHost::run_renderer_in_process())
return false;
- if (!DoesSiteRequireDedicatedProcess(isolation_context, site_url))
+ if (!DoesSiteURLRequireDedicatedProcess(isolation_context, site_url))
return false;
// Guest processes cannot be locked to their site because guests always have
diff --git a/chromium/content/browser/site_instance_impl.h b/chromium/content/browser/site_instance_impl.h
index a55149d3e45..a46901055bd 100644
--- a/chromium/content/browser/site_instance_impl.h
+++ b/chromium/content/browser/site_instance_impl.h
@@ -40,6 +40,19 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
static scoped_refptr<SiteInstanceImpl> CreateForURL(
BrowserContext* browser_context,
const GURL& url);
+ static scoped_refptr<SiteInstanceImpl> CreateForServiceWorker(
+ BrowserContext* browser_context,
+ const GURL& url,
+ bool can_reuse_process = false);
+
+ // Creates a SiteInstance for |url| like CreateForURL() would except the
+ // instance that is returned has its process_reuse_policy set to
+ // REUSE_PENDING_OR_COMMITTED_SITE and the default SiteInstance will never
+ // be returned.
+ static scoped_refptr<SiteInstanceImpl> CreateReusableInstanceForTesting(
+ BrowserContext* browser_context,
+ const GURL& url);
+
static bool ShouldAssignSiteForURL(const GURL& url);
// Returns whether |lock_url| is at least at the granularity of a site (i.e.,
@@ -64,10 +77,11 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// SiteInstance interface overrides.
int32_t GetId() override;
+ int32_t GetBrowsingInstanceId() override;
bool HasProcess() override;
RenderProcessHost* GetProcess() override;
- BrowserContext* GetBrowserContext() const override;
- const GURL& GetSiteURL() const override;
+ BrowserContext* GetBrowserContext() override;
+ const GURL& GetSiteURL() override;
scoped_refptr<SiteInstance> GetRelatedSiteInstance(const GURL& url) override;
bool IsRelatedSiteInstance(const SiteInstance* instance) override;
size_t GetRelatedActiveContentsCount() override;
@@ -103,6 +117,7 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
};
void set_process_reuse_policy(ProcessReusePolicy policy) {
+ DCHECK(!IsDefaultSiteInstance());
process_reuse_policy_ = policy;
}
ProcessReusePolicy process_reuse_policy() const {
@@ -114,12 +129,20 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// chosen existing process is reused because of the process limit, the process
// will be tracked as having an unmatched service worker until reused by
// another SiteInstance from the same site.
- void set_is_for_service_worker() { is_for_service_worker_ = true; }
bool is_for_service_worker() const { return is_for_service_worker_; }
// Returns the URL which was used to set the |site_| for this SiteInstance.
// May be empty if this SiteInstance does not have a |site_|.
- const GURL& original_url() { return original_url_; }
+ const GURL& original_url() {
+ DCHECK(!IsDefaultSiteInstance());
+ return original_url_;
+ }
+
+ // Returns true if |original_url()| is the same site as
+ // |dest_url| or this object is a default SiteInstance and can be
+ // considered the same site as |dest_url|.
+ bool IsOriginalUrlSameSite(const GURL& dest_url,
+ bool should_compare_effective_urls);
// Returns the URL which should be used in a LockToOrigin call for this
// SiteInstance's process. This is the same as |site_| except for cases
@@ -142,12 +165,10 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// Returns the site for the given URL, which includes only the scheme and
// registered domain. Returns an empty GURL if the URL has no host.
- // |should_use_effective_urls| defaults to true and specifies whether to
- // resolve |url| to an effective URL (via
+ // |url| will be resolved to an effective URL (via
// ContentBrowserClient::GetEffectiveURL()) before determining the site.
static GURL GetSiteForURL(const IsolationContext& isolation_context,
- const GURL& url,
- bool should_use_effective_urls = true);
+ const GURL& url);
// Returns the site of a given |origin|. Unlike GetSiteForURL(), this does
// not utilize effective URLs, isolated origins, or other special logic. It
@@ -220,6 +241,9 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// - SiteInstanceImpl::CanAssociateWithSpareProcess().
void PreventAssociationWithSpareProcess();
+ // Returns the special site URL used by the default SiteInstance.
+ static const GURL& GetDefaultSiteURL();
+
// Get the effective URL for the given actual URL. This allows the
// ContentBrowserClient to override the SiteInstance's site for certain URLs.
// For example, Chrome uses this to replace hosted app URLs with extension
@@ -288,6 +312,7 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
private:
friend class BrowsingInstance;
friend class SiteInstanceTestBrowserClient;
+ FRIEND_TEST_ALL_PREFIXES(SiteInstanceTest, ProcessLockDoesNotUseEffectiveURL);
// Create a new SiteInstance. Only BrowsingInstance should call this
// directly; clients should use Create() or GetRelatedSiteInstance() instead.
@@ -310,6 +335,28 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// a dedicated process.
void MaybeSetBrowsingInstanceDefaultProcess();
+ // Returns the site for the given URL, which includes only the scheme and
+ // registered domain. Returns an empty GURL if the URL has no host.
+ // |should_use_effective_urls| specifies whether to resolve |url| to an
+ // effective URL (via ContentBrowserClient::GetEffectiveURL()) before
+ // determining the site.
+ // |allow_default_site_url| specifies whether the default SiteInstance site
+ // URL is allowed to be returned.
+ static GURL GetSiteForURLInternal(const IsolationContext& isolation_context,
+ const GURL& url,
+ bool should_use_effective_urls,
+ bool allow_default_site_url);
+
+ // Returns true if pages loaded from |site_url| ought to be handled only by a
+ // renderer process isolated from other sites. If --site-per-process is used,
+ // this is true for all sites. In other site isolation modes, only a subset
+ // of sites will require dedicated processes.
+ // Note: Unlike DoesSiteRequireDedicatedProcess(), this method expects a site
+ // URL instead of a plain URL.
+ static bool DoesSiteURLRequireDedicatedProcess(
+ const IsolationContext& isolation_context,
+ const GURL& site_url);
+
// An object used to construct RenderProcessHosts.
static const RenderProcessHostFactory* g_render_process_host_factory_;
diff --git a/chromium/content/browser/site_instance_impl_unittest.cc b/chromium/content/browser/site_instance_impl_unittest.cc
index 0d036807928..03fb996c51e 100644
--- a/chromium/content/browser/site_instance_impl_unittest.cc
+++ b/chromium/content/browser/site_instance_impl_unittest.cc
@@ -48,10 +48,6 @@
namespace content {
namespace {
-GURL GetWebUIURL(std::string host) {
- return GURL(std::string(kChromeUIScheme) + "://" + host);
-}
-
bool IsSameWebSite(BrowserContext* context,
const GURL& url1,
const GURL& url2) {
@@ -481,12 +477,14 @@ TEST_F(SiteInstanceTest, ProcessLockDoesNotUseEffectiveURL) {
// URL's site (app.com) and the original URL's site (foo.com).
GURL expected_app_site_url(app_url.spec() + "#" + nonapp_site_url.spec());
{
- GURL site_url = SiteInstanceImpl::GetSiteForURL(
- isolation_context, test_url, false /* use_effective_urls */);
+ GURL site_url = SiteInstanceImpl::GetSiteForURLInternal(
+ isolation_context, test_url, false /* use_effective_urls */,
+ false /* allow_default_site_url */);
EXPECT_EQ(nonapp_site_url, site_url);
- site_url = SiteInstanceImpl::GetSiteForURL(isolation_context, test_url,
- true /* use_effective_urls */);
+ site_url = SiteInstanceImpl::GetSiteForURLInternal(
+ isolation_context, test_url, true /* use_effective_urls */,
+ false /* allow_default_site_url */);
EXPECT_EQ(expected_app_site_url, site_url);
}
@@ -776,10 +774,10 @@ TEST_F(SiteInstanceTest, HasWrongProcessForURL) {
EXPECT_FALSE(instance->HasWrongProcessForURL(
GURL("javascript:alert(document.location.href);")));
- EXPECT_TRUE(instance->HasWrongProcessForURL(GURL("chrome://gpu")));
+ EXPECT_TRUE(instance->HasWrongProcessForURL(GetWebUIURL(kChromeUIGpuHost)));
// Test that WebUI SiteInstances reject normal web URLs.
- const GURL webui_url("chrome://gpu");
+ const GURL webui_url(GetWebUIURL(kChromeUIGpuHost));
scoped_refptr<SiteInstanceImpl> webui_instance(
SiteInstanceImpl::Create(browser_context.get()));
webui_instance->SetSite(webui_url);
@@ -834,7 +832,7 @@ TEST_F(SiteInstanceTest, HasWrongProcessForURLInSitePerProcess) {
EXPECT_FALSE(instance->HasWrongProcessForURL(
GURL("javascript:alert(document.location.href);")));
- EXPECT_TRUE(instance->HasWrongProcessForURL(GURL("chrome://gpu")));
+ EXPECT_TRUE(instance->HasWrongProcessForURL(GetWebUIURL(kChromeUIGpuHost)));
DrainMessageLoop();
}
@@ -853,7 +851,7 @@ TEST_F(SiteInstanceTest, ProcessPerSiteWithWrongBindings) {
// Simulate navigating to a WebUI URL in a process that does not have WebUI
// bindings. This already requires bypassing security checks.
- const GURL webui_url("chrome://gpu");
+ const GURL webui_url(GetWebUIURL(kChromeUIGpuHost));
instance->SetSite(webui_url);
EXPECT_TRUE(instance->HasSite());
@@ -943,6 +941,74 @@ TEST_F(SiteInstanceTest, IsSameWebsiteForNestedURLs) {
EXPECT_FALSE(IsSameWebSite(&context, https_bar_url, fs_bar_url));
}
+TEST_F(SiteInstanceTest, StrictOriginIsolation) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kStrictOriginIsolation);
+ EXPECT_TRUE(base::FeatureList::IsEnabled(features::kStrictOriginIsolation));
+
+ GURL isolated1_foo_url("http://isolated1.foo.com");
+ GURL isolated2_foo_url("http://isolated2.foo.com");
+ TestBrowserContext browser_context;
+ IsolationContext isolation_context(&browser_context);
+
+ EXPECT_FALSE(IsSameWebSite(context(), isolated1_foo_url, isolated2_foo_url));
+ EXPECT_NE(
+ SiteInstanceImpl::GetSiteForURL(isolation_context, isolated1_foo_url),
+ SiteInstanceImpl::GetSiteForURL(isolation_context, isolated2_foo_url));
+
+ // A bunch of special cases of origins.
+ GURL secure_foo("https://foo.com");
+ EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(isolation_context, secure_foo),
+ secure_foo);
+ GURL foo_with_port("http://foo.com:1234");
+ EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(isolation_context, foo_with_port),
+ foo_with_port);
+ GURL local_host("http://localhost");
+ EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(isolation_context, local_host),
+ local_host);
+ GURL ip_local_host("http://127.0.0.1");
+ EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(isolation_context, ip_local_host),
+ ip_local_host);
+
+ // The following should not get origin-specific SiteInstances, as they don't
+ // have valid hosts.
+ GURL about_url("about:flags");
+ EXPECT_NE(SiteInstanceImpl::GetSiteForURL(isolation_context, about_url),
+ about_url);
+
+ GURL file_url("file:///home/user/foo");
+ EXPECT_NE(SiteInstanceImpl::GetSiteForURL(isolation_context, file_url),
+ file_url);
+}
+
+// Ensure that the site URL for a URL that resolves to a non-HTTP/HTTPS
+// effective site URL won't break with strict origin isolation. The effective
+// site URL should still contain the non-translated site URL in its hash. See
+// https://crbug.com/961386.
+TEST_F(SiteInstanceTest, StrictOriginIsolationWithEffectiveURLs) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kStrictOriginIsolation);
+ EXPECT_TRUE(base::FeatureList::IsEnabled(features::kStrictOriginIsolation));
+
+ const GURL kOriginalUrl("https://original.com");
+ const GURL kTranslatedUrl(GetWebUIURL("translated"));
+ EffectiveURLContentBrowserClient modified_client(kOriginalUrl,
+ kTranslatedUrl);
+ ContentBrowserClient* regular_client =
+ SetBrowserClientForTesting(&modified_client);
+
+ TestBrowserContext browser_context;
+ IsolationContext isolation_context(&browser_context);
+
+ // Ensure that original.com's effective site URL still contains the
+ // non-translated site URL in its hash.
+ GURL expected_site_url(kTranslatedUrl.spec() + "#" + kOriginalUrl.spec());
+ EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(isolation_context, kOriginalUrl),
+ expected_site_url);
+
+ SetBrowserClientForTesting(regular_client);
+}
+
TEST_F(SiteInstanceTest, IsolatedOrigins) {
GURL foo_url("http://www.foo.com");
GURL isolated_foo_url("http://isolated.foo.com");
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index eec2a9b2482..5a19ef3076d 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -167,7 +167,6 @@
#endif
#if defined(OS_CHROMEOS)
-#include "ui/aura/env.h"
#include "ui/aura/test/test_screen.h"
#endif
@@ -962,9 +961,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessHighDPIBrowserTest,
#if defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
SubframeUpdateToCorrectDeviceScaleFactor) {
- if (aura::Env::GetInstance()->mode() == aura::Env::Mode::MUS)
- return;
-
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b)"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1371,7 +1367,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
blink::WebInputEvent::GetStaticTimeStampForTests(),
blink::WebGestureDevice::kTouchscreen);
gesture_scroll_begin.data.scroll_begin.delta_hint_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0.f;
gesture_scroll_begin.data.scroll_begin.delta_y_hint = 5.f;
@@ -1383,7 +1379,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
blink::WebInputEvent::GetStaticTimeStampForTests(),
blink::WebGestureDevice::kTouchscreen);
gesture_scroll_update.data.scroll_update.delta_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
gesture_scroll_update.data.scroll_update.delta_x = 0.f;
gesture_scroll_update.data.scroll_update.delta_y = 5.f;
gesture_scroll_update.data.scroll_update.velocity_y = 5.f;
@@ -1726,7 +1722,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
blink::WebInputEvent::GetStaticTimeStampForTests());
gesture_scroll_begin.SetSourceDevice(blink::WebGestureDevice::kTouchscreen);
gesture_scroll_begin.data.scroll_begin.delta_hint_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0.f;
gesture_scroll_begin.data.scroll_begin.delta_y_hint = 5.f;
child_rwh->ForwardGestureEvent(gesture_scroll_begin);
@@ -5088,7 +5084,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigatePopupToIllegalURL) {
EXPECT_EQ(popup_url, popup->web_contents()->GetLastCommittedURL());
EXPECT_TRUE(
base::MatchPattern(console_delegate.message(),
- "Not allowed to load local resource: chrome:*"));
+ std::string("Not allowed to load local resource: ") +
+ kChromeUIScheme + ":*"));
}
// Verify that named frames are discoverable from their opener's ancestors.
@@ -13075,6 +13072,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
ChildFrameCrashMetrics_ScrolledIntoViewAfterTabIsShown) {
+ // Disable the feature to mark hidden tabs with sad frames for reload, since
+ // it makes the scenario for which this test collects metrics impossible.
+ base::test::ScopedFeatureList feature_list_;
+ feature_list_.InitAndDisableFeature(
+ features::kReloadHiddenTabsWithCrashedSubframes);
+
// Start on a page that has a single iframe, which is positioned out of
// view, and navigate that iframe cross-site.
GURL main_url(
@@ -13145,6 +13148,125 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
1);
}
+// Verify the feature where hidden tabs with crashed subframes are marked for
+// reload. This avoids showing crashed subframes if a hidden tab is eventually
+// shown. See https://crbug.com/841572.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ReloadHiddenTabWithCrashedSubframe) {
+ base::test::ScopedFeatureList feature_list_;
+ feature_list_.InitAndEnableFeature(
+ features::kReloadHiddenTabsWithCrashedSubframes);
+
+ auto crash_process = [](FrameTreeNode* ftn) {
+ RenderProcessHost* process = ftn->current_frame_host()->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ process->Shutdown(0);
+ crash_observer.Wait();
+ EXPECT_FALSE(ftn->current_frame_host()->IsRenderFrameLive());
+ };
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ // Hide the WebContents (UpdateWebContentsVisibility is called twice to avoid
+ // hitting the |!did_first_set_visible_| case).
+ web_contents()->UpdateWebContentsVisibility(Visibility::VISIBLE);
+ web_contents()->UpdateWebContentsVisibility(Visibility::HIDDEN);
+ EXPECT_EQ(Visibility::HIDDEN, web_contents()->GetVisibility());
+
+ // Kill the b.com subframe's process. This should mark the hidden
+ // WebContents for reload.
+ {
+ base::HistogramTester histograms;
+ crash_process(root->child_at(0));
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.TabMarkedForReload", true, 1);
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.TabMarkedForReload.Visibility",
+ blink::mojom::FrameVisibility::kRenderedInViewport, 1);
+
+ // Show the WebContents. This should trigger a reload of the main frame.
+ web_contents()->UpdateWebContentsVisibility(Visibility::VISIBLE);
+ EXPECT_TRUE(WaitForLoadStop(web_contents()));
+ histograms.ExpectUniqueSample(
+ "Navigation.LoadIfNecessaryType",
+ NavigationControllerImpl::NeedsReloadType::kCrashedSubframe, 1);
+ }
+
+ // Both frames should now have live renderer processes.
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+
+ // Next, try the same with a crashed subframe that's scrolled out of view.
+ // This should also trigger a reload.
+ GURL out_of_view_url(
+ embedded_test_server()->GetURL("a.com", "/iframe_out_of_view.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), out_of_view_url));
+ NavigateIframeToURL(web_contents(), "test_iframe",
+ embedded_test_server()->GetURL("b.com", "/title1.html"));
+ web_contents()->UpdateWebContentsVisibility(Visibility::HIDDEN);
+ {
+ base::HistogramTester histograms;
+ crash_process(root->child_at(0));
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.TabMarkedForReload", true, 1);
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.TabMarkedForReload.Visibility",
+ blink::mojom::FrameVisibility::kRenderedOutOfViewport, 1);
+
+ web_contents()->UpdateWebContentsVisibility(Visibility::VISIBLE);
+ EXPECT_TRUE(WaitForLoadStop(web_contents()));
+ histograms.ExpectUniqueSample(
+ "Navigation.LoadIfNecessaryType",
+ NavigationControllerImpl::NeedsReloadType::kCrashedSubframe, 1);
+ }
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+
+ // Now, load a page with where an iframe is hidden with "display:none".
+ // Ensure that we do not mark the tab for reload in that case.
+ GURL hidden_iframe_url(
+ embedded_test_server()->GetURL("a.com", "/page_with_hidden_iframe.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), hidden_iframe_url));
+ NavigateIframeToURL(web_contents(), "test_iframe",
+ embedded_test_server()->GetURL("b.com", "/title1.html"));
+ RenderFrameProxyHost* proxy_to_parent =
+ root->child_at(0)->render_manager()->GetProxyToParent();
+ EXPECT_TRUE(proxy_to_parent->cross_process_frame_connector()->IsHidden());
+
+ web_contents()->UpdateWebContentsVisibility(Visibility::HIDDEN);
+ {
+ base::HistogramTester histograms;
+ crash_process(root->child_at(0));
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.TabMarkedForReload", false, 1);
+ }
+ web_contents()->UpdateWebContentsVisibility(Visibility::VISIBLE);
+ EXPECT_TRUE(WaitForLoadStop(web_contents()));
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_FALSE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+
+ // Finally, ensure that the reload policy doesn't trigger for a visible tab,
+ // even if it becomes hidden and then visible again.
+ EXPECT_EQ(Visibility::VISIBLE, web_contents()->GetVisibility());
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ {
+ base::HistogramTester histograms;
+ crash_process(root->child_at(0));
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.TabMarkedForReload", false, 1);
+ }
+ EXPECT_EQ(Visibility::VISIBLE, web_contents()->GetVisibility());
+ web_contents()->UpdateWebContentsVisibility(Visibility::HIDDEN);
+ web_contents()->UpdateWebContentsVisibility(Visibility::VISIBLE);
+ EXPECT_TRUE(WaitForLoadStop(web_contents()));
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_FALSE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+}
+
// Check that when a frame changes a subframe's size twice and then sends a
// postMessage to the subframe, the subframe's onmessage handler sees the new
// size. In particular, ensure that the postMessage won't get reordered with
@@ -14004,6 +14126,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
std::string());
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_EQ(another_url, controller.GetPendingEntry()->GetURL());
+ NavigationRequest* navigation_request = root->navigation_request();
+ ASSERT_TRUE(navigation_request);
RenderProcessHostKillWaiter kill_waiter(
root->current_frame_host()->GetProcess());
@@ -14020,6 +14144,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
params->gesture = NavigationGestureAuto;
params->method = "GET";
params->page_state = PageState::CreateFromURL(start_url);
+ params->navigation_token =
+ root->navigation_request()->commit_params().navigation_token;
// Use an origin mismatched with the origin lock.
params->origin = url::Origin::Create(another_url);
@@ -14029,6 +14155,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ(start_url.host(), policy->GetOriginLock(process_id).host());
EXPECT_NE(another_url.host(), policy->GetOriginLock(process_id).host());
+ // Transfer the NavigationRequest ownership to the RenderFrameHost. The test
+ // for NavigationRequest match happens before the check of origin lock and
+ // needs to be successful.
+ root->TransferNavigationRequestOwnership(root->current_frame_host());
+ root->current_frame_host()->OnCrossDocumentCommitProcessed(
+ navigation_request, blink::mojom::CommitResult::Ok);
+
// Simulate a commit IPC.
service_manager::mojom::InterfaceProviderPtr interface_provider;
blink::mojom::DocumentInterfaceBrokerPtrInfo
@@ -14752,4 +14885,47 @@ INSTANTIATE_TEST_SUITE_P(
testing::Bool(),
testing::Bool()));
+// This checks what process is used when an iframe is navigated to about:blank.
+// The new document should be loaded in the process of its initiator.
+//
+// Test case:
+// 1. Navigate to A1(B2).
+// 2. B2 navigates itself to B3 = about:blank. Process B is used.
+// 3. A1 makes B3 to navigate to A4 = about:blank. Process A is used.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ SameAndCrossProcessIframeAboutBlankNavigation) {
+ // 1. Navigate to A1(B2).
+ GURL a1_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), a1_url));
+ RenderFrameHostImpl* a1_rfh = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* b2_rfh = a1_rfh->child_at(0)->current_frame_host();
+
+ // 2. B2 navigates itself to B3 = about:blank. Process B is used.
+ {
+ scoped_refptr<SiteInstance> b2_site_instance = b2_rfh->GetSiteInstance();
+ TestNavigationManager navigation_manager(web_contents(),
+ GURL("about:blank"));
+ EXPECT_TRUE(ExecJs(b2_rfh, "location.href = 'about:blank';"));
+ navigation_manager.WaitForNavigationFinished();
+
+ RenderFrameHostImpl* b3_rfh = a1_rfh->child_at(0)->current_frame_host();
+ DCHECK_EQ(b3_rfh->GetSiteInstance(), b2_site_instance);
+ DCHECK_NE(a1_rfh->GetProcess(), b3_rfh->GetProcess());
+ }
+
+ // 3. A1 makes B3 to navigate to A4 = about:blank. Process A is used.
+ {
+ TestNavigationManager navigation_manager(web_contents(),
+ GURL("about:blank"));
+ EXPECT_TRUE(ExecJs(a1_rfh, R"(
+ document.querySelector("iframe").src = "about:blank";
+ )"));
+ navigation_manager.WaitForNavigationFinished();
+
+ RenderFrameHostImpl* b4_rfh = a1_rfh->child_at(0)->current_frame_host();
+ DCHECK_EQ(a1_rfh->GetSiteInstance(), b4_rfh->GetSiteInstance());
+ }
+}
+
} // 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 ba3897f01c9..95f9ad25e17 100644
--- a/chromium/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/chromium/content/browser/site_per_process_hit_test_browsertest.cc
@@ -44,7 +44,6 @@
#include "content/public/test/test_utils.h"
#include "content/shell/common/shell_switches.h"
#include "content/test/mock_overscroll_observer.h"
-#include "ui/base/ui_base_features.h"
#include "ui/display/display_switches.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
@@ -927,8 +926,9 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessInternalsHitTestBrowserTest,
EXPECT_NE(div_scroll_top_start, div_scroll_top);
}
+// TODO(https://crbug.com/961135): disabled because tests are flaky
IN_PROC_BROWSER_TEST_P(SitePerProcessInternalsHitTestBrowserTest,
- NestedLocalNonFastScrollableDivCoordsAreLocal) {
+ DISABLED_NestedLocalNonFastScrollableDivCoordsAreLocal) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b)"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1191,8 +1191,16 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// release in (15, 10) same as the touch move in root frame. Before the fix the
// touch end would pass (15, 10) to subframe which should be (15, 15) in
// subframe.
+// https://crbug.com/959848: Flaky on Linux MSAN bots
+#if defined(OS_LINUX)
+#define MAYBE_TouchAndGestureEventPositionChange \
+ DISABLED_TouchAndGestureEventPositionChange
+#else
+#define MAYBE_TouchAndGestureEventPositionChange \
+ TouchAndGestureEventPositionChange
+#endif
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- TouchAndGestureEventPositionChange) {
+ MAYBE_TouchAndGestureEventPositionChange) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_tall_positioned_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1339,7 +1347,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
blink::WebGestureDevice::kTouchscreen);
gesture_scroll_begin.unique_touch_event_id = 2;
gesture_scroll_begin.data.scroll_begin.delta_hint_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0.f;
gesture_scroll_begin.data.scroll_begin.delta_y_hint = -5.f * scale_factor;
gesture_scroll_begin.SetPositionInWidget(touch_start_point);
@@ -1351,7 +1359,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
blink::WebGestureDevice::kTouchscreen);
gesture_scroll_update.unique_touch_event_id = 2;
gesture_scroll_update.data.scroll_update.delta_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
gesture_scroll_update.data.scroll_update.delta_x = 0.f;
gesture_scroll_update.data.scroll_update.delta_y = -5.f * scale_factor;
gesture_scroll_update.SetPositionInWidget(touch_start_point);
@@ -1409,7 +1417,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
blink::WebGestureDevice::kTouchscreen);
gesture_scroll_end.unique_touch_event_id = 3;
gesture_scroll_end.data.scroll_end.delta_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
gesture_scroll_end.SetPositionInWidget(touch_move_point);
InputEventAckWaiter await_scroll_end_in_child(
@@ -1804,14 +1812,6 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
rwhv_nested->GetRenderWidgetHost());
synchronize_threads.Wait();
-#if defined(USE_AURA)
- // Allow the scroll gesture through under mash.
- base::Optional<SystemEventRewriter::ScopedAllow> maybe_scoped_allow_events;
- if (features::IsSingleProcessMash()) {
- maybe_scoped_allow_events.emplace(&event_rewriter_);
- }
-#endif
-
SyntheticSmoothScrollGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
const gfx::PointF location_in_widget(25, 25);
@@ -2238,8 +2238,8 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
blink::WebInputEvent::kGestureScrollEnd);
#if defined(USE_AURA)
- const float overscroll_threshold = OverscrollConfig::GetThreshold(
- OverscrollConfig::Threshold::kStartTouchscreen);
+ const float overscroll_threshold =
+ OverscrollConfig::kStartTouchscreenThresholdDips;
#elif defined(OS_ANDROID)
const float overscroll_threshold = 0.f;
#endif
@@ -2253,7 +2253,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
blink::WebGestureDevice::kTouchscreen);
gesture_scroll_begin.unique_touch_event_id = 1;
gesture_scroll_begin.data.scroll_begin.delta_hint_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0.f;
gesture_scroll_begin.data.scroll_begin.delta_y_hint = 0.f;
#if defined(USE_AURA)
@@ -2278,7 +2278,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
blink::WebGestureDevice::kTouchscreen);
gesture_scroll_update.unique_touch_event_id = 1;
gesture_scroll_update.data.scroll_update.delta_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
gesture_scroll_update.data.scroll_update.delta_x = 0.f;
gesture_scroll_update.data.scroll_update.delta_y = 0.f;
#if defined(USE_AURA)
@@ -2319,7 +2319,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
blink::WebGestureDevice::kTouchscreen);
gesture_scroll_end.unique_touch_event_id = 1;
gesture_scroll_end.data.scroll_end.delta_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
mock_overscroll_observer->Reset();
router->RouteGestureEvent(rwhv_root, &gesture_scroll_end,
ui::LatencyInfo(ui::SourceEventType::TOUCH));
@@ -6216,25 +6216,7 @@ class SitePerProcessHitTestDataGenerationBrowserTest
device_scale_factor_ = rwhv_root->GetDeviceScaleFactor();
DCHECK_GT(device_scale_factor_, 0);
- auto hit_test_data = observer.GetHitTestData();
- MaybeStripHitTestData(&hit_test_data);
- return hit_test_data;
- }
-
- // Strip the ClientRoot frame sink id from |hit_test_data| when Window
- // Service is used because tests are written without considering it and
- // using a constant number index to access the data of the interested frame.
- // Related to http://crbug.com/895029.
- // Note the stripped data has wrong child count and should only be used to
- // verify test expectations.
- void MaybeStripHitTestData(
- std::vector<viz::AggregatedHitTestRegion>* hit_test_data) {
- if (!features::IsUsingWindowService())
- return;
-
- // There must be at least two frame sink ids: one root and one ClientRoot.
- ASSERT_GE(hit_test_data->size(), 2u);
- hit_test_data->erase(hit_test_data->begin() + 1);
+ return observer.GetHitTestData();
}
float current_device_scale_factor() const { return device_scale_factor_; }
@@ -6657,9 +6639,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestDataGenerationBrowserTest,
HitTestRegionObserver observer(rwhv_root->GetRootFrameSinkId());
observer.WaitForHitTestData();
hit_test_data = observer.GetHitTestData();
- MaybeStripHitTestData(&hit_test_data);
-
- DCHECK(hit_test_data.size() == 4);
+ ASSERT_EQ(4u, hit_test_data.size());
EXPECT_EQ(expected_region.ToString(), hit_test_data[2].rect.ToString());
EXPECT_TRUE(
expected_transform.ApproximatelyEqual(hit_test_data[2].transform()));
@@ -6706,6 +6686,9 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestDataGenerationBrowserTest,
EXPECT_EQ(kSlowHitTestFlags, hit_test_data[2].flags);
}
+// All tests are flaky on MSAN. https://crbug.com/959924
+#if !defined(MEMORY_SANITIZER)
+
static const int kHitTestOption[] = {0, 1, 2};
static const float kOneScale[] = {1.f};
@@ -6749,6 +6732,7 @@ INSTANTIATE_TEST_SUITE_P(/* no prefix */,
SitePerProcessGestureHitTestBrowserTest,
testing::Combine(testing::ValuesIn(kHitTestOption),
testing::ValuesIn(kOneScale)));
-#endif
+#endif // defined(USE_AURA)
+#endif // defined(MEMORY_SANITIZER)
} // namespace content
diff --git a/chromium/content/browser/site_per_process_unload_browsertest.cc b/chromium/content/browser/site_per_process_unload_browsertest.cc
index 3aade57b990..faa0669f5fb 100644
--- a/chromium/content/browser/site_per_process_unload_browsertest.cc
+++ b/chromium/content/browser/site_per_process_unload_browsertest.cc
@@ -1016,4 +1016,500 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
}
}
+// Regression test for https://crbug.com/960006.
+//
+// 1. Navigate to a1(a2(b3),c4),
+// 2. b3 has a slow unload handler.
+// 3. a2 navigates same process.
+// 4. When the new document is loaded, a message is sent to c4 to check it
+// cannot see b3 anymore, even if b3 is still unloading.
+IN_PROC_BROWSER_TEST_F(
+ SitePerProcessBrowserTest,
+ IsDetachedSubframeObservableDuringUnloadHandlerSameProcess) {
+ GURL page_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a(b),c)"));
+ EXPECT_TRUE(NavigateToURL(shell(), page_url));
+ RenderFrameHostImpl* node1 =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root()
+ ->current_frame_host();
+ RenderFrameHostImpl* node2 = node1->child_at(0)->current_frame_host();
+ RenderFrameHostImpl* node3 = node2->child_at(0)->current_frame_host();
+ RenderFrameHostImpl* node4 = node1->child_at(1)->current_frame_host();
+ ASSERT_TRUE(ExecJs(node1, "window.name = 'node1'"));
+ ASSERT_TRUE(ExecJs(node2, "window.name = 'node2'"));
+ ASSERT_TRUE(ExecJs(node3, "window.name = 'node3'"));
+ ASSERT_TRUE(ExecJs(node4, "window.name = 'node4'"));
+
+ // Test sanity check.
+ EXPECT_EQ(true, EvalJs(node1, "!!top.node2.node3"));
+ EXPECT_EQ(true, EvalJs(node2, "!!top.node2.node3"));
+ EXPECT_EQ(true, EvalJs(node3, "!!top.node2.node3"));
+ EXPECT_EQ(true, EvalJs(node4, "!!top.node2.node3"));
+
+ // Simulate a long-running unload handler in |node3|.
+ auto detach_filter = base::MakeRefCounted<DropMessageFilter>(
+ FrameMsgStart, FrameHostMsg_Detach::ID);
+ node3->GetProcess()->AddFilter(detach_filter.get());
+ node2->DisableSwapOutTimerForTesting();
+ ASSERT_TRUE(ExecJs(node3, "window.onunload = ()=>{}"));
+
+ // Prepare |node4| to respond to postMessage with a report of whether it can
+ // still find |node3|.
+ const char* kPostMessageHandlerScript = R"(
+ window.postMessageGotData == false;
+ window.postMessageCallback = function() {};
+ function receiveMessage(event) {
+ console.log('node4 - receiveMessage...');
+
+ var can_node3_be_found = false;
+ try {
+ can_node3_be_found = !!top.node2.node3;
+ } catch(e) {
+ can_node3_be_found = false;
+ }
+
+ window.postMessageGotData = true;
+ window.postMessageData = can_node3_be_found;
+ window.postMessageCallback(window.postMessageData);
+ }
+ window.addEventListener("message", receiveMessage, false);
+ )";
+ ASSERT_TRUE(ExecJs(node4, kPostMessageHandlerScript));
+
+ // Make |node1| navigate |node2| same process and after the navigation
+ // succeeds, send a post message to |node4|. We expect that the effects of the
+ // commit should be visible to |node4| by the time it receives the posted
+ // message.
+ const char* kNavigationScript = R"(
+ var node2_frame = document.getElementsByTagName('iframe')[0];
+ node2_frame.onload = function() {
+ console.log('node2_frame.onload ...');
+ node4.postMessage('try to find node3', '*');
+ };
+ node2_frame.src = $1;
+ )";
+ GURL url = embedded_test_server()->GetURL("a.com", "/title1.html");
+ ASSERT_TRUE(ExecJs(node1, JsReplace(kNavigationScript, url)));
+
+ // Check if |node4| has seen |node3| even after |node2| navigation finished
+ // (no other frame should see |node3| after the navigation of its parent).
+ const char* kPostMessageResultsScript = R"(
+ new Promise(function (resolve, reject) {
+ if (window.postMessageGotData)
+ resolve(window.postMessageData);
+ else
+ window.postMessageCallback = resolve;
+ });
+ )";
+ EXPECT_EQ(false, EvalJs(node4, kPostMessageResultsScript));
+}
+
+// Regression test for https://crbug.com/960006.
+//
+// 1. Navigate to a1(a2(b3),c4),
+// 2. b3 has a slow unload handler.
+// 3. a2 navigates cross process.
+// 4. When the new document is loaded, a message is sent to c4 to check it
+// cannot see b3 anymore, even if b3 is still unloading.
+//
+// Note: This test is the same as the above, except it uses a cross-process
+// navigation at step 3.
+IN_PROC_BROWSER_TEST_F(
+ SitePerProcessBrowserTest,
+ IsDetachedSubframeObservableDuringUnloadHandlerCrossProcess) {
+ GURL page_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a(b),c)"));
+ EXPECT_TRUE(NavigateToURL(shell(), page_url));
+ RenderFrameHostImpl* node1 =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root()
+ ->current_frame_host();
+ RenderFrameHostImpl* node2 = node1->child_at(0)->current_frame_host();
+ RenderFrameHostImpl* node3 = node2->child_at(0)->current_frame_host();
+ RenderFrameHostImpl* node4 = node1->child_at(1)->current_frame_host();
+ ASSERT_TRUE(ExecJs(node1, "window.name = 'node1'"));
+ ASSERT_TRUE(ExecJs(node2, "window.name = 'node2'"));
+ ASSERT_TRUE(ExecJs(node3, "window.name = 'node3'"));
+ ASSERT_TRUE(ExecJs(node4, "window.name = 'node4'"));
+
+ // Test sanity check.
+ EXPECT_EQ(true, EvalJs(node1, "!!top.node2.node3"));
+ EXPECT_EQ(true, EvalJs(node2, "!!top.node2.node3"));
+ EXPECT_EQ(true, EvalJs(node3, "!!top.node2.node3"));
+ EXPECT_EQ(true, EvalJs(node4, "!!top.node2.node3"));
+
+ // Add a long-running unload handler to |node3|.
+ auto detach_filter = base::MakeRefCounted<DropMessageFilter>(
+ FrameMsgStart, FrameHostMsg_Detach::ID);
+ node3->GetProcess()->AddFilter(detach_filter.get());
+ node2->DisableSwapOutTimerForTesting();
+ ASSERT_TRUE(ExecJs(node3, "window.onunload = ()=>{}"));
+
+ // Prepare |node4| to respond to postMessage with a report of whether it can
+ // still find |node3|.
+ const char* kPostMessageHandlerScript = R"(
+ window.postMessageGotData == false;
+ window.postMessageCallback = function() {};
+ function receiveMessage(event) {
+ console.log('node4 - receiveMessage...');
+
+ var can_node3_be_found = false;
+ try {
+ can_node3_be_found = !!top.node2.node3;
+ } catch(e) {
+ can_node3_be_found = false;
+ }
+
+ window.postMessageGotData = true;
+ window.postMessageData = can_node3_be_found;
+ window.postMessageCallback(window.postMessageData);
+ }
+ window.addEventListener("message", receiveMessage, false);
+ )";
+ ASSERT_TRUE(ExecJs(node4, kPostMessageHandlerScript));
+
+ // Make |node1| navigate |node2| cross process and after the navigation
+ // succeeds, send a post message to |node4|. We expect that the effects of the
+ // commit should be visible to |node4| by the time it receives the posted
+ // message.
+ const char* kNavigationScript = R"(
+ var node2_frame = document.getElementsByTagName('iframe')[0];
+ node2_frame.onload = function() {
+ console.log('node2_frame.onload ...');
+ node4.postMessage('try to find node3', '*');
+ };
+ node2_frame.src = $1;
+ )";
+ GURL url = embedded_test_server()->GetURL("d.com", "/title1.html");
+ ASSERT_TRUE(ExecJs(node1, JsReplace(kNavigationScript, url)));
+
+ // Check if |node4| has seen |node3| even after |node2| navigation finished
+ // (no other frame should see |node3| after the navigation of its parent).
+ const char* kPostMessageResultsScript = R"(
+ new Promise(function (resolve, reject) {
+ if (window.postMessageGotData)
+ resolve(window.postMessageData);
+ else
+ window.postMessageCallback = resolve;
+ });
+ )";
+ EXPECT_EQ(false, EvalJs(node4, kPostMessageResultsScript));
+}
+
+// Regression test. https://crbug.com/963330
+// 1. Start from A1(B2,C3)
+// 2. B2 is the "focused frame", is deleted and starts unloading.
+// 3. C3 commits a new navigation before B2 has completed its unload.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, FocusedFrameUnload) {
+ // 1) Start from A1(B2,C3)
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b,c)")));
+ RenderFrameHostImpl* A1 = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* B2 = A1->child_at(0)->current_frame_host();
+ RenderFrameHostImpl* C3 = A1->child_at(1)->current_frame_host();
+ FrameTree* frame_tree = A1->frame_tree_node()->frame_tree();
+
+ // 2.1) Make B2 to be the focused frame.
+ EXPECT_EQ(A1->frame_tree_node(), frame_tree->GetFocusedFrame());
+ EXPECT_TRUE(ExecJs(A1, "document.querySelector('iframe').focus()"));
+ EXPECT_EQ(B2->frame_tree_node(), frame_tree->GetFocusedFrame());
+
+ // 2.2 Unload B2. Drop detach message to simulate a long unloading.
+ auto filter = base::MakeRefCounted<DropMessageFilter>(
+ FrameMsgStart, FrameHostMsg_Detach::ID);
+ B2->GetProcess()->AddFilter(filter.get());
+ B2->SetSubframeUnloadTimeoutForTesting(base::TimeDelta::FromSeconds(30));
+
+ EXPECT_FALSE(B2->GetSuddenTerminationDisablerState(blink::kUnloadHandler));
+ EXPECT_TRUE(ExecJs(B2, "window.onunload = ()=>{};"));
+ EXPECT_TRUE(B2->GetSuddenTerminationDisablerState(blink::kUnloadHandler));
+
+ EXPECT_TRUE(B2->is_active());
+ EXPECT_TRUE(ExecJs(A1, "document.querySelector('iframe').remove()"));
+ EXPECT_EQ(nullptr, frame_tree->GetFocusedFrame());
+ EXPECT_EQ(2u, A1->child_count());
+ EXPECT_FALSE(B2->is_active());
+
+ // 3. C3 navigates.
+ NavigateFrameToURL(C3->frame_tree_node(),
+ embedded_test_server()->GetURL("d.com", "/title1.html"));
+ EXPECT_TRUE(WaitForLoadStop(web_contents()));
+ EXPECT_EQ(2u, A1->child_count());
+}
+
+// Test the unload timeout is effective.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, UnloadTimeout) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameHostImpl* A1 = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* B2 = A1->child_at(0)->current_frame_host();
+
+ // Simulate the iframe being slow to unload by dropping the
+ // FrameHostMsg_Detach message sent from B2 to the browser.
+ EXPECT_TRUE(ExecJs(B2, "window.onunload = ()=>{};"));
+ auto detach_filter = base::MakeRefCounted<DropMessageFilter>(
+ FrameMsgStart, FrameHostMsg_Detach::ID);
+ B2->GetProcess()->AddFilter(detach_filter.get());
+
+ RenderFrameDeletedObserver delete_B2(B2);
+ EXPECT_TRUE(ExecJs(A1, "document.querySelector('iframe').remove()"));
+ delete_B2.WaitUntilDeleted();
+}
+
+// Test that an unloading child can PostMessage its cross-process parent.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ UnloadPostMessageToParentCrossProcess) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameHostImpl* A1 = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* B2 = A1->child_at(0)->current_frame_host();
+ RenderFrameDeletedObserver delete_B2(B2);
+ EXPECT_TRUE(ExecJs(B2, R"(
+ window.addEventListener("unload", function() {
+ window.parent.postMessage("B2 message", "*");
+ });
+ )"));
+ EXPECT_TRUE(ExecJs(A1, R"(
+ window.received_message = "nothing received";
+ var received = false;
+ window.addEventListener('message', function(event) {
+ received_message = event.data;
+ });
+ document.querySelector('iframe').remove();
+ )"));
+ delete_B2.WaitUntilDeleted();
+ // TODO(https://crbug.com/964950): PostMessage called from an unloading frame
+ // must work. A1 must received 'B2 message'. This is not the case here.
+ EXPECT_EQ("nothing received", EvalJs(A1, "received_message"));
+}
+
+// Test that an unloading child can PostMessage its same-process parent.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ UnloadPostMessageToParentSameProcess) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameHostImpl* A1 = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* A2 = A1->child_at(0)->current_frame_host();
+ RenderFrameDeletedObserver delete_A1(A2);
+ EXPECT_TRUE(ExecJs(A2, R"(
+ window.addEventListener("unload", function() {
+ window.parent.postMessage("A2 message", "*");
+ });
+ )"));
+ EXPECT_TRUE(ExecJs(A1, R"(
+ window.received_message = "nothing received";
+ var received = false;
+ window.addEventListener('message', function(event) {
+ received_message = event.data;
+ });
+ document.querySelector('iframe').remove();
+ )"));
+ delete_A1.WaitUntilDeleted();
+ EXPECT_EQ("A2 message", EvalJs(A1, "received_message"));
+}
+
+// Related to issue https://crbug.com/950625.
+//
+// 1. Start from A1(B1)
+// 2. Navigate A1 to A3, same-process.
+// 3. A1 requests the browser to detach B1, but this message is dropped.
+// 4. The browser must be resilient and detach B1 when A3 commits.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ SameProcessNavigationResilientToDetachDropped) {
+ GURL A1_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ GURL A3_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), A1_url));
+ RenderFrameHostImpl* A1 = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* B1 = A1->child_at(0)->current_frame_host();
+
+ auto detach_filter = base::MakeRefCounted<DropMessageFilter>(
+ FrameMsgStart, FrameHostMsg_Detach::ID);
+ A1->GetProcess()->AddFilter(detach_filter.get());
+ RenderFrameDeletedObserver delete_B1(B1);
+ shell()->LoadURL(A3_url);
+ delete_B1.WaitUntilDeleted();
+}
+
+// Unload handlers should be able to do things that might require for instance
+// the RenderFrameHostImpl to stay alive.
+// - use console.log (handled via RFHI::DidAddMessageToConsole).
+// - use history.replaceState (handled via RFHI::OnUpdateState).
+// - use document.cookie
+// - use localStorage
+//
+// Test case:
+// 1. Start on A1(B2). B2 has an unload handler.
+// 2. Go to A3.
+// 3. Go back to A4(B5).
+//
+// TODO(https://crbug.com/960976): history.replaceState is broken in OOPIFs.
+//
+// This test is similar to UnloadHandlersArePowerfulGrandChild, but with a
+// different frame hierarchy.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, UnloadHandlersArePowerful) {
+ // Navigate to a page hosting a cross-origin frame.
+ GURL url = embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ RenderFrameHostImpl* A1 = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* B2 = A1->child_at(0)->current_frame_host();
+
+ // Add an unload handler to the subframe and try in that handler to preserve
+ // state that we will try to recover later.
+ ASSERT_TRUE(ExecJs(B2, R"(
+ window.addEventListener("unload", function() {
+ // Waiting for 100ms, to give more time for browser-side things to go bad
+ // and delete RenderFrameHostImpl prematurely.
+ var start = (new Date()).getTime();
+ do {
+ curr = (new Date()).getTime();
+ } while (start + 100 > curr);
+
+ // Test that various RFHI-dependent things work fine in an unload handler.
+ stateObj = { "history_test_key": "history_test_value" }
+ history.replaceState(stateObj, 'title', window.location.href);
+ console.log('console.log() sent');
+
+ // As a sanity check, test that RFHI-independent things also work fine.
+ localStorage.localstorage_test_key = 'localstorage_test_value';
+ document.cookie = 'cookie_test_key=' + 'cookie_test_value';
+ });
+ )"));
+
+ // Navigate A1(B2) to A3.
+ {
+ // Prepare observers.
+ ConsoleObserverDelegate console(web_contents(), "console.log() sent");
+ web_contents()->SetDelegate(&console);
+ RenderFrameDeletedObserver B2_deleted(B2);
+
+ // Navigate
+ GURL away_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ ASSERT_TRUE(ExecJs(A1, JsReplace("location = $1", away_url)));
+
+ // Observers must be reached.
+ B2_deleted.WaitUntilDeleted();
+ console.Wait();
+ }
+
+ // Navigate back from A3 to A4(B5).
+ web_contents()->GetController().GoBack();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ RenderFrameHostImpl* A4 = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* B5 = A4->child_at(0)->current_frame_host();
+
+ // Verify that we can recover the data that should have been persisted by the
+ // unload handler.
+ EXPECT_EQ("localstorage_test_value",
+ EvalJs(B5, "localStorage.localstorage_test_key"));
+ EXPECT_EQ("cookie_test_key=cookie_test_value", EvalJs(B5, "document.cookie"));
+
+ // TODO(lukasza): https://crbug.com/960976: Make the verification below
+ // unconditional, once the bug is fixed.
+ if (!AreAllSitesIsolatedForTesting()) {
+ EXPECT_EQ("history_test_value",
+ EvalJs(B5, "history.state.history_test_key"));
+ }
+}
+
+// Unload handlers should be able to do things that might require for instance
+// the RenderFrameHostImpl to stay alive.
+// - use console.log (handled via RFHI::DidAddMessageToConsole).
+// - use history.replaceState (handled via RFHI::OnUpdateState).
+// - use document.cookie
+// - use localStorage
+//
+// Test case:
+// 1. Start on A1(B2(C3)). C3 has an unload handler.
+// 2. Go to A4.
+// 3. Go back to A5(B6(C7)).
+//
+// TODO(https://crbug.com/960976): history.replaceState is broken in OOPIFs.
+//
+// This test is similar to UnloadHandlersArePowerful, but with a different frame
+// hierarchy.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ UnloadHandlersArePowerfulGrandChild) {
+ // Navigate to a page hosting a cross-origin frame.
+ GURL url = embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(c))");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ RenderFrameHostImpl* A1 = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* B2 = A1->child_at(0)->current_frame_host();
+ RenderFrameHostImpl* C3 = B2->child_at(0)->current_frame_host();
+
+ // Add an unload handler to the subframe and try in that handler to preserve
+ // state that we will try to recover later.
+ ASSERT_TRUE(ExecJs(C3, R"(
+ window.addEventListener("unload", function() {
+ // Waiting for 100ms, to give more time for browser-side things to go bad
+ // and delete RenderFrameHostImpl prematurely.
+ var start = (new Date()).getTime();
+ do {
+ curr = (new Date()).getTime();
+ } while (start + 100 > curr);
+
+ // Test that various RFHI-dependent things work fine in an unload handler.
+ stateObj = { "history_test_key": "history_test_value" }
+ history.replaceState(stateObj, 'title', window.location.href);
+ console.log('console.log() sent');
+
+ // As a sanity check, test that RFHI-independent things also work fine.
+ localStorage.localstorage_test_key = 'localstorage_test_value';
+ document.cookie = 'cookie_test_key=' + 'cookie_test_value';
+ });
+ )"));
+
+ // Navigate A1(B2(C3) to A4.
+ {
+ // Prepare observers.
+ ConsoleObserverDelegate console(web_contents(), "console.log() sent");
+ web_contents()->SetDelegate(&console);
+ RenderFrameDeletedObserver B2_deleted(B2);
+ RenderFrameDeletedObserver C3_deleted(C3);
+
+ // Navigate
+ GURL away_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ ASSERT_TRUE(ExecJs(A1, JsReplace("location = $1", away_url)));
+
+ // Observers must be reached.
+ B2_deleted.WaitUntilDeleted();
+ C3_deleted.WaitUntilDeleted();
+ console.Wait();
+ }
+
+ // Navigate back from A4 to A5(B6(C7))
+ web_contents()->GetController().GoBack();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ RenderFrameHostImpl* A4 = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* B5 = A4->child_at(0)->current_frame_host();
+ RenderFrameHostImpl* C6 = B5->child_at(0)->current_frame_host();
+
+ // Verify that we can recover the data that should have been persisted by the
+ // unload handler.
+ EXPECT_EQ("localstorage_test_value",
+ EvalJs(C6, "localStorage.localstorage_test_key"));
+ EXPECT_EQ("cookie_test_key=cookie_test_value", EvalJs(C6, "document.cookie"));
+
+ // TODO(lukasza): https://crbug.com/960976: Make the verification below
+ // unconditional, once the bug is fixed.
+ if (!AreAllSitesIsolatedForTesting()) {
+ EXPECT_EQ("history_test_value",
+ EvalJs(C6, "history.state.history_test_key"));
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/sms/OWNERS b/chromium/content/browser/sms/OWNERS
new file mode 100644
index 00000000000..a5caa2edf07
--- /dev/null
+++ b/chromium/content/browser/sms/OWNERS
@@ -0,0 +1,5 @@
+jsbell@chromium.org
+reillyg@chromium.org
+
+# COMPONENT: Blink>SMS
+# TEAM: fugu-dev@chromium.org \ No newline at end of file
diff --git a/chromium/content/browser/sms/sms_browsertest.cc b/chromium/content/browser/sms/sms_browsertest.cc
new file mode 100644
index 00000000000..ab8cd4bc6a9
--- /dev/null
+++ b/chromium/content/browser/sms/sms_browsertest.cc
@@ -0,0 +1,79 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/sms/sms_provider.h"
+#include "content/browser/sms/sms_service_impl.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::NiceMock;
+
+namespace content {
+
+namespace {
+
+class MockSmsProvider : public SmsProvider {
+ public:
+ MockSmsProvider() = default;
+ ~MockSmsProvider() override = default;
+
+ MOCK_METHOD0(Retrieve, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockSmsProvider);
+};
+
+class SmsBrowserTest : public ContentBrowserTest {
+ public:
+ SmsBrowserTest() = default;
+ ~SmsBrowserTest() override = default;
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ ContentBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitchASCII("enable-blink-features", "SmsReceiver");
+ command_line->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ }
+};
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(SmsBrowserTest, Start) {
+ GURL url = GetTestUrl(nullptr, "simple_page.html");
+ NavigateToURL(shell(), url);
+
+ auto* mock = new NiceMock<MockSmsProvider>();
+
+ auto* sms_service = static_cast<SmsServiceImpl*>(
+ shell()->web_contents()->GetBrowserContext()->GetSmsService());
+ sms_service->SetSmsProviderForTest(base::WrapUnique(mock));
+
+ // Test that SMS content can be retrieved after SmsManager.start().
+ std::string script = R"(
+ (async () => {
+ let receiver = new SMSReceiver({timeout: 60});
+ await receiver.start();
+ return new Promise(function(resolve) {
+ receiver.addEventListener('change', e => {
+ resolve(receiver.sms.content);
+ })
+ });
+ }) ();
+ )";
+
+ EXPECT_CALL(*mock, Retrieve()).WillOnce(Invoke([&mock, &url]() {
+ mock->NotifyReceive(url::Origin::Create(url), "hello");
+ }));
+
+ EXPECT_EQ("hello", EvalJs(shell(), script));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/sms/sms_manager_impl.cc b/chromium/content/browser/sms/sms_manager_impl.cc
new file mode 100644
index 00000000000..d47ea1ecc50
--- /dev/null
+++ b/chromium/content/browser/sms/sms_manager_impl.cc
@@ -0,0 +1,73 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <iterator>
+#include <queue>
+#include <utility>
+
+#include "content/browser/sms/sms_manager_impl.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+
+namespace content {
+
+SmsManagerImpl::SmsManagerImpl(SmsProvider* sms_provider,
+ const url::Origin& origin)
+ : sms_provider_(sms_provider), origin_(origin) {}
+
+SmsManagerImpl::~SmsManagerImpl() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void SmsManagerImpl::GetNextMessage(base::TimeDelta timeout,
+ GetNextMessageCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ Push(std::move(callback));
+}
+
+void SmsManagerImpl::Push(GetNextMessageCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (callbacks_.empty()) {
+ sms_provider_->AddObserver(this);
+ }
+
+ callbacks_.push(std::move(callback));
+ sms_provider_->Retrieve();
+}
+
+blink::mojom::SmsManager::GetNextMessageCallback SmsManagerImpl::Pop() {
+ DCHECK(!callbacks_.empty()) << "Unexpected SMS received";
+
+ GetNextMessageCallback callback = std::move(callbacks_.front());
+ callbacks_.pop();
+
+ if (callbacks_.empty()) {
+ sms_provider_->RemoveObserver(this);
+ }
+
+ return callback;
+}
+
+bool SmsManagerImpl::OnReceive(const url::Origin& origin,
+ const std::string& sms) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (origin_ != origin) {
+ return false;
+ }
+
+ Pop().Run(
+ blink::mojom::SmsMessage::New(blink::mojom::SmsStatus::kSuccess, sms));
+
+ return true;
+}
+
+void SmsManagerImpl::OnTimeout() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ Pop().Run(blink::mojom::SmsMessage::New(blink::mojom::SmsStatus::kTimeout,
+ base::nullopt));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/sms/sms_manager_impl.h b/chromium/content/browser/sms/sms_manager_impl.h
new file mode 100644
index 00000000000..d3bafa61535
--- /dev/null
+++ b/chromium/content/browser/sms/sms_manager_impl.h
@@ -0,0 +1,54 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SMS_SMS_MANAGER_IMPL_H_
+#define CONTENT_BROWSER_SMS_SMS_MANAGER_IMPL_H_
+
+#include <memory>
+#include <queue>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/time/time.h"
+#include "content/browser/sms/sms_provider.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "third_party/blink/public/mojom/sms/sms_manager.mojom.h"
+#include "url/origin.h"
+
+namespace content {
+
+class CONTENT_EXPORT SmsManagerImpl : public blink::mojom::SmsManager,
+ public content::SmsProvider::Observer {
+ public:
+ SmsManagerImpl(SmsProvider*, const url::Origin&);
+ ~SmsManagerImpl() override;
+
+ // content::SmsProvider::Observer
+ bool OnReceive(const url::Origin&, const std::string& message) override;
+ void OnTimeout() override;
+
+ // blink::mojom::SmsManager
+ void GetNextMessage(base::TimeDelta timeout, GetNextMessageCallback) override;
+
+ private:
+ // Manages the queue of callbacks.
+ void Push(GetNextMessageCallback);
+ blink::mojom::SmsManager::GetNextMessageCallback Pop();
+
+ // |sms_provider_| is safe because all instances of SmsManagerImpl are owned
+ // by SmsServiceImpl through a StrongBindingSet.
+ SmsProvider* sms_provider_;
+ const url::Origin origin_;
+ std::queue<GetNextMessageCallback> callbacks_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+ DISALLOW_COPY_AND_ASSIGN(SmsManagerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SMS_SMS_MANAGER_IMPL_H_
diff --git a/chromium/content/browser/sms/sms_parser.cc b/chromium/content/browser/sms/sms_parser.cc
new file mode 100644
index 00000000000..4fd53702316
--- /dev/null
+++ b/chromium/content/browser/sms/sms_parser.cc
@@ -0,0 +1,38 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstring>
+#include <memory>
+#include <string>
+
+#include "content/browser/sms/sms_parser.h"
+
+#include "base/optional.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+
+constexpr base::StringPiece kToken = "From: ";
+
+// static
+base::Optional<url::Origin> SmsParser::Parse(base::StringPiece sms) {
+ size_t found = sms.rfind(kToken);
+
+ if (found == base::StringPiece::npos) {
+ return base::nullopt;
+ }
+
+ base::StringPiece url = sms.substr(found + kToken.length());
+
+ GURL gurl(url);
+
+ if (!gurl.is_valid() || !gurl.SchemeIs(url::kHttpsScheme)) {
+ return base::nullopt;
+ }
+
+ return url::Origin::Create(gurl);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/sms/sms_parser.h b/chromium/content/browser/sms/sms_parser.h
new file mode 100644
index 00000000000..f70372c18a2
--- /dev/null
+++ b/chromium/content/browser/sms/sms_parser.h
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SMS_SMS_PARSER_H_
+#define CONTENT_BROWSER_SMS_SMS_PARSER_H_
+
+#include "base/optional.h"
+#include "content/common/content_export.h"
+
+namespace url {
+class Origin;
+}
+
+namespace content {
+
+// Extracts the origin from SMS messages according to the server-side
+// convention of https://github.com/samuelgoto/sms-receiver.
+// Returns an empty result if the formatting doesn't match.
+class CONTENT_EXPORT SmsParser {
+ public:
+ static base::Optional<url::Origin> Parse(base::StringPiece sms);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SMS_SMS_PARSER_H_
diff --git a/chromium/content/browser/sms/sms_parser_unittest.cc b/chromium/content/browser/sms/sms_parser_unittest.cc
new file mode 100644
index 00000000000..015151a28a3
--- /dev/null
+++ b/chromium/content/browser/sms/sms_parser_unittest.cc
@@ -0,0 +1,106 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/sms/sms_parser.h"
+
+#include "base/optional.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+
+TEST(SmsParserTest, NoToken) {
+ ASSERT_FALSE(SmsParser::Parse("foo"));
+}
+
+TEST(SmsParserTest, WithTokenInvalidUrl) {
+ ASSERT_FALSE(SmsParser::Parse("From: foo"));
+}
+
+TEST(SmsParserTest, NoSpace) {
+ ASSERT_FALSE(SmsParser::Parse("From:https://example.com"));
+}
+
+TEST(SmsParserTest, InvalidUrl) {
+ ASSERT_FALSE(SmsParser::Parse("From: //example.com"));
+}
+
+TEST(SmsParserTest, FtpScheme) {
+ ASSERT_FALSE(SmsParser::Parse("From: ftp://example.com"));
+}
+
+TEST(SmsParserTest, HttpScheme) {
+ ASSERT_FALSE(SmsParser::Parse("From: http://example.com"));
+}
+
+TEST(SmsParserTest, Mailto) {
+ ASSERT_FALSE(SmsParser::Parse("From: mailto:goto@chromium.org"));
+}
+
+TEST(SmsParserTest, Basic) {
+ base::Optional<url::Origin> origin =
+ SmsParser::Parse("From: https://example.com");
+
+ GURL url("https://example.com");
+ ASSERT_EQ(origin, url::Origin::Create(url));
+}
+
+TEST(SmsParserTest, Realistic) {
+ base::Optional<url::Origin> origin = SmsParser::Parse(
+ "<#> Your OTP is 1234ABC.\nFrom: https://example.com?s3LhKBB0M33");
+
+ GURL url("https://example.com");
+ ASSERT_EQ(origin, url::Origin::Create(url));
+}
+
+TEST(SmsParserTest, Paths) {
+ base::Optional<url::Origin> origin =
+ SmsParser::Parse("From: https://example.com/foobar");
+
+ GURL url("https://example.com");
+ ASSERT_EQ(origin, url::Origin::Create(url));
+}
+
+TEST(SmsParserTest, Message) {
+ base::Optional<url::Origin> origin =
+ SmsParser::Parse("hello world\nFrom: https://example.com");
+
+ GURL url("https://example.com");
+ ASSERT_EQ(origin, url::Origin::Create(url));
+}
+
+TEST(SmsParserTest, Whitespace) {
+ base::Optional<url::Origin> origin =
+ SmsParser::Parse("hello world\nFrom: https://example.com ");
+
+ GURL url("https://example.com");
+ ASSERT_EQ(origin, url::Origin::Create(url));
+}
+
+TEST(SmsParserTest, Newlines) {
+ base::Optional<url::Origin> origin =
+ SmsParser::Parse("hello world\nFrom: https://example.com\n");
+
+ GURL url("https://example.com");
+ ASSERT_EQ(origin, url::Origin::Create(url));
+}
+
+TEST(SmsParserTest, TwoTokens) {
+ base::Optional<url::Origin> origin =
+ SmsParser::Parse("From: https://a.com From: https://b.com");
+
+ GURL url("https://b.com");
+ ASSERT_EQ(origin, url::Origin::Create(url));
+}
+
+TEST(SmsParserTest, AppHash) {
+ base::Optional<url::Origin> origin = SmsParser::Parse(
+ "<#> Hello World\nFrom: https://example.com?s3LhKBB0M33");
+
+ GURL url("https://example.com");
+ ASSERT_EQ(origin, url::Origin::Create(url));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/sms/sms_provider.cc b/chromium/content/browser/sms/sms_provider.cc
new file mode 100644
index 00000000000..3b95cd287ed
--- /dev/null
+++ b/chromium/content/browser/sms/sms_provider.cc
@@ -0,0 +1,65 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+
+#include "build/build_config.h"
+#include "content/browser/sms/sms_provider.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+#if defined(OS_ANDROID)
+#include "content/browser/sms/sms_provider_android.h"
+#else
+#include "content/browser/sms/sms_provider_desktop.h"
+#endif
+
+namespace content {
+
+SmsProvider::SmsProvider() = default;
+
+SmsProvider::~SmsProvider() = default;
+
+// static
+std::unique_ptr<SmsProvider> SmsProvider::Create() {
+#if defined(OS_ANDROID)
+ return std::make_unique<SmsProviderAndroid>();
+#else
+ return std::make_unique<SmsProviderDesktop>();
+#endif
+}
+
+void SmsProvider::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void SmsProvider::RemoveObserver(const Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void SmsProvider::NotifyReceive(const std::string& sms) {
+ base::Optional<url::Origin> origin = SmsParser::Parse(sms);
+ if (origin) {
+ NotifyReceive(*origin, sms);
+ }
+}
+
+void SmsProvider::NotifyReceive(const url::Origin& origin,
+ const std::string& sms) {
+ for (Observer& obs : observers_) {
+ bool handled = obs.OnReceive(origin, sms);
+ if (handled) {
+ break;
+ }
+ }
+}
+
+void SmsProvider::NotifyTimeout() {
+ observers_.begin()->OnTimeout();
+}
+
+bool SmsProvider::HasObservers() {
+ return observers_.might_have_observers();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/sms/sms_provider.h b/chromium/content/browser/sms/sms_provider.h
new file mode 100644
index 00000000000..48eebfac6bf
--- /dev/null
+++ b/chromium/content/browser/sms/sms_provider.h
@@ -0,0 +1,57 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SMS_SMS_PROVIDER_H_
+#define CONTENT_BROWSER_SMS_SMS_PROVIDER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/observer_list.h"
+#include "base/observer_list_types.h"
+#include "content/browser/sms/sms_parser.h"
+#include "content/common/content_export.h"
+
+namespace url {
+class Origin;
+}
+
+namespace content {
+
+// This class wraps the platform-specific functions and allows tests to
+// inject custom providers.
+class CONTENT_EXPORT SmsProvider {
+ public:
+ class Observer : public base::CheckedObserver {
+ public:
+ // Receive an |sms| from an origin. Return true if the message is
+ // handled, which stops its propagation to other observers.
+ virtual bool OnReceive(const url::Origin&, const std::string& sms) = 0;
+ virtual void OnTimeout() = 0;
+ };
+
+ SmsProvider();
+ virtual ~SmsProvider();
+
+ // Listen to the next incoming SMS and notify observers (exactly once) when
+ // it is received or (exclusively) when it timeouts.
+ virtual void Retrieve() = 0;
+
+ static std::unique_ptr<SmsProvider> Create();
+
+ void AddObserver(Observer*);
+ void RemoveObserver(const Observer*);
+ void NotifyReceive(const url::Origin&, const std::string& sms);
+ void NotifyReceive(const std::string& sms);
+ void NotifyTimeout();
+ bool HasObservers();
+
+ private:
+ base::ObserverList<Observer> observers_;
+ DISALLOW_COPY_AND_ASSIGN(SmsProvider);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SMS_SMS_PROVIDER_H_
diff --git a/chromium/content/browser/sms/sms_provider_android.cc b/chromium/content/browser/sms/sms_provider_android.cc
new file mode 100644
index 00000000000..29bfff8fc8d
--- /dev/null
+++ b/chromium/content/browser/sms/sms_provider_android.cc
@@ -0,0 +1,54 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/bind.h"
+#include "content/browser/sms/sms_provider_android.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+#include "jni/SmsReceiver_jni.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ScopedJavaLocalRef;
+
+namespace content {
+
+SmsProviderAndroid::SmsProviderAndroid() : SmsProvider() {
+ // This class is constructed a single time whenever the
+ // first web page uses the SMS Retriever API to wait for
+ // SMSes.
+ JNIEnv* env = AttachCurrentThread();
+ j_sms_receiver_.Reset(
+ Java_SmsReceiver_create(env, reinterpret_cast<intptr_t>(this)));
+}
+
+SmsProviderAndroid::~SmsProviderAndroid() {
+ JNIEnv* env = AttachCurrentThread();
+ Java_SmsReceiver_destroy(env, j_sms_receiver_);
+}
+
+void SmsProviderAndroid::Retrieve() {
+ JNIEnv* env = AttachCurrentThread();
+
+ Java_SmsReceiver_listen(env, j_sms_receiver_);
+}
+
+void SmsProviderAndroid::OnReceive(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jstring message) {
+ std::string sms = ConvertJavaStringToUTF8(env, message);
+ NotifyReceive(sms);
+}
+
+void SmsProviderAndroid::OnTimeout(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj) {
+ NotifyTimeout();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/sms/sms_provider_android.h b/chromium/content/browser/sms/sms_provider_android.h
new file mode 100644
index 00000000000..40dca84b2ea
--- /dev/null
+++ b/chromium/content/browser/sms/sms_provider_android.h
@@ -0,0 +1,37 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SMS_SMS_PROVIDER_ANDROID_H_
+#define CONTENT_BROWSER_SMS_SMS_PROVIDER_ANDROID_H_
+
+#include <utility>
+
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/macros.h"
+#include "content/browser/sms/sms_provider.h"
+
+namespace content {
+
+class SmsProviderAndroid : public SmsProvider {
+ public:
+ SmsProviderAndroid();
+ ~SmsProviderAndroid() override;
+
+ void Retrieve() override;
+
+ void OnReceive(JNIEnv*,
+ const base::android::JavaParamRef<jobject>&,
+ jstring message);
+ void OnTimeout(JNIEnv* env, const base::android::JavaParamRef<jobject>&);
+
+ private:
+ base::android::ScopedJavaGlobalRef<jobject> j_sms_receiver_;
+
+ DISALLOW_COPY_AND_ASSIGN(SmsProviderAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SMS_SMS_PROVIDER_ANDROID_H_ \ No newline at end of file
diff --git a/chromium/content/browser/sms/sms_provider_desktop.cc b/chromium/content/browser/sms/sms_provider_desktop.cc
new file mode 100644
index 00000000000..d1656315fbf
--- /dev/null
+++ b/chromium/content/browser/sms/sms_provider_desktop.cc
@@ -0,0 +1,14 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/sms/sms_provider_desktop.h"
+
+namespace content {
+
+void SmsProviderDesktop::Retrieve() {
+ // TODO(crbug.com/670299): implementation pending.
+ NOTIMPLEMENTED();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/sms/sms_provider_desktop.h b/chromium/content/browser/sms/sms_provider_desktop.h
new file mode 100644
index 00000000000..488b370c29e
--- /dev/null
+++ b/chromium/content/browser/sms/sms_provider_desktop.h
@@ -0,0 +1,21 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SMS_SMS_PROVIDER_DESKTOP_H_
+#define CONTENT_BROWSER_SMS_SMS_PROVIDER_DESKTOP_H_
+
+#include "content/browser/sms/sms_provider.h"
+
+namespace content {
+
+class SmsProviderDesktop : public SmsProvider {
+ public:
+ SmsProviderDesktop() = default;
+ ~SmsProviderDesktop() override = default;
+ void Retrieve() override;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SMS_SMS_PROVIDER_DESKTOP_H_
diff --git a/chromium/content/browser/sms/sms_service_impl.cc b/chromium/content/browser/sms/sms_service_impl.cc
new file mode 100644
index 00000000000..f98021b3430
--- /dev/null
+++ b/chromium/content/browser/sms/sms_service_impl.cc
@@ -0,0 +1,41 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utility>
+
+#include "content/browser/sms/sms_service_impl.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "content/browser/sms/sms_manager_impl.h"
+
+namespace content {
+
+// static
+std::unique_ptr<SmsService> SmsService::Create() {
+ return std::make_unique<SmsServiceImpl>();
+}
+
+SmsServiceImpl::SmsServiceImpl() : sms_provider_(SmsProvider::Create()) {}
+
+SmsServiceImpl::~SmsServiceImpl() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void SmsServiceImpl::Bind(blink::mojom::SmsManagerRequest request,
+ const url::Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ bindings_.AddBinding(
+ std::make_unique<SmsManagerImpl>(sms_provider_.get(), origin),
+ std::move(request));
+}
+
+void SmsServiceImpl::SetSmsProviderForTest(
+ std::unique_ptr<SmsProvider> sms_provider) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ sms_provider_ = std::move(sms_provider);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/sms/sms_service_impl.h b/chromium/content/browser/sms/sms_service_impl.h
new file mode 100644
index 00000000000..571f9edd7a4
--- /dev/null
+++ b/chromium/content/browser/sms/sms_service_impl.h
@@ -0,0 +1,53 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SMS_SMS_SERVICE_IMPL_H_
+#define CONTENT_BROWSER_SMS_SMS_SERVICE_IMPL_H_
+
+#include <map>
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "content/browser/sms/sms_manager_impl.h"
+#include "content/browser/sms/sms_provider.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/sms_service.h"
+#include "mojo/public/cpp/bindings/strong_binding_set.h"
+#include "third_party/blink/public/mojom/sms/sms_manager.mojom.h"
+
+namespace url {
+class Origin;
+}
+
+namespace content {
+
+// The SmsServiceImpl is responsible for taking the incoming mojo calls from the
+// renderer process and dispatching them to the SmsProvider platform-specific
+// implementation.
+class CONTENT_EXPORT SmsServiceImpl : public content::SmsService {
+ public:
+ SmsServiceImpl();
+ ~SmsServiceImpl() override;
+
+ // content::SmsService
+ void Bind(blink::mojom::SmsManagerRequest, const url::Origin&) override;
+
+ // Testing helpers.
+ void SetSmsProviderForTest(std::unique_ptr<SmsProvider>);
+
+ private:
+ std::unique_ptr<SmsProvider> sms_provider_;
+
+ // Registered clients.
+ mojo::StrongBindingSet<blink::mojom::SmsManager> bindings_;
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ DISALLOW_COPY_AND_ASSIGN(SmsServiceImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SMS_SMS_SERVICE_IMPL_H_
diff --git a/chromium/content/browser/sms/sms_service_impl_unittest.cc b/chromium/content/browser/sms/sms_service_impl_unittest.cc
new file mode 100644
index 00000000000..154218aa109
--- /dev/null
+++ b/chromium/content/browser/sms/sms_service_impl_unittest.cc
@@ -0,0 +1,358 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/sms/sms_service_impl.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "base/time/time.h"
+#include "content/browser/sms/sms_provider.h"
+#include "content/public/common/service_manager_connection.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_renderer_host.h"
+#include "content/public/test/test_service_manager_context.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "services/service_manager/public/cpp/bind_source_info.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/sms/sms_manager.mojom.h"
+
+using blink::mojom::SmsManagerPtr;
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::NiceMock;
+
+namespace content {
+
+namespace {
+
+class MockSmsProvider : public SmsProvider {
+ public:
+ MockSmsProvider() = default;
+ ~MockSmsProvider() override = default;
+
+ MOCK_METHOD0(Retrieve, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockSmsProvider);
+};
+
+class SmsServiceImplTest : public RenderViewHostTestHarness {
+ protected:
+ SmsServiceImplTest() {}
+
+ ~SmsServiceImplTest() override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SmsServiceImplTest);
+};
+
+} // namespace
+
+TEST_F(SmsServiceImplTest, Basic) {
+ auto impl = std::make_unique<SmsServiceImpl>();
+ auto* mock = new NiceMock<MockSmsProvider>();
+
+ impl->SetSmsProviderForTest(base::WrapUnique(mock));
+
+ blink::mojom::SmsManagerPtr service_ptr;
+ GURL url("http://google.com");
+ impl->Bind(mojo::MakeRequest(&service_ptr), url::Origin::Create(url));
+ base::RunLoop loop;
+
+ EXPECT_CALL(*mock, Retrieve()).WillOnce(Invoke([&mock, &url]() {
+ mock->NotifyReceive(url::Origin::Create(url), "hi");
+ }));
+
+ service_ptr->GetNextMessage(
+ base::TimeDelta::FromSeconds(10),
+ base::BindLambdaForTesting([&](blink::mojom::SmsMessagePtr sms) {
+ EXPECT_EQ("hi", sms->content);
+ EXPECT_EQ(blink::mojom::SmsStatus::kSuccess, sms->status);
+ loop.Quit();
+ }));
+
+ loop.Run();
+
+ ASSERT_FALSE(mock->HasObservers());
+}
+
+TEST_F(SmsServiceImplTest, ExpectTwoReceiveTwoSerially) {
+ auto impl = std::make_unique<SmsServiceImpl>();
+ auto* mock = new NiceMock<MockSmsProvider>();
+
+ impl->SetSmsProviderForTest(base::WrapUnique(mock));
+
+ GURL url("http://google.com");
+
+ EXPECT_CALL(*mock, Retrieve())
+ .WillOnce(Invoke([&mock, &url]() {
+ mock->NotifyReceive(url::Origin::Create(url), "first");
+ }))
+ .WillOnce(Invoke([&mock, &url]() {
+ mock->NotifyReceive(url::Origin::Create(url), "second");
+ }));
+
+ blink::mojom::SmsManagerPtr service_ptr;
+ impl->Bind(mojo::MakeRequest(&service_ptr), url::Origin::Create(url));
+
+ {
+ base::RunLoop loop;
+
+ service_ptr->GetNextMessage(
+ base::TimeDelta::FromSeconds(10),
+ base::BindLambdaForTesting([&](blink::mojom::SmsMessagePtr sms) {
+ EXPECT_EQ("first", sms->content);
+ EXPECT_EQ(blink::mojom::SmsStatus::kSuccess, sms->status);
+ loop.Quit();
+ }));
+
+ loop.Run();
+ }
+
+ {
+ base::RunLoop loop;
+
+ service_ptr->GetNextMessage(
+ base::TimeDelta::FromSeconds(10),
+ base::BindLambdaForTesting([&](blink::mojom::SmsMessagePtr sms) {
+ EXPECT_EQ("second", sms->content);
+ EXPECT_EQ(blink::mojom::SmsStatus::kSuccess, sms->status);
+ loop.Quit();
+ }));
+
+ loop.Run();
+ }
+}
+
+TEST_F(SmsServiceImplTest, IgnoreFromOtherOrigins) {
+ auto impl = std::make_unique<SmsServiceImpl>();
+ auto* mock = new NiceMock<MockSmsProvider>();
+
+ impl->SetSmsProviderForTest(base::WrapUnique(mock));
+
+ blink::mojom::SmsManagerPtr service_ptr;
+ GURL url("http://a.com");
+ url::Origin origin = url::Origin::Create(url);
+ impl->Bind(mojo::MakeRequest(&service_ptr), origin);
+
+ blink::mojom::SmsMessagePtr response;
+
+ base::RunLoop listen_loop, sms_loop;
+
+ EXPECT_CALL(*mock, Retrieve()).WillOnce(Invoke([&listen_loop]() {
+ listen_loop.Quit();
+ }));
+
+ service_ptr->GetNextMessage(
+ base::TimeDelta::FromSeconds(10),
+ base::BindLambdaForTesting([&](blink::mojom::SmsMessagePtr sms) {
+ response = std::move(sms);
+ sms_loop.Quit();
+ }));
+
+ listen_loop.Run();
+
+ // Delivers an SMS from an unrelated origin first and expect the manager to
+ // ignore it.
+ GURL another_url("http://b.com");
+ mock->NotifyReceive(url::Origin::Create(another_url), "wrong");
+
+ mock->NotifyReceive(origin, "right");
+
+ sms_loop.Run();
+
+ EXPECT_EQ("right", response->content);
+ EXPECT_EQ(blink::mojom::SmsStatus::kSuccess, response->status);
+}
+
+TEST_F(SmsServiceImplTest, ExpectOneReceiveTwo) {
+ auto impl = std::make_unique<SmsServiceImpl>();
+ auto* mock = new NiceMock<MockSmsProvider>();
+
+ impl->SetSmsProviderForTest(base::WrapUnique(mock));
+
+ blink::mojom::SmsManagerPtr service_ptr;
+ GURL url("http://a.com");
+ url::Origin origin = url::Origin::Create(url);
+ impl->Bind(mojo::MakeRequest(&service_ptr), origin);
+
+ blink::mojom::SmsMessagePtr response;
+
+ base::RunLoop listen_loop, sms_loop;
+
+ EXPECT_CALL(*mock, Retrieve()).WillOnce(Invoke([&listen_loop]() {
+ listen_loop.Quit();
+ }));
+
+ service_ptr->GetNextMessage(
+ base::TimeDelta::FromSeconds(10),
+ base::BindLambdaForTesting([&](blink::mojom::SmsMessagePtr sms) {
+ response = std::move(sms);
+ sms_loop.Quit();
+ }));
+
+ listen_loop.Run();
+
+ // Delivers two SMSes for the same origin, even if only one was being
+ // expected.
+ mock->NotifyReceive(origin, "first");
+ mock->NotifyReceive(origin, "second");
+
+ sms_loop.Run();
+
+ EXPECT_EQ("first", response->content);
+ EXPECT_EQ(blink::mojom::SmsStatus::kSuccess, response->status);
+}
+
+TEST_F(SmsServiceImplTest, ExpectTwoReceiveTwoConcurrently) {
+ auto impl = std::make_unique<SmsServiceImpl>();
+ auto* mock = new NiceMock<MockSmsProvider>();
+
+ impl->SetSmsProviderForTest(base::WrapUnique(mock));
+
+ blink::mojom::SmsManagerPtr service_ptr;
+ GURL url("http://a.com");
+ url::Origin origin = url::Origin::Create(url);
+ impl->Bind(mojo::MakeRequest(&service_ptr), origin);
+
+ blink::mojom::SmsMessagePtr response1;
+ blink::mojom::SmsMessagePtr response2;
+
+ base::RunLoop listen_loop, sms1_loop, sms2_loop;
+
+ // Expects two GetNextMessage() calls to be made before any of them gets
+ // an SMS to resolve them.
+ EXPECT_CALL(*mock, Retrieve())
+ .WillOnce(testing::Return())
+ .WillOnce(Invoke([&listen_loop]() { listen_loop.Quit(); }));
+
+ service_ptr->GetNextMessage(
+ base::TimeDelta::FromSeconds(10),
+ base::BindLambdaForTesting([&](blink::mojom::SmsMessagePtr sms) {
+ response1 = std::move(sms);
+ sms1_loop.Quit();
+ }));
+
+ service_ptr->GetNextMessage(
+ base::TimeDelta::FromSeconds(10),
+ base::BindLambdaForTesting([&](blink::mojom::SmsMessagePtr sms) {
+ response2 = std::move(sms);
+ sms2_loop.Quit();
+ }));
+
+ listen_loop.Run();
+
+ // Delivers the first SMS.
+
+ mock->NotifyReceive(origin, "first");
+
+ sms1_loop.Run();
+
+ EXPECT_EQ("first", response1->content);
+ EXPECT_EQ(blink::mojom::SmsStatus::kSuccess, response1->status);
+
+ // Delivers the second SMS.
+
+ mock->NotifyReceive(origin, "second");
+
+ sms2_loop.Run();
+
+ EXPECT_EQ("second", response2->content);
+ EXPECT_EQ(blink::mojom::SmsStatus::kSuccess, response2->status);
+}
+
+TEST_F(SmsServiceImplTest, Timeout) {
+ auto impl = std::make_unique<SmsServiceImpl>();
+ auto* mock = new NiceMock<MockSmsProvider>();
+
+ impl->SetSmsProviderForTest(base::WrapUnique(mock));
+
+ blink::mojom::SmsManagerPtr service_ptr;
+ GURL url("http://a.com");
+ impl->Bind(mojo::MakeRequest(&service_ptr), url::Origin::Create(url));
+
+ base::RunLoop loop;
+
+ EXPECT_CALL(*mock, Retrieve()).WillOnce(Invoke([&mock]() {
+ mock->NotifyTimeout();
+ }));
+
+ service_ptr->GetNextMessage(
+ base::TimeDelta::FromSeconds(10),
+ base::BindLambdaForTesting([&](blink::mojom::SmsMessagePtr sms) {
+ EXPECT_EQ(blink::mojom::SmsStatus::kTimeout, sms->status);
+ loop.Quit();
+ }));
+
+ loop.Run();
+}
+
+TEST_F(SmsServiceImplTest, TimeoutTwoOrigins) {
+ auto impl = std::make_unique<SmsServiceImpl>();
+ auto* mock = new NiceMock<MockSmsProvider>();
+
+ impl->SetSmsProviderForTest(base::WrapUnique(mock));
+
+ blink::mojom::SmsManagerPtr service_ptr1;
+ GURL url1("http://a.com");
+ impl->Bind(mojo::MakeRequest(&service_ptr1), url::Origin::Create(url1));
+
+ blink::mojom::SmsManagerPtr service_ptr2;
+ GURL url2("http://b.com");
+ impl->Bind(mojo::MakeRequest(&service_ptr2), url::Origin::Create(url2));
+
+ blink::mojom::SmsMessagePtr response1;
+ blink::mojom::SmsMessagePtr response2;
+
+ base::RunLoop listen, sms_loop1, sms_loop2;
+
+ EXPECT_CALL(*mock, Retrieve())
+ .WillOnce(testing::Return())
+ .WillOnce(Invoke([&listen]() { listen.Quit(); }));
+
+ service_ptr1->GetNextMessage(
+ base::TimeDelta::FromSeconds(10),
+ base::BindLambdaForTesting([&](blink::mojom::SmsMessagePtr sms) {
+ response1 = std::move(sms);
+ sms_loop1.Quit();
+ }));
+
+ service_ptr2->GetNextMessage(
+ base::TimeDelta::FromSeconds(10),
+ base::BindLambdaForTesting([&](blink::mojom::SmsMessagePtr sms) {
+ response2 = std::move(sms);
+ sms_loop2.Quit();
+ }));
+
+ listen.Run();
+
+ // Timesout the first request.
+
+ mock->NotifyTimeout();
+
+ sms_loop1.Run();
+
+ EXPECT_EQ(blink::mojom::SmsStatus::kTimeout, response1->status);
+
+ // Delivers the second SMS.
+
+ mock->NotifyReceive(url::Origin::Create(url2), "second");
+
+ sms_loop2.Run();
+
+ EXPECT_EQ("second", response2->content);
+ EXPECT_EQ(blink::mojom::SmsStatus::kSuccess, response2->status);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/speech/audio_encoder_fuzzer.cc b/chromium/content/browser/speech/audio_encoder_fuzzer.cc
new file mode 100644
index 00000000000..bd05b408290
--- /dev/null
+++ b/chromium/content/browser/speech/audio_encoder_fuzzer.cc
@@ -0,0 +1,43 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/test/fuzzed_data_provider.h"
+#include "content/browser/speech/audio_encoder.h"
+
+using content::AudioChunk;
+
+// Copied from speech_recognition_engine.cc.
+const int kDefaultConfigSampleRate = 8000;
+const int kDefaultConfigBitsPerSample = 16;
+const int kAudioSampleRate = 16000;
+const int kAudioPacketIntervalMs = 100;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ base::FuzzedDataProvider provider(data, size);
+ content::AudioEncoder encoder(kDefaultConfigSampleRate,
+ kDefaultConfigBitsPerSample);
+
+ while (provider.remaining_bytes()) {
+ std::string chunk_str =
+ provider.ConsumeRandomLengthString(provider.remaining_bytes());
+ scoped_refptr<AudioChunk> chunk =
+ new AudioChunk(reinterpret_cast<const uint8_t*>(chunk_str.data()),
+ chunk_str.size(), kDefaultConfigBitsPerSample / 8);
+ encoder.Encode(*chunk);
+ }
+
+ size_t sample_count = kAudioSampleRate * kAudioPacketIntervalMs / 1000;
+ scoped_refptr<AudioChunk> dummy_chunk = new AudioChunk(
+ sample_count * sizeof(int16_t), kDefaultConfigBitsPerSample / 8);
+ encoder.Encode(*dummy_chunk.get());
+ encoder.Flush();
+ scoped_refptr<AudioChunk> encoded_data(encoder.GetEncodedDataAndClear());
+ encoded_data->AsString();
+ encoder.GetMimeType();
+ encoder.GetBitsPerSample();
+ return 0;
+}
diff --git a/chromium/content/browser/speech/mock_tts_controller.cc b/chromium/content/browser/speech/mock_tts_controller.cc
index 2d7c0dcb0d0..7d8d632d069 100644
--- a/chromium/content/browser/speech/mock_tts_controller.cc
+++ b/chromium/content/browser/speech/mock_tts_controller.cc
@@ -62,6 +62,10 @@ class MockTtsController : public TtsController {
int QueueSize() override { return 0; }
+ void StripSSML(
+ const std::string& utterance,
+ base::OnceCallback<void(const std::string&)> callback) override {}
+
private:
friend struct base::DefaultSingletonTraits<MockTtsController>;
DISALLOW_COPY_AND_ASSIGN(MockTtsController);
diff --git a/chromium/content/browser/speech/speech_recognition_engine.cc b/chromium/content/browser/speech/speech_recognition_engine.cc
index aac4f3917c0..71473883f59 100644
--- a/chromium/content/browser/speech/speech_recognition_engine.cc
+++ b/chromium/content/browser/speech/speech_recognition_engine.cc
@@ -559,9 +559,7 @@ SpeechRecognitionEngine::ConnectBothStreams(const FSMEventArgs&) {
}
})");
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->allow_credentials = false;
downstream_request->url = downstream_url;
downstream_loader_ = std::make_unique<DownstreamLoader>(
std::move(downstream_request), downstream_traffic_annotation,
@@ -659,9 +657,7 @@ SpeechRecognitionEngine::ConnectBothStreams(const FSMEventArgs&) {
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;
+ upstream_request->allow_credentials = false;
if (use_framed_post_data_) {
upstream_request->headers.SetHeader(net::HttpRequestHeaders::kContentType,
"application/octet-stream");
diff --git a/chromium/content/browser/speech/speech_recognition_engine_unittest.cc b/chromium/content/browser/speech/speech_recognition_engine_unittest.cc
index b6479b9a470..a4062a1c580 100644
--- a/chromium/content/browser/speech/speech_recognition_engine_unittest.cc
+++ b/chromium/content/browser/speech/speech_recognition_engine_unittest.cc
@@ -563,8 +563,8 @@ void SpeechRecognitionEngineTest::ProvideMockResponseStartDownstreamIfNeeded() {
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()));
+ head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(headers));
downstream_request->client->OnReceiveResponse(head);
mojo::DataPipe data_pipe;
@@ -631,8 +631,8 @@ void SpeechRecognitionEngineTest::CloseMockDownstream(
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()));
+ head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(headers));
downstream_request->client->OnReceiveResponse(head);
// Wait for the response to be handled.
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.cc b/chromium/content/browser/speech/speech_recognizer_impl.cc
index 1801ff9f64e..35ed5f79939 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl.cc
@@ -880,9 +880,10 @@ void SpeechRecognizerImpl::CreateAudioCapturerSource() {
if (connector) {
audio_capturer_source_ = audio::CreateInputDevice(
connector->Clone(), device_id_,
- MediaInternals::GetInstance()->CreateMojoAudioLog(
- media::AudioLogFactory::AUDIO_INPUT_CONTROLLER,
- 0 /* component_id */));
+ MediaInternals::GetInstance()
+ ->CreateMojoAudioLog(media::AudioLogFactory::AUDIO_INPUT_CONTROLLER,
+ 0 /* component_id */)
+ .PassInterface());
}
}
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
index 89a1ca0db74..0c8ae645b21 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -580,7 +580,7 @@ TEST_F(SpeechRecognizerImplTest, ServerError) {
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)));
+ net::HttpUtil::AssembleRawHeaders(kHeaders));
url_loader_factory_.AddResponse(pending_request->request.url, response, "",
network::URLLoaderCompletionStatus());
diff --git a/chromium/content/browser/speech/tts_android.cc b/chromium/content/browser/speech/tts_android.cc
index 706251da62e..e88d4031906 100644
--- a/chromium/content/browser/speech/tts_android.cc
+++ b/chromium/content/browser/speech/tts_android.cc
@@ -7,6 +7,7 @@
#include <string>
#include "base/android/jni_string.h"
+#include "base/bind.h"
#include "base/memory/singleton.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/buildflags.h"
@@ -18,7 +19,8 @@ using base::android::JavaParamRef;
namespace content {
-TtsPlatformImplAndroid::TtsPlatformImplAndroid() : utterance_id_(0) {
+TtsPlatformImplAndroid::TtsPlatformImplAndroid()
+ : utterance_id_(0), weak_factory_(this) {
JNIEnv* env = AttachCurrentThread();
java_ref_.Reset(
Java_TtsPlatformImpl_create(env, reinterpret_cast<intptr_t>(this)));
@@ -33,24 +35,41 @@ bool TtsPlatformImplAndroid::PlatformImplAvailable() {
return true;
}
-bool TtsPlatformImplAndroid::Speak(
+void TtsPlatformImplAndroid::Speak(
int utterance_id,
const std::string& utterance,
const std::string& lang,
const VoiceData& voice,
- const UtteranceContinuousParameters& params) {
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished) {
+ // Parse SSML and process speech.
+ TtsController::GetInstance()->StripSSML(
+ utterance, base::BindOnce(&TtsPlatformImplAndroid::ProcessSpeech,
+ weak_factory_.GetWeakPtr(), utterance_id, lang,
+ voice, params, std::move(on_speak_finished)));
+}
+
+void TtsPlatformImplAndroid::ProcessSpeech(
+ int utterance_id,
+ const std::string& lang,
+ const VoiceData& voice,
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished,
+ const std::string& parsed_utterance) {
JNIEnv* env = AttachCurrentThread();
jboolean success = Java_TtsPlatformImpl_speak(
env, java_ref_, utterance_id,
- base::android::ConvertUTF8ToJavaString(env, utterance),
+ base::android::ConvertUTF8ToJavaString(env, parsed_utterance),
base::android::ConvertUTF8ToJavaString(env, lang), params.rate,
params.pitch, params.volume);
- if (!success)
- return false;
+ if (!success) {
+ std::move(on_speak_finished).Run(false);
+ return;
+ }
- utterance_ = utterance;
+ utterance_ = parsed_utterance;
utterance_id_ = utterance_id;
- return true;
+ std::move(on_speak_finished).Run(true);
}
bool TtsPlatformImplAndroid::StopSpeaking() {
diff --git a/chromium/content/browser/speech/tts_android.h b/chromium/content/browser/speech/tts_android.h
index da8dd04cfcf..76f38d39c7b 100644
--- a/chromium/content/browser/speech/tts_android.h
+++ b/chromium/content/browser/speech/tts_android.h
@@ -15,11 +15,12 @@ class TtsPlatformImplAndroid : public TtsPlatformImpl {
public:
// TtsPlatform overrides.
bool PlatformImplAvailable() override;
- bool Speak(int utterance_id,
+ void Speak(int utterance_id,
const std::string& utterance,
const std::string& lang,
const VoiceData& voice,
- const UtteranceContinuousParameters& params) override;
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished) override;
bool StopSpeaking() override;
void Pause() override;
void Resume() override;
@@ -52,10 +53,19 @@ class TtsPlatformImplAndroid : public TtsPlatformImpl {
TtsEventType event_type,
int char_index);
+ void ProcessSpeech(int utterance_id,
+ const std::string& lang,
+ const VoiceData& voice,
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished,
+ const std::string& parsed_utterance);
+
base::android::ScopedJavaGlobalRef<jobject> java_ref_;
int utterance_id_;
std::string utterance_;
+ base::WeakPtrFactory<TtsPlatformImplAndroid> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplAndroid);
};
diff --git a/chromium/content/browser/speech/tts_controller_impl.cc b/chromium/content/browser/speech/tts_controller_impl.cc
index 554a2129632..bf5d302bd3c 100644
--- a/chromium/content/browser/speech/tts_controller_impl.cc
+++ b/chromium/content/browser/speech/tts_controller_impl.cc
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "base/bind.h"
#include "base/containers/queue.h"
#include "base/json/json_reader.h"
#include "base/metrics/histogram_macros.h"
@@ -16,6 +17,11 @@
#include "base/values.h"
#include "build/build_config.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/service_manager_connection.h"
+#include "services/data_decoder/public/cpp/safe_xml_parser.h"
+#include "services/data_decoder/public/mojom/constants.mojom.h"
+#include "services/data_decoder/public/mojom/xml_parser.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
#include "third_party/blink/public/platform/web_speech_synthesis_constants.h"
namespace content {
@@ -326,11 +332,6 @@ void TtsControllerImpl::SpeakNow(TtsUtterance* utterance) {
if (!GetTtsControllerDelegate())
return;
- // Ensure we have all built-in voices loaded. This is a no-op if already
- // loaded.
- bool loaded_built_in =
- GetTtsPlatform()->LoadBuiltInTtsEngine(utterance->GetBrowserContext());
-
// Get all available voices and try to find a matching voice.
std::vector<VoiceData> voices;
GetVoices(utterance->GetBrowserContext(), &voices);
@@ -389,25 +390,31 @@ void TtsControllerImpl::SpeakNow(TtsUtterance* utterance) {
// during |speak|.
current_utterance_ = utterance;
GetTtsPlatform()->ClearError();
- bool success = GetTtsPlatform()->Speak(
- utterance->GetId(), utterance->GetText(), utterance->GetLang(), voice,
- utterance->GetContinuousParameters());
- if (!success)
- current_utterance_ = nullptr;
+ GetTtsPlatform()->Speak(utterance->GetId(), utterance->GetText(),
+ utterance->GetLang(), voice,
+ utterance->GetContinuousParameters(),
+ base::BindOnce(&TtsControllerImpl::OnSpeakFinished,
+ base::Unretained(this), utterance));
+ }
+}
- // If the native voice wasn't able to process this speech, see if
- // the browser has built-in TTS that isn't loaded yet.
- if (!success && loaded_built_in) {
- utterance_queue_.push(utterance);
- return;
- }
+void TtsControllerImpl::OnSpeakFinished(TtsUtterance* utterance, bool success) {
+ if (!success)
+ current_utterance_ = nullptr;
- if (!success) {
- utterance->OnTtsEvent(TTS_EVENT_ERROR, kInvalidCharIndex, kInvalidLength,
- GetTtsPlatform()->GetError());
- delete utterance;
- return;
- }
+ // If the native voice wasn't able to process this speech, see if
+ // the browser has built-in TTS that isn't loaded yet.
+ if (!success &&
+ GetTtsPlatform()->LoadBuiltInTtsEngine(utterance->GetBrowserContext())) {
+ utterance_queue_.push(utterance);
+ return;
+ }
+
+ if (!success) {
+ utterance->OnTtsEvent(TTS_EVENT_ERROR, kInvalidCharIndex, kInvalidLength,
+ GetTtsPlatform()->GetError());
+ delete utterance;
+ return;
}
}
@@ -477,4 +484,81 @@ TtsControllerDelegate* TtsControllerImpl::GetTtsControllerDelegate() {
return nullptr;
}
+void TtsControllerImpl::StripSSML(
+ const std::string& utterance,
+ base::OnceCallback<void(const std::string&)> on_ssml_parsed) {
+ // Skip parsing and return if not xml.
+ if (utterance.find("<?xml") == std::string::npos) {
+ std::move(on_ssml_parsed).Run(utterance);
+ return;
+ }
+
+ // Get ServiceManagerConnection and Connector.
+ ServiceManagerConnection* service_manager_connection =
+ ServiceManagerConnection::GetForProcess();
+ CHECK(service_manager_connection);
+ service_manager::Connector* connector =
+ service_manager_connection->GetConnector();
+ CHECK(connector);
+
+ // Parse using safe, out-of-process Xml Parser.
+ data_decoder::ParseXml(connector, utterance,
+ base::BindOnce(&TtsControllerImpl::StripSSMLHelper,
+ utterance, std::move(on_ssml_parsed)));
+}
+
+// Called when ParseXml finishes.
+// Uses parsed xml to build parsed utterance text.
+void TtsControllerImpl::StripSSMLHelper(
+ const std::string& utterance,
+ base::OnceCallback<void(const std::string&)> on_ssml_parsed,
+ std::unique_ptr<base::Value> value,
+ const base::Optional<std::string>& error_message) {
+ // Error checks.
+ // If invalid xml, return original utterance text.
+ if (!value || error_message) {
+ std::move(on_ssml_parsed).Run(utterance);
+ return;
+ }
+
+ std::string root_tag_name;
+ data_decoder::GetXmlElementTagName(*value, &root_tag_name);
+ // Root element must be <speak>.
+ if (root_tag_name.compare("speak") != 0) {
+ std::move(on_ssml_parsed).Run(utterance);
+ return;
+ }
+
+ std::string parsed_text = "";
+ // Change from unique_ptr to base::Value* so recursion will work.
+ PopulateParsedText(&parsed_text, &(*value));
+
+ // Run with parsed_text.
+ std::move(on_ssml_parsed).Run(parsed_text);
+}
+
+void TtsControllerImpl::PopulateParsedText(std::string* parsed_text,
+ const base::Value* element) {
+ DCHECK(parsed_text);
+ if (!element)
+ return;
+ // Add element's text if present.
+ // Note: We don't use data_decoder::GetXmlElementText because it gets the text
+ // of element's first child, not text of current element.
+ const base::Value* text_value = element->FindKeyOfType(
+ data_decoder::mojom::XmlParser::kTextKey, base::Value::Type::STRING);
+ if (text_value)
+ *parsed_text += text_value->GetString();
+
+ const base::Value* children = data_decoder::GetXmlElementChildren(*element);
+ if (!children || !children->is_list())
+ return;
+
+ for (size_t i = 0; i < children->GetList().size(); ++i) {
+ // We need to iterate over all children because some text elements are
+ // nested within other types of elements, such as <emphasis> tags.
+ PopulateParsedText(parsed_text, &children->GetList()[i]);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/speech/tts_controller_impl.h b/chromium/content/browser/speech/tts_controller_impl.h
index 93abbdb0f02..354dcdee040 100644
--- a/chromium/content/browser/speech/tts_controller_impl.h
+++ b/chromium/content/browser/speech/tts_controller_impl.h
@@ -63,6 +63,11 @@ class CONTENT_EXPORT TtsControllerImpl : public TtsController {
void SetTtsPlatform(TtsPlatform* tts_platform) override;
int QueueSize() override;
+ // Strips SSML so that tags are not output by speech engine.
+ void StripSSML(
+ const std::string& utterance,
+ base::OnceCallback<void(const std::string&)> callback) override;
+
protected:
TtsControllerImpl();
~TtsControllerImpl() override;
@@ -97,6 +102,18 @@ class CONTENT_EXPORT TtsControllerImpl : public TtsController {
// pulled from user prefs, and may not be the same as other platforms.
void UpdateUtteranceDefaults(TtsUtterance* utterance);
+ // Passed to Speak() as a callback.
+ void OnSpeakFinished(TtsUtterance* utterance, bool success);
+
+ // Static helper methods for StripSSML.
+ static void StripSSMLHelper(
+ const std::string& utterance,
+ base::OnceCallback<void(const std::string&)> on_ssml_parsed,
+ std::unique_ptr<base::Value> value,
+ const base::Optional<std::string>& error_message);
+ static void PopulateParsedText(std::string* parsed_text,
+ const base::Value* element);
+
TtsControllerDelegate* GetTtsControllerDelegate();
TtsControllerDelegate* delegate_;
diff --git a/chromium/content/browser/speech/tts_controller_unittest.cc b/chromium/content/browser/speech/tts_controller_unittest.cc
index b3b96e3fa3e..07ca4c8a27d 100644
--- a/chromium/content/browser/speech/tts_controller_unittest.cc
+++ b/chromium/content/browser/speech/tts_controller_unittest.cc
@@ -22,12 +22,13 @@ class MockTtsPlatformImpl : public TtsPlatform {
MockTtsPlatformImpl() {}
virtual ~MockTtsPlatformImpl() {}
bool PlatformImplAvailable() override { return true; }
- bool Speak(int utterance_id,
+ void Speak(int utterance_id,
const std::string& utterance,
const std::string& lang,
const VoiceData& voice,
- const UtteranceContinuousParameters& params) override {
- return true;
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished) override {
+ std::move(on_speak_finished).Run(true);
}
bool IsSpeaking() override { return false; }
bool StopSpeaking() override { return true; }
diff --git a/chromium/content/browser/speech/tts_linux.cc b/chromium/content/browser/speech/tts_linux.cc
index e4cfe1e1431..6f1b78311a1 100644
--- a/chromium/content/browser/speech/tts_linux.cc
+++ b/chromium/content/browser/speech/tts_linux.cc
@@ -38,11 +38,12 @@ struct SPDChromeVoice {
class TtsPlatformImplLinux : public TtsPlatformImpl {
public:
bool PlatformImplAvailable() override;
- bool Speak(int utterance_id,
+ void Speak(int utterance_id,
const std::string& utterance,
const std::string& lang,
const VoiceData& voice,
- const UtteranceContinuousParameters& params) override;
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished) override;
bool StopSpeaking() override;
void Pause() override;
void Resume() override;
@@ -73,6 +74,13 @@ class TtsPlatformImplLinux : public TtsPlatformImpl {
SPDNotificationType state,
char* index_mark);
+ void ProcessSpeech(int utterance_id,
+ const std::string& lang,
+ const VoiceData& voice,
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished,
+ const std::string& parsed_utterance);
+
static SPDNotificationType current_notification_;
base::Lock initialization_lock_;
@@ -89,13 +97,16 @@ class TtsPlatformImplLinux : public TtsPlatformImpl {
friend struct base::DefaultSingletonTraits<TtsPlatformImplLinux>;
+ base::WeakPtrFactory<TtsPlatformImplLinux> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplLinux);
};
// static
SPDNotificationType TtsPlatformImplLinux::current_notification_ = SPD_EVENT_END;
-TtsPlatformImplLinux::TtsPlatformImplLinux() : utterance_id_(0) {
+TtsPlatformImplLinux::TtsPlatformImplLinux()
+ : utterance_id_(0), weak_factory_(this) {
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
if (!command_line.HasSwitch(switches::kEnableSpeechDispatcher))
@@ -160,16 +171,33 @@ bool TtsPlatformImplLinux::PlatformImplAvailable() {
return result;
}
-bool TtsPlatformImplLinux::Speak(int utterance_id,
- const std::string& utterance,
- const std::string& lang,
- const VoiceData& voice,
- const UtteranceContinuousParameters& params) {
+void TtsPlatformImplLinux::Speak(
+ int utterance_id,
+ const std::string& utterance,
+ const std::string& lang,
+ const VoiceData& voice,
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished) {
if (!PlatformImplAvailable()) {
error_ = kNotSupportedError;
- return false;
+ std::move(on_speak_finished).Run(false);
+ return;
}
+ // Parse SSML and process speech.
+ TtsController::GetInstance()->StripSSML(
+ utterance, base::BindOnce(&TtsPlatformImplLinux::ProcessSpeech,
+ weak_factory_.GetWeakPtr(), utterance_id, lang,
+ voice, params, std::move(on_speak_finished)));
+}
+
+void TtsPlatformImplLinux::ProcessSpeech(
+ int utterance_id,
+ const std::string& lang,
+ const VoiceData& voice,
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished,
+ const std::string& parsed_utterance) {
// Speech dispatcher's speech params are around 3x at either limit.
float rate = params.rate > 3 ? 3 : params.rate;
rate = params.rate < 0.334 ? 0.334 : rate;
@@ -192,14 +220,16 @@ bool TtsPlatformImplLinux::Speak(int utterance_id,
if (!lang.empty())
libspeechd_loader_.spd_set_language(conn_, lang.c_str());
- utterance_ = utterance;
+ utterance_ = parsed_utterance;
utterance_id_ = utterance_id;
- if (libspeechd_loader_.spd_say(conn_, SPD_TEXT, utterance.c_str()) == -1) {
+ if (libspeechd_loader_.spd_say(conn_, SPD_TEXT, parsed_utterance.c_str()) ==
+ -1) {
Reset();
- return false;
+ std::move(on_speak_finished).Run(false);
+ return;
}
- return true;
+ std::move(on_speak_finished).Run(true);
}
bool TtsPlatformImplLinux::StopSpeaking() {
diff --git a/chromium/content/browser/speech/tts_mac.mm b/chromium/content/browser/speech/tts_mac.mm
index 02f87148450..a3e67680048 100644
--- a/chromium/content/browser/speech/tts_mac.mm
+++ b/chromium/content/browser/speech/tts_mac.mm
@@ -4,6 +4,7 @@
#include <string>
+#include "base/bind.h"
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
@@ -52,11 +53,12 @@ class TtsPlatformImplMac : public content::TtsPlatformImpl {
public:
bool PlatformImplAvailable() override { return true; }
- bool Speak(int utterance_id,
+ void Speak(int utterance_id,
const std::string& utterance,
const std::string& lang,
const content::VoiceData& voice,
- const content::UtteranceContinuousParameters& params) override;
+ const content::UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished) override;
bool StopSpeaking() override;
@@ -83,6 +85,13 @@ class TtsPlatformImplMac : public content::TtsPlatformImpl {
TtsPlatformImplMac();
~TtsPlatformImplMac() override;
+ void ProcessSpeech(int utterance_id,
+ const std::string& lang,
+ const content::VoiceData& voice,
+ const content::UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished,
+ const std::string& parsed_utterance);
+
base::scoped_nsobject<SingleUseSpeechSynthesizer> speech_synthesizer_;
base::scoped_nsobject<ChromeTtsDelegate> delegate_;
int utterance_id_;
@@ -92,6 +101,8 @@ class TtsPlatformImplMac : public content::TtsPlatformImpl {
friend struct base::DefaultSingletonTraits<TtsPlatformImplMac>;
+ base::WeakPtrFactory<TtsPlatformImplMac> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplMac);
};
@@ -100,20 +111,36 @@ content::TtsPlatformImpl* content::TtsPlatformImpl::GetInstance() {
return TtsPlatformImplMac::GetInstance();
}
-bool TtsPlatformImplMac::Speak(
+void TtsPlatformImplMac::Speak(
int utterance_id,
const std::string& utterance,
const std::string& lang,
const content::VoiceData& voice,
- const content::UtteranceContinuousParameters& params) {
- // TODO: convert SSML to SAPI xml. http://crbug.com/88072
- utterance_ = utterance;
+ const content::UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished) {
+ // Parse SSML and process speech.
+ content::TtsController::GetInstance()->StripSSML(
+ utterance, base::BindOnce(&TtsPlatformImplMac::ProcessSpeech,
+ weak_factory_.GetWeakPtr(), utterance_id, lang,
+ voice, params, std::move(on_speak_finished)));
+}
+
+void TtsPlatformImplMac::ProcessSpeech(
+ int utterance_id,
+ const std::string& lang,
+ const content::VoiceData& voice,
+ const content::UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished,
+ const std::string& parsed_utterance) {
+ utterance_ = parsed_utterance;
paused_ = false;
NSString* utterance_nsstring =
[NSString stringWithUTF8String:utterance_.c_str()];
- if (!utterance_nsstring)
- return false;
+ if (!utterance_nsstring) {
+ std::move(on_speak_finished).Run(false);
+ return;
+ }
// Deliberately construct a new speech synthesizer every time Speak is
// called, otherwise there's no way to know whether calls to the delegate
@@ -166,7 +193,7 @@ bool TtsPlatformImplMac::Speak(
content::TtsController* controller = content::TtsController::GetInstance();
controller->OnTtsEvent(utterance_id_, content::TTS_EVENT_START, 0, -1, "");
}
- return success;
+ std::move(on_speak_finished).Run(success);
}
bool TtsPlatformImplMac::StopSpeaking() {
@@ -272,7 +299,7 @@ void TtsPlatformImplMac::OnSpeechEvent(NSSpeechSynthesizer* sender,
last_char_index_ = char_index;
}
-TtsPlatformImplMac::TtsPlatformImplMac() {
+TtsPlatformImplMac::TtsPlatformImplMac() : weak_factory_(this) {
utterance_id_ = -1;
paused_ = false;
diff --git a/chromium/content/browser/speech/tts_platform_fuzzer.cc b/chromium/content/browser/speech/tts_platform_fuzzer.cc
index 7d5ee252576..2b4e0d6e6c7 100644
--- a/chromium/content/browser/speech/tts_platform_fuzzer.cc
+++ b/chromium/content/browser/speech/tts_platform_fuzzer.cc
@@ -4,6 +4,7 @@
#include <objbase.h>
+#include "base/bind.h"
#include "build/build_config.h"
#include "content/public/browser/tts_platform.h"
@@ -99,9 +100,10 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) {
<< " volume=" << params.volume << " utterance='" << utterance << "'";
tts->StopSpeaking();
- tts->Speak(utterance_id, utterance, lang, voice, params);
+ tts->Speak(utterance_id, utterance, lang, voice, params,
+ base::BindOnce([](bool success) {}));
return 0;
}
-} // namespace content \ No newline at end of file
+} // namespace content
diff --git a/chromium/content/browser/speech/tts_ssml_browsertest.cc b/chromium/content/browser/speech/tts_ssml_browsertest.cc
new file mode 100644
index 00000000000..48dc375168f
--- /dev/null
+++ b/chromium/content/browser/speech/tts_ssml_browsertest.cc
@@ -0,0 +1,96 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "content/browser/speech/tts_controller_impl.h"
+
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+
+namespace content {
+
+namespace {
+
+// Tts Controller implementation that does nothing.
+class MockTtsControllerImpl : public TtsControllerImpl {
+ public:
+ MockTtsControllerImpl() {}
+ ~MockTtsControllerImpl() override {}
+};
+
+class TtsSsmlBrowserTest : public ContentBrowserTest {
+ public:
+ // If no SSML is stripped, then we want input == output.
+ void RunNoStripSSMLTest(std::string input) { RunSSMLStripTest(input, input); }
+
+ void RunSSMLStripTest(std::string input, std::string expected_string) {
+ MockTtsControllerImpl* controller = new MockTtsControllerImpl();
+
+ TtsUtterance* utterance = TtsUtterance::Create(nullptr);
+ utterance->SetText(input);
+
+ base::RunLoop run_loop;
+ controller->StripSSML(
+ utterance->GetText(),
+ base::BindOnce(&TtsSsmlBrowserTest::CheckCorrect,
+ base::Unretained(this), run_loop.QuitClosure(),
+ expected_string));
+ run_loop.Run();
+
+ delete controller;
+ }
+
+ // Passed as callback to StripSSML.
+ void CheckCorrect(base::OnceClosure quit_loop_closure,
+ const std::string& expected_string,
+ const std::string& actual_string) {
+ EXPECT_EQ(expected_string, actual_string);
+ base::ScopedClosureRunner runner(std::move(quit_loop_closure));
+ }
+};
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(TtsSsmlBrowserTest, TestStripSSML) {
+ // No SSML should be stripped.
+ RunNoStripSSMLTest("");
+ RunNoStripSSMLTest("What if I told you that 5 < 4?");
+ RunNoStripSSMLTest("What if I told you that 4 > 5?");
+ RunNoStripSSMLTest("Truth is, 4 < 5! And 5 > 4!");
+ RunNoStripSSMLTest(
+ "<?xml version='1.0'?><paragraph>Hello world<speak>Invalid "
+ "ssml</speak></paragraph>");
+ RunNoStripSSMLTest(
+ "<?xml version='1.0'?><paragraph><sentence>Invalid"
+ "SSML</sentence></paragraph>");
+
+ // SSML should be stripped.
+ RunSSMLStripTest("<?xml version='1.0'?><speak>Hello world</speak>",
+ "Hello world");
+ RunSSMLStripTest(
+ "<?xml version='1.0'?>"
+ "<speak>"
+ "<voice gender='female'>Any female voice here."
+ "<voice category='child'>"
+ "A female child voice here."
+ "<paragraph xml:lang='ja'>"
+ "こんにちは"
+ "</paragraph>"
+ "</voice>"
+ "</voice>"
+ "</speak>",
+ "Any female voice here.A female child voice here.こんにちは");
+ RunSSMLStripTest(
+ "<?xml version='1.0'?>"
+ "<speak>The <emphasis>second</emphasis> word of this sentence was "
+ "emphasized.</speak>",
+ "The second word of this sentence was emphasized.");
+ RunSSMLStripTest(
+ "<?xml version='1.0'?>"
+ "<!-- Ignore this -->"
+ "<speak xml:lang='en-US'>"
+ "<paragraph>I would like to have a hamburger.</paragraph>"
+ "</speak>",
+ "I would like to have a hamburger.");
+}
+
+} // namespace content
diff --git a/chromium/content/browser/speech/tts_win.cc b/chromium/content/browser/speech/tts_win.cc
index 6a7e8fdd778..aab64503c14 100644
--- a/chromium/content/browser/speech/tts_win.cc
+++ b/chromium/content/browser/speech/tts_win.cc
@@ -8,6 +8,9 @@
#include <stdint.h>
#include <wrl/client.h>
+#include <algorithm>
+
+#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/strings/string_number_conversions.h"
@@ -33,11 +36,12 @@ class TtsPlatformImplWin : public TtsPlatformImpl {
public:
bool PlatformImplAvailable() override { return true; }
- bool Speak(int utterance_id,
+ void Speak(int utterance_id,
const std::string& utterance,
const std::string& lang,
const VoiceData& voice,
- const UtteranceContinuousParameters& params) override;
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished) override;
bool StopSpeaking() override;
@@ -62,6 +66,13 @@ class TtsPlatformImplWin : public TtsPlatformImpl {
void SetVoiceFromName(const std::string& name);
+ void ProcessSpeech(int utterance_id,
+ const std::string& lang,
+ const VoiceData& voice,
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished,
+ const std::string& parsed_utterance);
+
Microsoft::WRL::ComPtr<ISpVoice> speech_synthesizer_;
// These apply to the current utterance only.
@@ -76,6 +87,8 @@ class TtsPlatformImplWin : public TtsPlatformImpl {
friend struct base::DefaultSingletonTraits<TtsPlatformImplWin>;
+ base::WeakPtrFactory<TtsPlatformImplWin> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplWin);
};
@@ -84,16 +97,34 @@ TtsPlatformImpl* TtsPlatformImpl::GetInstance() {
return TtsPlatformImplWin::GetInstance();
}
-bool TtsPlatformImplWin::Speak(int utterance_id,
- const std::string& src_utterance,
- const std::string& lang,
- const VoiceData& voice,
- const UtteranceContinuousParameters& params) {
+void TtsPlatformImplWin::Speak(
+ int utterance_id,
+ const std::string& utterance,
+ const std::string& lang,
+ const VoiceData& voice,
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished) {
+ // Parse SSML and process speech.
+ TtsController::GetInstance()->StripSSML(
+ utterance, base::BindOnce(&TtsPlatformImplWin::ProcessSpeech,
+ weak_factory_.GetWeakPtr(), utterance_id, lang,
+ voice, params, std::move(on_speak_finished)));
+}
+
+void TtsPlatformImplWin::ProcessSpeech(
+ int utterance_id,
+ const std::string& lang,
+ const VoiceData& voice,
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished,
+ const std::string& parsed_utterance) {
std::wstring prefix;
std::wstring suffix;
- if (!speech_synthesizer_.Get())
- return false;
+ if (!speech_synthesizer_.Get()) {
+ std::move(on_speak_finished).Run(false);
+ return;
+ }
SetVoiceFromName(voice.name);
@@ -107,11 +138,16 @@ bool TtsPlatformImplWin::Speak(int utterance_id,
}
if (params.pitch >= 0.0) {
- // The TTS api allows a range of -10 to 10 for speech pitch.
- // TODO(dtseng): cleanup if we ever use any other properties that
- // require xml.
- std::wstring pitch_value = base::NumberToString16(params.pitch * 10 - 10);
- prefix = L"<pitch absmiddle=\"" + pitch_value + L"\">";
+ // The TTS api allows a range of -10 to 10 for speech pitch:
+ // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms720500(v%3Dvs.85)
+ // Note that the API requires an integer value, so be sure to cast the pitch
+ // value to an int before calling NumberToString16. TODO(dtseng): cleanup if
+ // we ever use any other properties that require xml.
+ double adjusted_pitch =
+ std::max<double>(-10, std::min<double>(params.pitch * 10 - 10, 10));
+ std::wstring adjusted_pitch_string =
+ base::NumberToString16(static_cast<int>(adjusted_pitch));
+ prefix = L"<pitch absmiddle=\"" + adjusted_pitch_string + L"\">";
suffix = L"</pitch>";
}
@@ -122,7 +158,7 @@ bool TtsPlatformImplWin::Speak(int utterance_id,
// TODO(dmazzoni): convert SSML to SAPI xml. http://crbug.com/88072
- utterance_ = base::UTF8ToWide(src_utterance);
+ utterance_ = base::UTF8ToWide(parsed_utterance);
utterance_id_ = utterance_id;
char_position_ = 0;
char_length_ = 0;
@@ -131,7 +167,7 @@ bool TtsPlatformImplWin::Speak(int utterance_id,
HRESULT result = speech_synthesizer_->Speak(merged_utterance.c_str(),
SPF_ASYNC, &stream_number_);
- return (result == S_OK);
+ std::move(on_speak_finished).Run((result == S_OK));
}
bool TtsPlatformImplWin::StopSpeaking() {
@@ -304,7 +340,8 @@ TtsPlatformImplWin::TtsPlatformImplWin()
prefix_len_(0),
stream_number_(0),
char_position_(0),
- paused_(false) {
+ paused_(false),
+ weak_factory_(this) {
::CoCreateInstance(CLSID_SpVoice, nullptr, CLSCTX_ALL,
IID_PPV_ARGS(&speech_synthesizer_));
if (speech_synthesizer_.Get()) {
diff --git a/chromium/content/browser/ssl/ssl_error_handler.cc b/chromium/content/browser/ssl/ssl_error_handler.cc
index 5fc0b3cae44..c875b71a8ff 100644
--- a/chromium/content/browser/ssl/ssl_error_handler.cc
+++ b/chromium/content/browser/ssl/ssl_error_handler.cc
@@ -44,16 +44,17 @@ void CompleteContinueRequest(
SSLErrorHandler::SSLErrorHandler(WebContents* web_contents,
const base::WeakPtr<Delegate>& delegate,
BrowserThread::ID delegate_thread,
- ResourceType resource_type,
+ bool is_main_frame_request,
const GURL& url,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal)
: delegate_(delegate),
delegate_thread_(delegate_thread),
request_url_(url),
- resource_type_(resource_type),
+ is_main_frame_request_(is_main_frame_request),
ssl_info_(ssl_info),
- cert_error_(net::MapCertStatusToNetError(ssl_info.cert_status)),
+ cert_error_(net_error),
fatal_(fatal),
web_contents_(web_contents) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chromium/content/browser/ssl/ssl_error_handler.h b/chromium/content/browser/ssl/ssl_error_handler.h
index 6cfe07c070f..d80dd09885b 100644
--- a/chromium/content/browser/ssl/ssl_error_handler.h
+++ b/chromium/content/browser/ssl/ssl_error_handler.h
@@ -13,7 +13,6 @@
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_request_id.h"
-#include "content/public/common/resource_type.h"
#include "net/ssl/ssl_info.h"
#include "url/gurl.h"
@@ -51,8 +50,9 @@ class SSLErrorHandler {
SSLErrorHandler(WebContents* web_contents,
const base::WeakPtr<Delegate>& delegate,
BrowserThread::ID delegate_thread,
- ResourceType resource_type,
+ bool is_main_frame_request,
const GURL& url,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal);
@@ -62,7 +62,7 @@ class SSLErrorHandler {
const GURL& request_url() const { return request_url_; }
- ResourceType resource_type() const { return resource_type_; }
+ bool is_main_frame_request() const { return is_main_frame_request_; }
WebContents* web_contents() const { return web_contents_; }
@@ -94,9 +94,8 @@ class SSLErrorHandler {
// The URL for the request that generated the error.
const GURL request_url_;
- // What kind of resource is associated with the request that generated
- // the error.
- const ResourceType resource_type_;
+ // Whether this request is for the main frame's html.
+ const bool is_main_frame_request_;
// The net::SSLInfo associated with the request that generated the error.
const net::SSLInfo ssl_info_;
diff --git a/chromium/content/browser/ssl/ssl_manager.cc b/chromium/content/browser/ssl/ssl_manager.cc
index 7bf4d27ff48..448a93b925d 100644
--- a/chromium/content/browser/ssl/ssl_manager.cc
+++ b/chromium/content/browser/ssl/ssl_manager.cc
@@ -108,14 +108,15 @@ void HandleSSLErrorOnUI(
const base::Callback<WebContents*(void)>& web_contents_getter,
const base::WeakPtr<SSLErrorHandler::Delegate>& delegate,
BrowserThread::ID delegate_thread,
- const ResourceType resource_type,
+ bool is_main_frame_request,
const GURL& url,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal) {
content::WebContents* web_contents = web_contents_getter.Run();
- std::unique_ptr<SSLErrorHandler> handler(
- new SSLErrorHandler(web_contents, delegate, delegate_thread,
- resource_type, url, ssl_info, fatal));
+ std::unique_ptr<SSLErrorHandler> handler(new SSLErrorHandler(
+ web_contents, delegate, delegate_thread, is_main_frame_request, url,
+ net_error, ssl_info, fatal));
if (!web_contents) {
// Requests can fail to dispatch because they don't have a WebContents. See
@@ -151,21 +152,20 @@ void LogMixedContentMetrics(MixedContentType type,
// static
void SSLManager::OnSSLCertificateError(
const base::WeakPtr<SSLErrorHandler::Delegate>& delegate,
- const ResourceType resource_type,
+ bool is_main_frame_request,
const GURL& url,
const base::Callback<WebContents*(void)>& web_contents_getter,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal) {
DCHECK(delegate.get());
- DVLOG(1) << "OnSSLCertificateError() cert_error: "
- << net::MapCertStatusToNetError(ssl_info.cert_status)
- << " resource_type: " << static_cast<int>(resource_type)
+ DVLOG(1) << "OnSSLCertificateError() cert_error: " << net_error
<< " url: " << url.spec() << " cert_status: " << std::hex
<< ssl_info.cert_status;
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
HandleSSLErrorOnUI(web_contents_getter, delegate, BrowserThread::UI,
- resource_type, url, ssl_info, fatal);
+ is_main_frame_request, url, net_error, ssl_info, fatal);
return;
}
@@ -174,7 +174,8 @@ void SSLManager::OnSSLCertificateError(
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&HandleSSLErrorOnUI, web_contents_getter, delegate,
- BrowserThread::IO, resource_type, url, ssl_info, fatal));
+ BrowserThread::IO, is_main_frame_request, url, net_error,
+ ssl_info, fatal));
}
// static
@@ -183,12 +184,13 @@ void SSLManager::OnSSLCertificateSubresourceError(
const GURL& url,
int render_process_id,
int render_frame_id,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal) {
- OnSSLCertificateError(delegate, ResourceType::kSubResource, url,
+ OnSSLCertificateError(delegate, false, url,
base::Bind(&WebContentsImpl::FromRenderFrameHostID,
render_process_id, render_frame_id),
- ssl_info, fatal);
+ net_error, ssl_info, fatal);
}
SSLManager::SSLManager(NavigationControllerImpl* controller)
@@ -391,7 +393,7 @@ void SSLManager::OnCertErrorInternal(std::unique_ptr<SSLErrorHandler> handler,
int cert_error = handler->cert_error();
const net::SSLInfo& ssl_info = handler->ssl_info();
const GURL& request_url = handler->request_url();
- ResourceType resource_type = handler->resource_type();
+ bool is_main_frame_request = handler->is_main_frame_request();
bool fatal = handler->fatal();
base::Callback<void(bool, content::CertificateRequestResultType)> callback =
@@ -406,8 +408,8 @@ void SSLManager::OnCertErrorInternal(std::unique_ptr<SSLErrorHandler> handler,
}
GetContentClient()->browser()->AllowCertificateError(
- web_contents, cert_error, ssl_info, request_url, resource_type, fatal,
- expired_previous_decision,
+ web_contents, cert_error, ssl_info, request_url, is_main_frame_request,
+ fatal, expired_previous_decision,
base::Bind(&OnAllowCertificateWithRecordDecision, true,
std::move(callback)));
}
diff --git a/chromium/content/browser/ssl/ssl_manager.h b/chromium/content/browser/ssl/ssl_manager.h
index f7d35e8633f..dff7ab2dd4e 100644
--- a/chromium/content/browser/ssl/ssl_manager.h
+++ b/chromium/content/browser/ssl/ssl_manager.h
@@ -42,15 +42,17 @@ class CONTENT_EXPORT SSLManager {
// Entry point for SSLCertificateErrors. This function begins the process
// of resolving a certificate error during an SSL connection. SSLManager
// will adjust the security UI and either call |CancelSSLRequest| or
- // |ContinueSSLRequest| of |delegate|.
+ // |ContinueSSLRequest| of |delegate|. |is_main_frame_request| is true only
+ // when the request is for a navigation in the main frame.
//
// This can be called on the UI or IO thread. It will call |delegate| on the
// same thread.
static void OnSSLCertificateError(
const base::WeakPtr<SSLErrorHandler::Delegate>& delegate,
- ResourceType resource_type,
+ bool is_main_frame_request,
const GURL& url,
const base::Callback<WebContents*(void)>& web_contents_getter,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal);
@@ -62,6 +64,7 @@ class CONTENT_EXPORT SSLManager {
const GURL& url,
int render_process_id,
int render_frame_id,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal);
diff --git a/chromium/content/browser/startup_data_impl.h b/chromium/content/browser/startup_data_impl.h
index ddc91a0f85c..b2397029eef 100644
--- a/chromium/content/browser/startup_data_impl.h
+++ b/chromium/content/browser/startup_data_impl.h
@@ -7,7 +7,9 @@
#include <memory>
+#include "base/power_monitor/power_monitor.h"
#include "content/browser/browser_process_sub_thread.h"
+#include "content/common/content_export.h"
#include "content/public/browser/startup_data.h"
namespace content {
@@ -15,12 +17,13 @@ namespace content {
class ServiceManagerContext;
// The browser implementation of StartupData.
-struct StartupDataImpl : public StartupData {
+struct CONTENT_EXPORT StartupDataImpl : public StartupData {
StartupDataImpl();
~StartupDataImpl() override;
std::unique_ptr<BrowserProcessSubThread> thread;
ServiceManagerContext* service_manager_context;
+ std::unique_ptr<base::PowerMonitor> power_monitor;
};
} // namespace content
diff --git a/chromium/content/browser/startup_helper.cc b/chromium/content/browser/startup_helper.cc
index 191db21e004..eff43f8a6a6 100644
--- a/chromium/content/browser/startup_helper.cc
+++ b/chromium/content/browser/startup_helper.cc
@@ -11,42 +11,10 @@
#include "base/task/thread_pool/thread_pool.h"
#include "build/build_config.h"
#include "content/common/thread_pool_util.h"
-#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_switches.h"
namespace content {
-namespace {
-
-std::unique_ptr<base::ThreadPool::InitParams> GetDefaultThreadPoolInitParams() {
-#if defined(OS_ANDROID)
- // Mobile config, for iOS see ios/web/app/web_main_loop.cc.
- return std::make_unique<base::ThreadPool::InitParams>(
- base::SchedulerWorkerPoolParams(
- base::RecommendedMaxNumberOfThreadsInPool(4, 8, 0.2, 0),
- base::TimeDelta::FromSeconds(30)),
- base::SchedulerWorkerPoolParams(
- base::RecommendedMaxNumberOfThreadsInPool(6, 8, 0.6, 0),
- base::TimeDelta::FromSeconds(30)));
-#else
- // Desktop config.
- return std::make_unique<base::ThreadPool::InitParams>(
- base::SchedulerWorkerPoolParams(
- base::RecommendedMaxNumberOfThreadsInPool(6, 8, 0.2, 0),
- base::TimeDelta::FromSeconds(30)),
- base::SchedulerWorkerPoolParams(
- base::RecommendedMaxNumberOfThreadsInPool(16, 32, 0.6, 0),
- base::TimeDelta::FromSeconds(30))
-#if defined(OS_WIN)
- ,
- base::ThreadPool::InitParams::SharedWorkerPoolEnvironment::COM_MTA
-#endif // defined(OS_WIN)
- );
-#endif
-}
-
-} // namespace
-
std::unique_ptr<base::FieldTrialList> SetUpFieldTrialsAndFeatureList() {
auto field_trial_list = std::make_unique<base::FieldTrialList>(nullptr);
const base::CommandLine* command_line =
@@ -69,29 +37,34 @@ std::unique_ptr<base::FieldTrialList> SetUpFieldTrialsAndFeatureList() {
return field_trial_list;
}
+// TODO(scheduler-dev): Standardize thread pool logic and remove the need for
+// specifying thread count manually.
void StartBrowserThreadPool() {
- auto thread_pool_init_params =
- GetContentClient()->browser()->GetThreadPoolInitParams();
- if (!thread_pool_init_params)
- thread_pool_init_params = GetDefaultThreadPoolInitParams();
- DCHECK(thread_pool_init_params);
+ base::ThreadPoolInstance::InitParams thread_pool_init_params = {
+#if defined(OS_ANDROID)
+ // Mobile config, for iOS see ios/web/app/web_main_loop.cc.
+ base::RecommendedMaxNumberOfThreadsInThreadGroup(6, 8, 0.6, 0)
+#else
+ // Desktop config.
+ base::RecommendedMaxNumberOfThreadsInThreadGroup(16, 32, 0.6, 0)
+#endif
+ };
+
+#if defined(OS_WIN)
+ thread_pool_init_params.common_thread_pool_environment = base::
+ ThreadPoolInstance::InitParams::CommonThreadPoolEnvironment::COM_MTA;
+#endif
// If a renderer lives in the browser process, adjust the number of
// threads in the foreground pool.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSingleProcess)) {
- const base::SchedulerWorkerPoolParams&
- current_foreground_worker_pool_params(
- thread_pool_init_params->foreground_worker_pool_params);
- thread_pool_init_params->foreground_worker_pool_params =
- base::SchedulerWorkerPoolParams(
- std::max(GetMinForegroundThreadsInRendererThreadPool(),
- current_foreground_worker_pool_params.max_tasks()),
- current_foreground_worker_pool_params.suggested_reclaim_time(),
- current_foreground_worker_pool_params.backward_compatibility());
+ thread_pool_init_params.max_num_foreground_threads =
+ std::max(GetMinForegroundThreadsInRendererThreadPool(),
+ thread_pool_init_params.max_num_foreground_threads);
}
- base::ThreadPool::GetInstance()->Start(*thread_pool_init_params.get());
+ base::ThreadPoolInstance::Get()->Start(thread_pool_init_params);
}
} // namespace content
diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc
index ab64e8ae556..3a860d58cb8 100644
--- a/chromium/content/browser/storage_partition_impl.cc
+++ b/chromium/content/browser/storage_partition_impl.cc
@@ -23,12 +23,14 @@
#include "base/strings/utf_string_conversions.h"
#include "base/syslog_logging.h"
#include "base/task/post_task.h"
+#include "base/time/default_clock.h"
#include "build/build_config.h"
#include "components/variations/net/variations_http_headers.h"
#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/browser/blob_storage/blob_registry_wrapper.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browser_main_loop.h"
+#include "content/browser/browsing_data/clear_site_data_handler.h"
#include "content/browser/browsing_data/storage_partition_code_cache_data_remover.h"
#include "content/browser/browsing_data/storage_partition_http_cache_data_remover.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -38,7 +40,9 @@
#include "content/browser/gpu/shader_cache_factory.h"
#include "content/browser/indexed_db/leveldb/leveldb_env.h"
#include "content/browser/loader/prefetch_url_loader_service.h"
+#include "content/browser/native_file_system/native_file_system_manager_impl.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_context.h"
@@ -268,6 +272,19 @@ void ClearSessionStorageOnUIThread(
origin_matcher, perform_storage_cleanup, std::move(callback)));
}
+WebContents* GetWebContentsForStoragePartition(uint32_t process_id,
+ uint32_t routing_id) {
+ if (process_id != network::mojom::kBrowserProcessId) {
+ return WebContentsImpl::FromRenderFrameHostID(process_id, routing_id);
+ }
+ return WebContents::FromFrameTreeNodeId(routing_id);
+}
+
+BrowserContext* GetBrowserContextFromStoragePartition(
+ base::WeakPtr<StoragePartitionImpl> weak_partition_ptr) {
+ return weak_partition_ptr ? weak_partition_ptr->browser_context() : nullptr;
+}
+
} // namespace
// Class to own the NetworkContext wrapping a storage partitions
@@ -459,30 +476,6 @@ class StoragePartitionImpl::QuotaManagedDataDeletionHelper {
// finally destroyed when deletion completes (and |callback| is invoked).
class StoragePartitionImpl::DataDeletionHelper {
public:
- // An instance of this class is used instead of a callback to
- // DecrementTaskCount when the callback may be destroyed
- // rather than invoked. The destruction of this object (which also
- // occurs if the null callback is called) will automatically decrement
- // the task count.
- // Note that this object may be destroyed on any thread, as
- // DecrementTaskCount() is thread-neutral.
- // Note that the DataDeletionHelper must outlive this object. This
- // should be guaranteed by the fact that the object holds a reference
- // to the DataDeletionHelper.
- class OwnsReference {
- public:
- explicit OwnsReference(DataDeletionHelper* helper) : helper_(helper) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- helper->IncrementTaskCountOnUI();
- }
-
- ~OwnsReference() { helper_->DecrementTaskCount(); }
-
- static void Callback(std::unique_ptr<OwnsReference> reference) {}
-
- DataDeletionHelper* helper_;
- };
-
DataDeletionHelper(uint32_t remove_mask,
uint32_t quota_storage_remove_mask,
base::OnceClosure callback)
@@ -493,9 +486,6 @@ class StoragePartitionImpl::DataDeletionHelper {
~DataDeletionHelper() {}
- void IncrementTaskCountOnUI();
- void DecrementTaskCount(); // Callable on any thread.
-
void ClearDataOnUIThread(
const GURL& storage_origin,
const OriginMatcherFunction& origin_matcher,
@@ -521,6 +511,19 @@ class StoragePartitionImpl::DataDeletionHelper {
base::OnceClosure callback);
private:
+ enum class TracingDataType {
+ kSynchronous = 1,
+ kCookies = 2,
+ kQuota = 3,
+ kLocalStorage = 4,
+ kSessionStorage = 5,
+ kShaderCache = 6,
+ kPluginPrivate = 7,
+ };
+
+ base::OnceClosure CreateTaskCompletionClosure(TracingDataType data_type);
+ void OnTaskComplete(int tracing_id); // Callable on any thread.
+
uint32_t remove_mask_;
uint32_t quota_storage_remove_mask_;
@@ -671,7 +674,8 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
base::FilePath path = in_memory ? base::FilePath() : partition_path;
partition->indexed_db_context_ = new IndexedDBContextImpl(
path, context->GetSpecialStoragePolicy(), quota_manager_proxy,
- indexed_db::GetDefaultLevelDBFactory());
+ indexed_db::GetDefaultLevelDBFactory(),
+ base::DefaultClock::GetInstance());
partition->cache_storage_context_ = new CacheStorageContextImpl(context);
partition->cache_storage_context_->Init(
@@ -701,7 +705,7 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->platform_notification_context_->Initialize();
partition->devtools_background_services_context_ =
- base::MakeRefCounted<DevToolsBackgroundServicesContext>(
+ base::MakeRefCounted<DevToolsBackgroundServicesContextImpl>(
context, partition->service_worker_context_);
partition->background_fetch_context_ =
@@ -750,6 +754,10 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->cookie_store_context_->Initialize(
partition->service_worker_context_, base::DoNothing());
+ partition->native_file_system_manager_ =
+ base::MakeRefCounted<NativeFileSystemManagerImpl>(
+ partition->filesystem_context_, blob_context);
+
if (base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache)) {
GeneratedCodeCacheSettings settings =
GetContentClient()->browser()->GetGeneratedCodeCacheSettings(context);
@@ -929,11 +937,16 @@ StoragePartitionImpl::GetGeneratedCodeCacheContext() {
return generated_code_cache_context_.get();
}
-DevToolsBackgroundServicesContext*
+DevToolsBackgroundServicesContextImpl*
StoragePartitionImpl::GetDevToolsBackgroundServicesContext() {
return devtools_background_services_context_.get();
}
+NativeFileSystemManagerImpl*
+StoragePartitionImpl::GetNativeFileSystemManager() {
+ return native_file_system_manager_.get();
+}
+
void StoragePartitionImpl::OpenLocalStorage(
const url::Origin& origin,
blink::mojom::StorageAreaRequest request) {
@@ -994,6 +1007,21 @@ void StoragePartitionImpl::OnCanSendDomainReliabilityUpload(
blink::mojom::PermissionStatus::GRANTED);
}
+void StoragePartitionImpl::OnClearSiteData(uint32_t process_id,
+ int32_t routing_id,
+ const GURL& url,
+ const std::string& header_value,
+ int load_flags,
+ OnClearSiteDataCallback callback) {
+ auto browser_context_getter = base::BindRepeating(
+ GetBrowserContextFromStoragePartition, weak_factory_.GetWeakPtr());
+ auto web_contents_getter = base::BindRepeating(
+ GetWebContentsForStoragePartition, process_id, routing_id);
+ ClearSiteDataHandler::HandleHeader(browser_context_getter,
+ web_contents_getter, url, header_value,
+ load_flags, std::move(callback));
+}
+
void StoragePartitionImpl::ClearDataImpl(
uint32_t remove_mask,
uint32_t quota_storage_remove_mask,
@@ -1028,14 +1056,14 @@ void StoragePartitionImpl::DeletionHelperDone(base::OnceClosure callback) {
}
}
-void StoragePartitionImpl::
- QuotaManagedDataDeletionHelper::IncrementTaskCountOnIO() {
+void StoragePartitionImpl::QuotaManagedDataDeletionHelper::
+ IncrementTaskCountOnIO() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
++task_count_;
}
-void StoragePartitionImpl::
- QuotaManagedDataDeletionHelper::DecrementTaskCountOnIO() {
+void StoragePartitionImpl::QuotaManagedDataDeletionHelper::
+ DecrementTaskCountOnIO() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_GT(task_count_, 0);
--task_count_;
@@ -1148,21 +1176,32 @@ void StoragePartitionImpl::QuotaManagedDataDeletionHelper::
CheckQuotaManagedDataDeletionStatus(deletion_task_count, done_callback);
}
-void StoragePartitionImpl::DataDeletionHelper::IncrementTaskCountOnUI() {
+base::OnceClosure
+StoragePartitionImpl::DataDeletionHelper::CreateTaskCompletionClosure(
+ TracingDataType data_type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
++task_count_;
+ static int tracing_id = 0;
+ TRACE_EVENT_ASYNC_BEGIN1("browsing_data", "StoragePartitionImpl",
+ ++tracing_id, "data_type",
+ static_cast<int>(data_type));
+ return base::BindOnce(
+ &StoragePartitionImpl::DataDeletionHelper::OnTaskComplete,
+ base::Unretained(this), tracing_id);
}
-void StoragePartitionImpl::DataDeletionHelper::DecrementTaskCount() {
+void StoragePartitionImpl::DataDeletionHelper::OnTaskComplete(int tracing_id) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&DataDeletionHelper::DecrementTaskCount,
- base::Unretained(this)));
+ base::BindOnce(&DataDeletionHelper::OnTaskComplete,
+ base::Unretained(this), tracing_id));
return;
}
DCHECK_GT(task_count_, 0);
--task_count_;
+ TRACE_EVENT_ASYNC_END0("browsing_data", "StoragePartitionImpl", tracing_id);
+
if (!task_count_) {
std::move(callback_).Run();
delete this;
@@ -1185,9 +1224,8 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
DCHECK_NE(remove_mask_, 0u);
DCHECK(!callback_.is_null());
- IncrementTaskCountOnUI();
- base::RepeatingClosure decrement_callback = base::BindRepeating(
- &DataDeletionHelper::DecrementTaskCount, base::Unretained(this));
+ base::ScopedClosureRunner synchronous_clear_operations(
+ CreateTaskCompletionClosure(TracingDataType::kSynchronous));
if (remove_mask_ & REMOVE_DATA_MASK_COOKIES) {
// The CookieDeletionFilter has a redundant time interval to |begin| and
@@ -1205,11 +1243,10 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
std::move(cookie_deletion_filter),
base::BindOnce(
&OnClearedCookies,
- // Use OwnsReference instead of Increment/DecrementTaskCount*
- // to handle the cookie store being destroyed and the callback
- // thus not being called.
- base::BindOnce(&OwnsReference::Callback,
- std::make_unique<OwnsReference>(this))));
+ // Handle the cookie store being destroyed and the callback thus not
+ // being called.
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ CreateTaskCompletionClosure(TracingDataType::kCookies))));
}
if (remove_mask_ & REMOVE_DATA_MASK_INDEXEDDB ||
@@ -1218,29 +1255,27 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
remove_mask_ & REMOVE_DATA_MASK_FILE_SYSTEMS ||
remove_mask_ & REMOVE_DATA_MASK_SERVICE_WORKERS ||
remove_mask_ & REMOVE_DATA_MASK_CACHE_STORAGE) {
- IncrementTaskCountOnUI();
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&DataDeletionHelper::ClearQuotaManagedDataOnIOThread,
base::Unretained(this), base::WrapRefCounted(quota_manager), begin,
storage_origin, base::WrapRefCounted(special_storage_policy),
- origin_matcher, perform_storage_cleanup, decrement_callback));
+ origin_matcher, perform_storage_cleanup,
+ CreateTaskCompletionClosure(TracingDataType::kQuota)));
}
if (remove_mask_ & REMOVE_DATA_MASK_LOCAL_STORAGE) {
- IncrementTaskCountOnUI();
- ClearLocalStorageOnUIThread(base::WrapRefCounted(dom_storage_context),
- base::WrapRefCounted(special_storage_policy),
- origin_matcher, storage_origin,
- perform_storage_cleanup, begin, end,
- decrement_callback);
+ ClearLocalStorageOnUIThread(
+ base::WrapRefCounted(dom_storage_context),
+ base::WrapRefCounted(special_storage_policy), origin_matcher,
+ storage_origin, perform_storage_cleanup, begin, end,
+ CreateTaskCompletionClosure(TracingDataType::kLocalStorage));
// ClearDataImpl cannot clear session storage data when a particular origin
// is specified. Therefore we ignore clearing session storage in this case.
// TODO(lazyboy): Fix.
if (storage_origin.is_empty()) {
- IncrementTaskCountOnUI();
// TODO(crbug.com/960325): Sometimes SessionStorage fails to call its
// callback. Figure out why.
ClearSessionStorageOnUIThread(
@@ -1248,30 +1283,32 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
base::WrapRefCounted(special_storage_policy), origin_matcher,
perform_storage_cleanup,
mojo::WrapCallbackWithDefaultInvokeIfNotRun(
- static_cast<base::OnceClosure>(decrement_callback)));
+ CreateTaskCompletionClosure(TracingDataType::kSessionStorage)));
}
}
if (remove_mask_ & REMOVE_DATA_MASK_SHADER_CACHE) {
- IncrementTaskCountOnUI();
- base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&ClearShaderCacheOnIOThread, path,
- begin, end, decrement_callback));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(
+ &ClearShaderCacheOnIOThread, path, begin, end,
+ CreateTaskCompletionClosure(TracingDataType::kShaderCache)));
}
#if BUILDFLAG(ENABLE_PLUGINS)
if (remove_mask_ & REMOVE_DATA_MASK_PLUGIN_PRIVATE_DATA) {
- IncrementTaskCountOnUI();
filesystem_context->default_file_task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ClearPluginPrivateDataOnFileTaskRunner,
- base::WrapRefCounted(filesystem_context),
- storage_origin, origin_matcher,
- base::WrapRefCounted(special_storage_policy),
- begin, end, std::move(decrement_callback)));
+ FROM_HERE,
+ base::BindOnce(
+ &ClearPluginPrivateDataOnFileTaskRunner,
+ base::WrapRefCounted(filesystem_context), storage_origin,
+ origin_matcher, base::WrapRefCounted(special_storage_policy), begin,
+ end,
+ base::AdaptCallbackForRepeating(
+ CreateTaskCompletionClosure(TracingDataType::kPluginPrivate))));
}
#endif // BUILDFLAG(ENABLE_PLUGINS)
- DecrementTaskCount();
}
void StoragePartitionImpl::ClearDataForOrigin(
@@ -1287,13 +1324,12 @@ void StoragePartitionImpl::ClearDataForOrigin(
base::Time(), base::Time::Max(), base::DoNothing());
}
-void StoragePartitionImpl::ClearData(
- uint32_t remove_mask,
- uint32_t quota_storage_remove_mask,
- const GURL& storage_origin,
- const base::Time begin,
- const base::Time end,
- base::OnceClosure callback) {
+void StoragePartitionImpl::ClearData(uint32_t remove_mask,
+ uint32_t quota_storage_remove_mask,
+ const GURL& storage_origin,
+ const base::Time begin,
+ const base::Time end,
+ base::OnceClosure callback) {
CookieDeletionFilterPtr deletion_filter = CookieDeletionFilter::New();
if (!storage_origin.host().empty())
deletion_filter->host_name = storage_origin.host();
@@ -1367,6 +1403,8 @@ void StoragePartitionImpl::FlushNetworkInterfaceForTesting() {
url_loader_factory_for_browser_process_.FlushForTesting();
if (cookie_manager_for_browser_process_)
cookie_manager_for_browser_process_.FlushForTesting();
+ if (origin_policy_manager_for_browser_process_)
+ origin_policy_manager_for_browser_process_.FlushForTesting();
}
void StoragePartitionImpl::WaitForDeletionTasksForTesting() {
@@ -1477,4 +1515,25 @@ StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessInternal() {
return url_loader_factory_for_browser_process_.get();
}
+network::mojom::OriginPolicyManager*
+StoragePartitionImpl::GetOriginPolicyManagerForBrowserProcess() {
+ if (!origin_policy_manager_for_browser_process_ ||
+ origin_policy_manager_for_browser_process_.encountered_error()) {
+ GetNetworkContext()->GetOriginPolicyManager(
+ mojo::MakeRequest(&origin_policy_manager_for_browser_process_));
+ }
+ return origin_policy_manager_for_browser_process_.get();
+}
+
+void StoragePartitionImpl::SetOriginPolicyManagerForBrowserProcessForTesting(
+ network::mojom::OriginPolicyManagerPtr test_origin_policy_manager) {
+ origin_policy_manager_for_browser_process_ =
+ std::move(test_origin_policy_manager);
+}
+
+void StoragePartitionImpl::
+ ResetOriginPolicyManagerForBrowserProcessForTesting() {
+ origin_policy_manager_for_browser_process_ = nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/storage_partition_impl.h b/chromium/content/browser/storage_partition_impl.h
index 84aa3aa2091..17e21457603 100644
--- a/chromium/content/browser/storage_partition_impl.h
+++ b/chromium/content/browser/storage_partition_impl.h
@@ -21,7 +21,7 @@
#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"
-#include "content/browser/devtools/devtools_background_services_context.h"
+#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/idle/idle_manager.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
@@ -52,6 +52,7 @@ class CookieStoreContext;
class BlobRegistryWrapper;
class PrefetchURLLoaderService;
class GeneratedCodeCacheContext;
+class NativeFileSystemManagerImpl;
class CONTENT_EXPORT StoragePartitionImpl
: public StoragePartition,
@@ -106,6 +107,8 @@ class CONTENT_EXPORT StoragePartitionImpl
ServiceWorkerContextWrapper* GetServiceWorkerContext() override;
SharedWorkerServiceImpl* GetSharedWorkerService() override;
GeneratedCodeCacheContext* GetGeneratedCodeCacheContext() override;
+ DevToolsBackgroundServicesContextImpl* GetDevToolsBackgroundServicesContext()
+ override;
#if !defined(OS_ANDROID)
HostZoomMap* GetHostZoomMap() override;
HostZoomLevelContext* GetHostZoomLevelContext() override;
@@ -144,7 +147,6 @@ class CONTENT_EXPORT StoragePartitionImpl
void ClearBluetoothAllowedDevicesMapForTesting() override;
void FlushNetworkInterfaceForTesting() override;
void WaitForDeletionTasksForTesting() override;
-
BackgroundFetchContext* GetBackgroundFetchContext();
PaymentAppContextImpl* GetPaymentAppContext();
BroadcastChannelProvider* GetBroadcastChannelProvider();
@@ -152,7 +154,7 @@ class CONTENT_EXPORT StoragePartitionImpl
BlobRegistryWrapper* GetBlobRegistry();
PrefetchURLLoaderService* GetPrefetchURLLoaderService();
CookieStoreContext* GetCookieStoreContext();
- DevToolsBackgroundServicesContext* GetDevToolsBackgroundServicesContext();
+ NativeFileSystemManagerImpl* GetNativeFileSystemManager();
// blink::mojom::StoragePartitionService interface.
void OpenLocalStorage(const url::Origin& origin,
@@ -168,6 +170,12 @@ class CONTENT_EXPORT StoragePartitionImpl
void OnCanSendDomainReliabilityUpload(
const GURL& origin,
OnCanSendDomainReliabilityUploadCallback callback) override;
+ void OnClearSiteData(uint32_t process_id,
+ int32_t routing_id,
+ const GURL& url,
+ const std::string& header_value,
+ int load_flags,
+ OnClearSiteDataCallback callback) override;
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter() {
return url_loader_factory_getter_;
@@ -201,6 +209,15 @@ class CONTENT_EXPORT StoragePartitionImpl
return site_for_service_worker_;
}
+ // Use the network context to retrieve the origin policy manager.
+ network::mojom::OriginPolicyManager*
+ GetOriginPolicyManagerForBrowserProcess();
+
+ // Override the origin policy manager for testing use only.
+ void SetOriginPolicyManagerForBrowserProcessForTesting(
+ network::mojom::OriginPolicyManagerPtr test_origin_policy_manager);
+ void ResetOriginPolicyManagerForBrowserProcessForTesting();
+
private:
class DataDeletionHelper;
class QuotaManagedDataDeletionHelper;
@@ -339,8 +356,9 @@ class CONTENT_EXPORT StoragePartitionImpl
scoped_refptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
scoped_refptr<CookieStoreContext> cookie_store_context_;
scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context_;
- scoped_refptr<DevToolsBackgroundServicesContext>
+ scoped_refptr<DevToolsBackgroundServicesContextImpl>
devtools_background_services_context_;
+ scoped_refptr<NativeFileSystemManagerImpl> native_file_system_manager_;
// BindingSet for StoragePartitionService, using the process id as the
// binding context type. The process id can subsequently be used during
@@ -368,6 +386,8 @@ class CONTENT_EXPORT StoragePartitionImpl
network::mojom::URLLoaderFactoryPtr url_loader_factory_for_browser_process_;
bool is_test_url_loader_factory_for_browser_process_ = false;
network::mojom::CookieManagerPtr cookie_manager_for_browser_process_;
+ network::mojom::OriginPolicyManagerPtr
+ origin_policy_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_map.cc b/chromium/content/browser/storage_partition_impl_map.cc
index 27a2400e1e2..1ce0d53ba1d 100644
--- a/chromium/content/browser/storage_partition_impl_map.cc
+++ b/chromium/content/browser/storage_partition_impl_map.cc
@@ -574,12 +574,8 @@ void StoragePartitionImplMap::PostCreateInitialization(
browser_context_->GetResourceContext(), request_context_getter,
base::RetainedRef(browser_context_->GetSpecialStoragePolicy())));
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&CacheStorageContextImpl::SetBlobParametersForCache,
- partition->GetCacheStorageContext(),
- base::RetainedRef(ChromeBlobStorageContext::GetFor(
- browser_context_))));
+ partition->GetCacheStorageContext()->SetBlobParametersForCache(
+ ChromeBlobStorageContext::GetFor(browser_context_));
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
@@ -589,10 +585,12 @@ void StoragePartitionImplMap::PostCreateInitialization(
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&PrefetchURLLoaderService::InitializeResourceContext,
- partition->GetPrefetchURLLoaderService(),
- browser_context_->GetResourceContext(),
- request_context_getter));
+ base::BindOnce(
+ &PrefetchURLLoaderService::InitializeResourceContext,
+ partition->GetPrefetchURLLoaderService(),
+ browser_context_->GetResourceContext(), request_context_getter,
+ base::RetainedRef(
+ ChromeBlobStorageContext::GetFor(browser_context_))));
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
diff --git a/chromium/content/browser/storage_partition_impl_unittest.cc b/chromium/content/browser/storage_partition_impl_unittest.cc
index 67044446d16..39a7d9984f1 100644
--- a/chromium/content/browser/storage_partition_impl_unittest.cc
+++ b/chromium/content/browser/storage_partition_impl_unittest.cc
@@ -68,7 +68,7 @@ const char kCacheValue[] = "cached value";
const char kTestOrigin1[] = "http://host1:1/";
const char kTestOrigin2[] = "http://host2:1/";
const char kTestOrigin3[] = "http://host3:1/";
-const char kTestOriginDevTools[] = "chrome-devtools://abcdefghijklmnopqrstuvw/";
+const char kTestOriginDevTools[] = "devtools://abcdefghijklmnopqrstuvw/";
const char kTestURL[] = "http://host4/script.js";
const char kFilterURLForCodeCache[] = "http://host5/script.js";
@@ -137,16 +137,13 @@ class AwaitCompletionHelper {
class RemoveCookieTester {
public:
- explicit RemoveCookieTester(TestBrowserContext* context)
- : get_cookie_success_(false),
- cookie_store_(context->GetRequestContext()
- ->GetURLRequestContext()
- ->cookie_store()) {}
+ explicit RemoveCookieTester(StoragePartition* storage_partition)
+ : get_cookie_success_(false), storage_partition_(storage_partition) {}
// Returns true, if the given cookie exists in the cookie store.
bool ContainsCookie() {
get_cookie_success_ = false;
- cookie_store_->GetCookieListWithOptionsAsync(
+ storage_partition_->GetCookieManagerForBrowserProcess()->GetCookieList(
kOrigin1.GetURL(), net::CookieOptions(),
base::BindOnce(&RemoveCookieTester::GetCookieListCallback,
base::Unretained(this)));
@@ -155,8 +152,12 @@ class RemoveCookieTester {
}
void AddCookie() {
- cookie_store_->SetCookieWithOptionsAsync(
- kOrigin1.GetURL(), "A=1", net::CookieOptions(),
+ CanonicalCookie::CookieInclusionStatus status;
+ std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create(
+ kOrigin1.GetURL(), "A=1", base::Time::Now(), net::CookieOptions(),
+ &status));
+ storage_partition_->GetCookieManagerForBrowserProcess()->SetCanonicalCookie(
+ *cc, kOrigin1.scheme(), net::CookieOptions(),
base::BindOnce(&RemoveCookieTester::SetCookieCallback,
base::Unretained(this)));
await_completion_.BlockUntilNotified();
@@ -183,7 +184,7 @@ class RemoveCookieTester {
bool get_cookie_success_;
AwaitCompletionHelper await_completion_;
- net::CookieStore* cookie_store_;
+ StoragePartition* storage_partition_;
DISALLOW_COPY_AND_ASSIGN(RemoveCookieTester);
};
@@ -1152,15 +1153,13 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedIgnoreDevTools) {
}
TEST_F(StoragePartitionImplTest, RemoveCookieForever) {
- RemoveCookieTester tester(browser_context());
+ StoragePartition* partition =
+ BrowserContext::GetDefaultStoragePartition(browser_context());
+ RemoveCookieTester tester(partition);
tester.AddCookie();
ASSERT_TRUE(tester.ContainsCookie());
- StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
- BrowserContext::GetDefaultStoragePartition(browser_context()));
- partition->SetURLRequestContext(browser_context()->GetRequestContext());
-
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&ClearCookies, partition, base::Time(),
@@ -1171,15 +1170,14 @@ TEST_F(StoragePartitionImplTest, RemoveCookieForever) {
}
TEST_F(StoragePartitionImplTest, RemoveCookieLastHour) {
- RemoveCookieTester tester(browser_context());
+ StoragePartition* partition =
+ BrowserContext::GetDefaultStoragePartition(browser_context());
+ RemoveCookieTester tester(partition);
tester.AddCookie();
ASSERT_TRUE(tester.ContainsCookie());
- StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
- BrowserContext::GetDefaultStoragePartition(browser_context()));
base::Time an_hour_ago = base::Time::Now() - base::TimeDelta::FromHours(1);
- partition->SetURLRequestContext(browser_context()->GetRequestContext());
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -1191,15 +1189,13 @@ TEST_F(StoragePartitionImplTest, RemoveCookieLastHour) {
}
TEST_F(StoragePartitionImplTest, RemoveCookieWithDeleteInfo) {
- RemoveCookieTester tester(browser_context());
+ StoragePartition* partition =
+ BrowserContext::GetDefaultStoragePartition(browser_context());
+ RemoveCookieTester tester(partition);
tester.AddCookie();
ASSERT_TRUE(tester.ContainsCookie());
- StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
- BrowserContext::GetDefaultStoragePartition(browser_context()));
- partition->SetURLRequestContext(browser_context()->GetRequestContext());
-
base::RunLoop run_loop2;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&ClearCookiesMatchingInfo, partition,
@@ -1391,8 +1387,7 @@ TEST_F(StoragePartitionImplTest, ClearCodeCacheSpecificURL) {
base::RunLoop().RunUntilIdle();
}
-// TODO(https://crbug.com/925957): Flakes, especially under Fuchsia.
-TEST_F(StoragePartitionImplTest, DISABLED_ClearCodeCacheDateRange) {
+TEST_F(StoragePartitionImplTest, ClearCodeCacheDateRange) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(net::features::kIsolatedCodeCache);
ASSERT_TRUE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
@@ -1424,8 +1419,8 @@ TEST_F(StoragePartitionImplTest, DISABLED_ClearCodeCacheDateRange) {
origin, data);
EXPECT_TRUE(tester.ContainsEntry(RemoveCodeCacheTester::kJs,
kFilterResourceURLForCodeCache, origin));
- tester.SetLastUseTime(RemoveCodeCacheTester::kJs, kResourceURL, origin,
- in_range_time);
+ tester.SetLastUseTime(RemoveCodeCacheTester::kJs,
+ kFilterResourceURLForCodeCache, origin, in_range_time);
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chromium/content/browser/tracing/background_tracing_active_scenario.cc b/chromium/content/browser/tracing/background_tracing_active_scenario.cc
index 259b0a03afa..ac4b04326d6 100644
--- a/chromium/content/browser/tracing/background_tracing_active_scenario.cc
+++ b/chromium/content/browser/tracing/background_tracing_active_scenario.cc
@@ -16,12 +16,22 @@
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/browser/tracing/background_tracing_rule.h"
#include "content/browser/tracing/tracing_controller_impl.h"
+#include "content/public/common/service_manager_connection.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/system/data_pipe_drainer.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_config.h"
#include "services/tracing/public/cpp/perfetto/trace_event_data_source.h"
#include "services/tracing/public/cpp/tracing_features.h"
+#include "services/tracing/public/mojom/constants.mojom.h"
using base::trace_event::TraceConfig;
using Metrics = content::BackgroundTracingManagerImpl::Metrics;
+namespace {
+const size_t kDefaultTraceBufferSizeInKb = 10 * 1024;
+} // namespace
+
namespace content {
class BackgroundTracingActiveScenario::TracingTimer {
@@ -50,8 +60,218 @@ class BackgroundTracingActiveScenario::TracingTimer {
BackgroundTracingManager::StartedFinalizingCallback callback_;
};
+class BackgroundTracingActiveScenario::TracingSession {
+ public:
+ virtual ~TracingSession() = default;
+ virtual void BeginFinalizing(const base::RepeatingClosure& on_success,
+ const base::RepeatingClosure& on_failure) = 0;
+ virtual void AbortScenario(
+ const base::RepeatingClosure& on_abort_callback) = 0;
+};
+
+class PerfettoTracingSession
+ : public BackgroundTracingActiveScenario::TracingSession,
+ public tracing::mojom::TracingSessionClient,
+ public mojo::DataPipeDrainer::Client {
+ public:
+ PerfettoTracingSession(BackgroundTracingActiveScenario* parent_scenario,
+ const TraceConfig& chrome_config,
+ BackgroundTracingConfigImpl::CategoryPreset preset)
+ : parent_scenario_(parent_scenario),
+ category_preset_(preset),
+ raw_data_(std::make_unique<std::string>()) {
+#if !defined(OS_ANDROID)
+ // TODO(crbug.com/941318): Re-enable startup tracing for Android once all
+ // Perfetto-related deadlocks are resolved.
+ if (!TracingControllerImpl::GetInstance()->IsTracing() &&
+ tracing::TracingUsesPerfettoBackend()) {
+ tracing::TraceEventDataSource::GetInstance()->SetupStartupTracing(
+ /*privacy_filtering_enabled=*/true);
+ }
+#endif
+
+ ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
+ tracing::mojom::kServiceName, &consumer_host_);
+
+ perfetto::TraceConfig perfetto_config = tracing::GetDefaultPerfettoConfig(
+ chrome_config, /*privacy_filtering_enabled=*/true);
+
+ tracing::mojom::TracingSessionClientPtr tracing_session_client;
+ binding_.Bind(mojo::MakeRequest(&tracing_session_client));
+ binding_.set_connection_error_handler(
+ base::BindOnce(&PerfettoTracingSession::OnTracingSessionEnded,
+ base::Unretained(this)));
+
+ consumer_host_->EnableTracing(
+ mojo::MakeRequest(&tracing_session_host_),
+ std::move(tracing_session_client), std::move(perfetto_config),
+ tracing::mojom::TracingClientPriority::kBackground);
+ tracing_session_host_.set_connection_error_handler(
+ base::BindOnce(&PerfettoTracingSession::OnTracingSessionEnded,
+ base::Unretained(this)));
+ }
+
+ // BackgroundTracingActiveScenario::TracingSession implementation.
+ void BeginFinalizing(const base::RepeatingClosure& on_success,
+ const base::RepeatingClosure& on_failure) override {
+ bool is_allowed_finalization =
+ BackgroundTracingManagerImpl::GetInstance()->IsAllowedFinalization();
+
+ if (!is_allowed_finalization) {
+ on_failure.Run();
+ return;
+ }
+
+ tracing_session_host_->DisableTracing();
+ on_success.Run();
+ }
+
+ void AbortScenario(const base::RepeatingClosure& on_abort_callback) override {
+ on_abort_callback.Run();
+ }
+
+ // mojo::DataPipeDrainer::Client implementation:
+ void OnDataAvailable(const void* data, size_t num_bytes) override {
+ raw_data_->append(reinterpret_cast<const char*>(data), num_bytes);
+ }
+
+ void OnDataComplete() override {
+ has_finished_receiving_data_ = true;
+ MaybeFinishedReceivingTrace();
+ }
+
+ // tracing::mojom::TracingSession implementation:
+ void OnTracingEnabled() override {
+ BackgroundTracingManagerImpl::GetInstance()->OnStartTracingDone(
+ category_preset_);
+ }
+
+ void OnTracingDisabled() override {
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+
+ MojoResult result =
+ mojo::CreateDataPipe(nullptr, &producer_handle, &consumer_handle);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+
+ drainer_ = std::make_unique<mojo::DataPipeDrainer>(
+ this, std::move(consumer_handle));
+ tracing_session_host_->ReadBuffers(
+ std::move(producer_handle),
+ base::BindOnce(&PerfettoTracingSession::OnReadBuffersComplete,
+ base::Unretained(this)));
+ }
+
+ void OnReadBuffersComplete() {
+ has_finished_read_buffers_ = true;
+ MaybeFinishedReceivingTrace();
+ }
+
+ void MaybeFinishedReceivingTrace() {
+ if (has_finished_read_buffers_ && has_finished_receiving_data_) {
+ DCHECK(raw_data_);
+ parent_scenario_->OnProtoDataComplete(std::move(raw_data_));
+ }
+ }
+
+ private:
+ void OnTracingSessionEnded() { parent_scenario_->AbortScenario(); }
+
+ BackgroundTracingActiveScenario* const parent_scenario_;
+ mojo::Binding<tracing::mojom::TracingSessionClient> binding_{this};
+ tracing::mojom::TracingSessionHostPtr tracing_session_host_;
+ std::unique_ptr<mojo::DataPipeDrainer> drainer_;
+ tracing::mojom::ConsumerHostPtr consumer_host_;
+ BackgroundTracingConfigImpl::CategoryPreset category_preset_;
+ std::unique_ptr<std::string> raw_data_;
+ bool has_finished_read_buffers_ = false;
+ bool has_finished_receiving_data_ = false;
+};
+
+class LegacyTracingSession
+ : public BackgroundTracingActiveScenario::TracingSession {
+ public:
+ LegacyTracingSession(BackgroundTracingActiveScenario* parent_scenario,
+ const TraceConfig& chrome_config,
+ BackgroundTracingConfigImpl::CategoryPreset preset)
+ : parent_scenario_(parent_scenario) {
+#if !defined(OS_ANDROID)
+ // TODO(crbug.com/941318): Re-enable startup tracing for Android once all
+ // Perfetto-related deadlocks are resolved.
+ if (!TracingControllerImpl::GetInstance()->IsTracing() &&
+ tracing::TracingUsesPerfettoBackend()) {
+ tracing::TraceEventDataSource::GetInstance()->SetupStartupTracing(
+ /*privacy_filtering_enabled=*/false);
+ }
+#endif
+
+ bool result = TracingControllerImpl::GetInstance()->StartTracing(
+ chrome_config,
+ base::BindOnce(
+ &BackgroundTracingManagerImpl::OnStartTracingDone,
+ base::Unretained(BackgroundTracingManagerImpl::GetInstance()),
+ preset));
+ // We check IsEnabled() before creating the LegacyTracingSession,
+ // so any failures to start tracing at this point would be due to invalid
+ // configs which we treat as a failure scenario.
+ DCHECK(result);
+ }
+
+ ~LegacyTracingSession() override {
+ DCHECK(!TracingControllerImpl::GetInstance()->IsTracing());
+ }
+
+ // BackgroundTracingActiveScenario::TracingSession implementation.
+ void BeginFinalizing(const base::RepeatingClosure& on_success,
+ const base::RepeatingClosure& on_failure) override {
+ if (!BackgroundTracingManagerImpl::GetInstance()->IsAllowedFinalization()) {
+ TracingControllerImpl::GetInstance()->StopTracing(
+ TracingControllerImpl::CreateCallbackEndpoint(base::BindRepeating(
+ [](const base::RepeatingClosure& on_failure,
+ std::unique_ptr<const base::DictionaryValue>,
+ base::RefCountedString*) { on_failure.Run(); },
+ std::move(on_failure))));
+ return;
+ }
+
+ auto trace_data_endpoint =
+ TracingControllerImpl::CreateCompressedStringEndpoint(
+ TracingControllerImpl::CreateCallbackEndpoint(base::BindRepeating(
+ [](base::WeakPtr<BackgroundTracingActiveScenario> weak_this,
+ const base::RepeatingClosure& on_success,
+ std::unique_ptr<const base::DictionaryValue> metadata,
+ base::RefCountedString* file_contents) {
+ on_success.Run();
+ if (weak_this) {
+ weak_this->OnJSONDataComplete(std::move(metadata),
+ file_contents);
+ }
+ },
+ parent_scenario_->GetWeakPtr(), std::move(on_success))),
+ true /* compress_with_background_priority */);
+
+ TracingControllerImpl::GetInstance()->StopTracing(trace_data_endpoint);
+ }
+
+ void AbortScenario(const base::RepeatingClosure& on_abort_callback) override {
+ if (TracingControllerImpl::GetInstance()->IsTracing()) {
+ TracingControllerImpl::GetInstance()->StopTracing(
+ TracingControllerImpl::CreateCallbackEndpoint(base::BindRepeating(
+ [](const base::RepeatingClosure& on_abort_callback,
+ std::unique_ptr<const base::DictionaryValue>,
+ base::RefCountedString*) { on_abort_callback.Run(); },
+ std::move(on_abort_callback))));
+ } else {
+ on_abort_callback.Run();
+ }
+ }
+
+ private:
+ BackgroundTracingActiveScenario* const parent_scenario_;
+};
+
BackgroundTracingActiveScenario::BackgroundTracingActiveScenario(
- std::unique_ptr<const BackgroundTracingConfigImpl> config,
+ std::unique_ptr<BackgroundTracingConfigImpl> config,
bool requires_anonymized_data,
BackgroundTracingManager::ReceiveCallback receive_callback,
base::OnceClosure on_aborted_callback)
@@ -104,6 +324,7 @@ void BackgroundTracingActiveScenario::SetState(State new_state) {
}
if (scenario_state_ == State::kAborted) {
+ tracing_session_.reset();
std::move(on_aborted_callback_).Run();
}
}
@@ -118,59 +339,69 @@ void BackgroundTracingActiveScenario::SetRuleTriggeredCallbackForTesting(
rule_triggered_callback_for_testing_ = callback;
}
+base::WeakPtr<BackgroundTracingActiveScenario>
+BackgroundTracingActiveScenario::GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
void BackgroundTracingActiveScenario::StartTracingIfConfigNeedsIt() {
DCHECK(config_);
if (config_->tracing_mode() == BackgroundTracingConfigImpl::PREEMPTIVE) {
StartTracing(config_->category_preset(),
base::trace_event::RECORD_CONTINUOUSLY);
- return;
}
// There is nothing to do in case of reactive tracing.
}
-void BackgroundTracingActiveScenario::StartTracing(
+bool BackgroundTracingActiveScenario::StartTracing(
BackgroundTracingConfigImpl::CategoryPreset preset,
base::trace_event::TraceRecordMode record_mode) {
- TraceConfig config = BackgroundTracingConfigImpl::GetConfigForCategoryPreset(
- preset, record_mode);
- if (requires_anonymized_data_)
- config.EnableArgumentFilter();
+ TraceConfig chrome_config =
+ BackgroundTracingConfigImpl::GetConfigForCategoryPreset(preset,
+ record_mode);
+ if (requires_anonymized_data_) {
+ chrome_config.EnableArgumentFilter();
+ }
+
+ chrome_config.SetTraceBufferSizeInKb(kDefaultTraceBufferSizeInKb);
+
#if defined(OS_ANDROID)
// Set low trace buffer size on Android in order to upload small trace files.
if (config_->tracing_mode() == BackgroundTracingConfigImpl::PREEMPTIVE) {
- config.SetTraceBufferSizeInEvents(20000);
- config.SetTraceBufferSizeInKb(500);
+ chrome_config.SetTraceBufferSizeInEvents(20000);
+ chrome_config.SetTraceBufferSizeInKb(500);
}
#endif
- if (!TracingControllerImpl::GetInstance()->IsTracing() &&
- tracing::TracingUsesPerfettoBackend()) {
- tracing::TraceEventDataSource::GetInstance()->SetupStartupTracing();
- }
-
- if (!TracingControllerImpl::GetInstance()->StartTracing(
- config,
- base::BindOnce(
- &BackgroundTracingManagerImpl::OnStartTracingDone,
- base::Unretained(BackgroundTracingManagerImpl::GetInstance()),
- preset))) {
+ // If the tracing controller is tracing, i.e. DevTools or about://tracing,
+ // we don't start background tracing to not interfere with the user activity.
+ if (TracingControllerImpl::GetInstance()->IsTracing()) {
AbortScenario();
- return;
+ return false;
}
- SetState(State::kTracing);
-
// Activate the categories immediately. StartTracing eventually does this
- // itself, but asynchronously via PostTask, and in the meantime events will be
+ // itself, but asynchronously via Mojo, and in the meantime events will be
// dropped. This ensures that we start recording events for those categories
// immediately.
uint8_t modes = base::trace_event::TraceLog::RECORDING_MODE;
- if (!config.event_filters().empty())
+ if (!chrome_config.event_filters().empty())
modes |= base::trace_event::TraceLog::FILTERING_MODE;
- base::trace_event::TraceLog::GetInstance()->SetEnabled(config, modes);
+ base::trace_event::TraceLog::GetInstance()->SetEnabled(chrome_config, modes);
+
+ DCHECK(!tracing_session_);
+ if (base::FeatureList::IsEnabled(features::kBackgroundTracingProtoOutput)) {
+ tracing_session_ =
+ std::make_unique<PerfettoTracingSession>(this, chrome_config, preset);
+ } else {
+ tracing_session_ =
+ std::make_unique<LegacyTracingSession>(this, chrome_config, preset);
+ }
+ SetState(State::kTracing);
BackgroundTracingManagerImpl::RecordMetric(Metrics::RECORDING_ENABLED);
+ return true;
}
void BackgroundTracingActiveScenario::BeginFinalizing(
@@ -178,56 +409,54 @@ void BackgroundTracingActiveScenario::BeginFinalizing(
triggered_named_event_handle_ = -1;
tracing_timer_.reset();
- scoped_refptr<TracingControllerImpl::TraceDataEndpoint> trace_data_endpoint;
- bool is_allowed_finalization =
- BackgroundTracingManagerImpl::GetInstance()->IsAllowedFinalization();
- base::RepeatingClosure started_finalizing_closure;
- if (!callback.is_null()) {
- started_finalizing_closure =
- base::BindRepeating(callback, is_allowed_finalization);
- }
-
- if (is_allowed_finalization) {
- trace_data_endpoint = TracingControllerImpl::CreateCompressedStringEndpoint(
- TracingControllerImpl::CreateCallbackEndpoint(base::BindRepeating(
- &BackgroundTracingActiveScenario::OnTracingStopped,
- weak_ptr_factory_.GetWeakPtr(),
- std::move(started_finalizing_closure))),
- true /* compress_with_background_priority */);
- BackgroundTracingManagerImpl::RecordMetric(Metrics::FINALIZATION_ALLOWED);
- } else {
- trace_data_endpoint =
- TracingControllerImpl::CreateCallbackEndpoint(base::BindRepeating(
- [](base::RepeatingClosure closure,
- base::WeakPtr<BackgroundTracingActiveScenario> active_scenario,
- std::unique_ptr<const base::DictionaryValue> metadata,
- base::RefCountedString* file_contents) {
- if (active_scenario) {
- active_scenario->SetState(State::kAborted);
- }
-
- if (closure) {
- std::move(closure).Run();
- }
- },
- std::move(started_finalizing_closure),
- weak_ptr_factory_.GetWeakPtr()));
- BackgroundTracingManagerImpl::RecordMetric(
- Metrics::FINALIZATION_DISALLOWED);
- }
-
- TracingControllerImpl::GetInstance()->StopTracing(trace_data_endpoint);
+ auto on_begin_finalization_success = base::BindRepeating(
+ [](base::WeakPtr<BackgroundTracingActiveScenario> weak_this,
+ BackgroundTracingManager::StartedFinalizingCallback callback) {
+ if (!weak_this) {
+ return;
+ }
+
+ weak_this->SetState(State::kFinalizing);
+ BackgroundTracingManagerImpl::RecordMetric(
+ Metrics::FINALIZATION_ALLOWED);
+ DCHECK(!weak_this->started_finalizing_closure_);
+ if (!callback.is_null()) {
+ weak_this->started_finalizing_closure_ =
+ base::BindOnce(callback, /*is_allowed_finalization=*/true);
+ }
+ },
+ weak_ptr_factory_.GetWeakPtr(), callback);
+
+ auto on_begin_finalization_failure = base::BindRepeating(
+ [](base::WeakPtr<BackgroundTracingActiveScenario> weak_this,
+ BackgroundTracingManager::StartedFinalizingCallback callback) {
+ if (!weak_this) {
+ return;
+ }
+
+ BackgroundTracingManagerImpl::RecordMetric(
+ Metrics::FINALIZATION_DISALLOWED);
+ weak_this->SetState(State::kAborted);
+
+ if (!callback.is_null()) {
+ callback.Run(false);
+ }
+ },
+ weak_ptr_factory_.GetWeakPtr(), callback);
+
+ tracing_session_->BeginFinalizing(std::move(on_begin_finalization_success),
+ std::move(on_begin_finalization_failure));
}
-void BackgroundTracingActiveScenario::OnTracingStopped(
- base::RepeatingClosure started_finalizing_closure,
+void BackgroundTracingActiveScenario::OnJSONDataComplete(
std::unique_ptr<const base::DictionaryValue> metadata,
base::RefCountedString* file_contents) {
- SetState(State::kFinalizing);
BackgroundTracingManagerImpl::RecordMetric(Metrics::FINALIZATION_STARTED);
UMA_HISTOGRAM_MEMORY_KB("Tracing.Background.FinalizingTraceSizeInKB",
file_contents->size() / 1024);
+ // Send the finalized and compressed tracing data to the destination
+ // callback.
if (!receive_callback_.is_null()) {
receive_callback_.Run(
file_contents, std::move(metadata),
@@ -235,8 +464,22 @@ void BackgroundTracingActiveScenario::OnTracingStopped(
weak_ptr_factory_.GetWeakPtr()));
}
- if (!started_finalizing_closure.is_null()) {
- std::move(started_finalizing_closure).Run();
+ if (started_finalizing_closure_) {
+ std::move(started_finalizing_closure_).Run();
+ }
+}
+
+void BackgroundTracingActiveScenario::OnProtoDataComplete(
+ std::unique_ptr<std::string> proto_trace) {
+ BackgroundTracingManagerImpl::RecordMetric(Metrics::FINALIZATION_STARTED);
+ UMA_HISTOGRAM_MEMORY_KB("Tracing.Background.FinalizingTraceSizeInKB",
+ proto_trace->size() / 1024);
+
+ BackgroundTracingManagerImpl::GetInstance()->SetTraceToUpload(
+ std::move(proto_trace));
+
+ if (started_finalizing_closure_) {
+ std::move(started_finalizing_closure_).Run();
}
}
@@ -247,6 +490,7 @@ void BackgroundTracingActiveScenario::OnFinalizeComplete(bool success) {
BackgroundTracingManagerImpl::RecordMetric(Metrics::UPLOAD_FAILED);
}
+ tracing_session_.reset();
SetState(State::kIdle);
// Now that a trace has completed, we may need to enable recording again.
@@ -254,24 +498,18 @@ void BackgroundTracingActiveScenario::OnFinalizeComplete(bool success) {
}
void BackgroundTracingActiveScenario::AbortScenario() {
- if ((state() != State::kTracing)) {
+ if (tracing_session_) {
+ tracing_session_->AbortScenario(base::BindRepeating(
+ [](base::WeakPtr<BackgroundTracingActiveScenario> weak_this) {
+ if (weak_this) {
+ weak_this->SetState(State::kAborted);
+ }
+ },
+ weak_ptr_factory_.GetWeakPtr()));
+ } else {
// Setting the kAborted state will cause |this| to be destroyed.
SetState(State::kAborted);
- return;
}
-
- auto trace_data_endpoint =
- TracingControllerImpl::CreateCallbackEndpoint(base::BindRepeating(
- [](base::WeakPtr<BackgroundTracingActiveScenario> active_scenario,
- std::unique_ptr<const base::DictionaryValue>,
- base::RefCountedString*) {
- if (active_scenario) {
- active_scenario->SetState(State::kAborted);
- }
- },
- weak_ptr_factory_.GetWeakPtr()));
-
- TracingControllerImpl::GetInstance()->StopTracing(trace_data_endpoint);
}
void BackgroundTracingActiveScenario::TriggerNamedEvent(
@@ -315,6 +553,7 @@ void BackgroundTracingActiveScenario::OnHistogramTrigger(
void BackgroundTracingActiveScenario::OnRuleTriggered(
const BackgroundTracingRule* triggered_rule,
BackgroundTracingManager::StartedFinalizingCallback callback) {
+ DCHECK_NE(state(), State::kAborted);
double trigger_chance = triggered_rule->trigger_chance();
if (trigger_chance < 1.0 && base::RandDouble() > trigger_chance) {
if (!callback.is_null()) {
@@ -335,8 +574,10 @@ void BackgroundTracingActiveScenario::OnRuleTriggered(
if (state() != State::kTracing) {
// It was not already tracing, start a new trace.
- StartTracing(triggered_rule->category_preset(),
- base::trace_event::RECORD_UNTIL_FULL);
+ if (!StartTracing(triggered_rule->category_preset(),
+ base::trace_event::RECORD_UNTIL_FULL)) {
+ return;
+ }
} else {
// Some reactive configs that trigger again while tracing should just
// end right away (to not capture multiple navigations, for example).
diff --git a/chromium/content/browser/tracing/background_tracing_active_scenario.h b/chromium/content/browser/tracing/background_tracing_active_scenario.h
index 8c1aaaa0f8d..5b9a6db55df 100644
--- a/chromium/content/browser/tracing/background_tracing_active_scenario.h
+++ b/chromium/content/browser/tracing/background_tracing_active_scenario.h
@@ -11,7 +11,9 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/tracing/background_tracing_config_impl.h"
+#include "content/browser/tracing/tracing_controller_impl.h"
#include "content/public/browser/background_tracing_manager.h"
+#include "services/tracing/public/mojom/perfetto_service.mojom.h"
namespace base {
class RefCountedString;
@@ -24,13 +26,14 @@ class BackgroundTracingConfigImpl;
class BackgroundTracingActiveScenario {
public:
enum class State { kIdle, kTracing, kFinalizing, kUploading, kAborted };
+ class TracingSession;
BackgroundTracingActiveScenario(
- std::unique_ptr<const BackgroundTracingConfigImpl> config,
+ std::unique_ptr<BackgroundTracingConfigImpl> config,
bool requires_anonymized_data,
BackgroundTracingManager::ReceiveCallback receive_callback,
base::OnceClosure on_aborted_callback);
- ~BackgroundTracingActiveScenario();
+ virtual ~BackgroundTracingActiveScenario();
void StartTracingIfConfigNeedsIt();
void AbortScenario();
@@ -39,6 +42,7 @@ class BackgroundTracingActiveScenario {
void GenerateMetadataDict(base::DictionaryValue* metadata_dict);
State state() const { return scenario_state_; }
bool requires_anonymized_data() const { return requires_anonymized_data_; }
+ base::WeakPtr<BackgroundTracingActiveScenario> GetWeakPtr();
void TriggerNamedEvent(
BackgroundTracingManager::TriggerHandle handle,
@@ -48,29 +52,34 @@ class BackgroundTracingActiveScenario {
const BackgroundTracingRule* triggered_rule,
BackgroundTracingManager::StartedFinalizingCallback callback);
+ // Called by LegacyTracingSession when the final trace data is ready.
+ void OnJSONDataComplete(std::unique_ptr<const base::DictionaryValue> metadata,
+ base::RefCountedString*);
+ // Called by the PerfettoTracingSession when the proto trace is ready.
+ void OnProtoDataComplete(std::unique_ptr<std::string> proto_trace);
+
+ // Called when the finalized trace data has been uploaded/transferred away
+ // from the background tracing system.
+ void OnFinalizeComplete(bool success);
+
// For testing
CONTENT_EXPORT void FireTimerForTesting();
CONTENT_EXPORT void SetRuleTriggeredCallbackForTesting(
const base::RepeatingClosure& callback);
private:
- void StartTracing(BackgroundTracingConfigImpl::CategoryPreset,
+ bool StartTracing(BackgroundTracingConfigImpl::CategoryPreset,
base::trace_event::TraceRecordMode);
-
void BeginFinalizing(
BackgroundTracingManager::StartedFinalizingCallback callback);
- void OnTracingStopped(base::RepeatingClosure started_finalizing_closure,
- std::unique_ptr<const base::DictionaryValue> metadata,
- base::RefCountedString*);
-
- void OnFinalizeComplete(bool success);
BackgroundTracingRule* GetRuleAbleToTriggerTracing(
const std::string& trigger_name);
void SetState(State new_state);
- std::unique_ptr<const BackgroundTracingConfigImpl> config_;
+ std::unique_ptr<TracingSession> tracing_session_;
+ std::unique_ptr<BackgroundTracingConfigImpl> config_;
bool requires_anonymized_data_;
State scenario_state_;
std::unique_ptr<base::DictionaryValue> last_triggered_rule_;
@@ -78,6 +87,7 @@ class BackgroundTracingActiveScenario {
BackgroundTracingManager::ReceiveCallback receive_callback_;
BackgroundTracingManager::TriggerHandle triggered_named_event_handle_;
base::OnceClosure on_aborted_callback_;
+ base::OnceClosure started_finalizing_closure_;
class TracingTimer;
std::unique_ptr<TracingTimer> tracing_timer_;
diff --git a/chromium/content/browser/tracing/background_tracing_config_impl.cc b/chromium/content/browser/tracing/background_tracing_config_impl.cc
index cdde02f2b1e..40d4d0303de 100644
--- a/chromium/content/browser/tracing/background_tracing_config_impl.cc
+++ b/chromium/content/browser/tracing/background_tracing_config_impl.cc
@@ -168,7 +168,7 @@ bool BackgroundTracingConfigImpl::StringToCategoryPreset(
return false;
}
-void BackgroundTracingConfigImpl::IntoDict(base::DictionaryValue* dict) const {
+void BackgroundTracingConfigImpl::IntoDict(base::DictionaryValue* dict) {
switch (tracing_mode()) {
case BackgroundTracingConfigImpl::PREEMPTIVE:
dict->SetString(kConfigModeKey, kConfigModePreemptive);
@@ -366,7 +366,7 @@ TraceConfig BackgroundTracingConfigImpl::GetConfigForCategoryPreset(
case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_SERVICEWORKER:
return TraceConfig(
"benchmark,toplevel,ipc,base,ServiceWorker,CacheStorage,Blob,"
- "loader,loading,navigation,blink.user_timing,"
+ "loading,mojom,navigation,renderer,blink,blink_gc,blink.user_timing,"
"disabled-by-default-network",
record_mode);
case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_POWER:
diff --git a/chromium/content/browser/tracing/background_tracing_config_impl.h b/chromium/content/browser/tracing/background_tracing_config_impl.h
index 9abb311aedd..2b35272ab0d 100644
--- a/chromium/content/browser/tracing/background_tracing_config_impl.h
+++ b/chromium/content/browser/tracing/background_tracing_config_impl.h
@@ -26,7 +26,7 @@ class CONTENT_EXPORT BackgroundTracingConfigImpl
~BackgroundTracingConfigImpl() override;
// From BackgroundTracingConfig
- void IntoDict(base::DictionaryValue* dict) const override;
+ void IntoDict(base::DictionaryValue* dict) override;
enum CategoryPreset {
CATEGORY_PRESET_UNSET,
diff --git a/chromium/content/browser/tracing/background_tracing_config_unittest.cc b/chromium/content/browser/tracing/background_tracing_config_unittest.cc
index a535f362e93..f568dbd5d39 100644
--- a/chromium/content/browser/tracing/background_tracing_config_unittest.cc
+++ b/chromium/content/browser/tracing/background_tracing_config_unittest.cc
@@ -37,7 +37,7 @@ std::unique_ptr<BackgroundTracingConfigImpl> ReadFromJSONString(
return config;
}
-std::string ConfigToString(const BackgroundTracingConfig* config) {
+std::string ConfigToString(BackgroundTracingConfig* config) {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
config->IntoDict(dict.get());
diff --git a/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc b/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
index 20cf874dd14..556bc8bc99c 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
@@ -16,7 +16,11 @@
#include "base/run_loop.h"
#include "base/strings/pattern.h"
#include "base/task/post_task.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/test_timeouts.h"
#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
+#include "content/browser/devtools/protocol/devtools_protocol_test_support.h"
#include "content/browser/tracing/background_startup_tracing_observer.h"
#include "content/browser/tracing/background_tracing_active_scenario.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
@@ -27,6 +31,8 @@
#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 "services/tracing/perfetto/privacy_filtering_check.h"
+#include "services/tracing/public/cpp/tracing_features.h"
#include "third_party/zlib/zlib.h"
using base::trace_event::TraceLog;
@@ -47,6 +53,21 @@ class TestStartupPreferenceManagerImpl
bool enabled_ = false;
};
+// Wait until |condition| returns true.
+void WaitForCondition(base::RepeatingCallback<bool()> condition,
+ const std::string& description) {
+ const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(30);
+ const base::TimeTicks start_time = base::TimeTicks::Now();
+ while (!condition.Run() && (base::TimeTicks::Now() - start_time < kTimeout)) {
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
+ run_loop.Run();
+ }
+ ASSERT_TRUE(condition.Run())
+ << "Timeout waiting for condition: " << description;
+}
+
// An helper class that observes tracing states transition and allows
// synchronisation with tests. The class adds itself as a tracelog
// enable state observer and provides methods to wait for a given state.
@@ -356,7 +377,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
handle, trigger_helper.receive_closure(true));
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -387,7 +408,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
handle, trigger_helper.receive_closure(false));
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -421,7 +442,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
trigger_helper.WaitForTriggerReceived();
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -436,8 +457,15 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
// the full WaitForTracingEnabled() callback (background tracing will directly
// enable the TraceLog so we get events prior to waiting for the whole IPC
// sequence to enable tracing coming back from the tracing service).
+// Temporarily disabled startup tracing on Android to be able to unblock
+// Perfetto-based background tracing: https://crbug.com/941318
+#if defined(OS_ANDROID)
+#define MAYBE_EarlyTraceEventsInTrace DISABLED_EarlyTraceEventsInTrace
+#else
+#define MAYBE_EarlyTraceEventsInTrace EarlyTraceEventsInTrace
+#endif
IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
- EarlyTraceEventsInTrace) {
+ MAYBE_EarlyTraceEventsInTrace) {
TestTraceReceiverHelper trace_receiver_helper;
TestBackgroundTracingHelper background_tracing_helper;
@@ -461,7 +489,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
trigger_helper.WaitForTriggerReceived();
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -492,7 +520,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
handle, trigger_helper.receive_closure(true));
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -531,7 +559,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
handle, trigger_helper.receive_closure(true));
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -590,7 +618,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
handle2, trigger_helper.receive_closure(false));
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -654,7 +682,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -697,7 +725,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
handle, trigger_helper.receive_closure(false));
// Abort the scenario.
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_FALSE(trace_receiver_helper.trace_received());
@@ -729,7 +757,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
handle, trigger_helper.receive_closure(false));
// Abort the scenario.
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_FALSE(trace_receiver_helper.trace_received());
@@ -775,7 +803,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
handle, trigger_helper.receive_closure(false));
// Abort the scenario.
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_FALSE(trace_receiver_helper.trace_received());
@@ -821,7 +849,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
trigger_helper.WaitForTriggerReceived();
// Abort the scenario.
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_FALSE(trace_receiver_helper.trace_received());
@@ -864,7 +892,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
LOCAL_HISTOGRAM_COUNTS("fake", 2);
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -909,7 +937,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
trace_receiver_helper.WaitForTraceReceived();
// Abort the scenario.
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -953,7 +981,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
LOCAL_HISTOGRAM_COUNTS("fake", 0);
// Abort the scenario.
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_FALSE(trace_receiver_helper.trace_received());
@@ -998,7 +1026,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
LOCAL_HISTOGRAM_COUNTS("fake", 0);
// Abort the scenario.
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_FALSE(trace_receiver_helper.trace_received());
@@ -1052,7 +1080,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
->FireTimerForTesting();
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -1082,7 +1110,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
handle, trigger_helper.receive_closure(true));
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -1127,7 +1155,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
EXPECT_TRUE(trace_receiver_helper.trace_received(1));
// Abort the scenario.
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
}
@@ -1192,7 +1220,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
handle1, trigger_helper.receive_closure(true));
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -1227,7 +1255,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
handle, trigger_helper.receive_closure(false));
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -1287,7 +1315,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
->FireTimerForTesting();
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
@@ -1335,7 +1363,7 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
EXPECT_TRUE(preferences->GetBackgroundStartupTracingEnabled());
// Abort the scenario.
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_FALSE(trace_receiver_helper.trace_received());
@@ -1394,11 +1422,92 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest, RunStartupTracing) {
->FireTimerForTesting();
trace_receiver_helper.WaitForTraceReceived();
- BackgroundTracingManager::GetInstance()->AbortScenario();
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
background_tracing_helper.WaitForScenarioAborted();
EXPECT_TRUE(trace_receiver_helper.trace_received());
EXPECT_FALSE(preferences->GetBackgroundStartupTracingEnabled());
}
+namespace {
+
+class ProtoBackgroundTracingTest : public DevToolsProtocolTest {
+ public:
+ ProtoBackgroundTracingTest() {
+ scoped_feature_list_.InitWithFeatures(
+ /*enabled_features=*/{features::kTracingPerfettoBackend,
+ features::kBackgroundTracingProtoOutput},
+ /*disabled_features=*/{});
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(ProtoBackgroundTracingTest,
+ DevtoolsInterruptsBackgroundTracing) {
+ TestBackgroundTracingHelper background_tracing_helper;
+ TestTraceReceiverHelper trace_receiver_helper;
+
+ std::unique_ptr<BackgroundTracingConfig> config = CreatePreemptiveConfig();
+
+ EXPECT_TRUE(BackgroundTracingManager::GetInstance()->SetActiveScenario(
+ std::move(config), trace_receiver_helper.get_receive_callback(),
+ BackgroundTracingManager::NO_DATA_FILTERING));
+
+ background_tracing_helper.WaitForTracingEnabled();
+
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+
+ base::Value* start_tracing_result =
+ SendCommand("Tracing.start", nullptr, true);
+ ASSERT_TRUE(start_tracing_result);
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
+ background_tracing_helper.WaitForScenarioAborted();
+}
+
+IN_PROC_BROWSER_TEST_F(ProtoBackgroundTracingTest, ProtoTraceReceived) {
+ TestBackgroundTracingHelper background_tracing_helper;
+
+ std::unique_ptr<BackgroundTracingConfig> config = CreatePreemptiveConfig();
+
+ BackgroundTracingManager::TriggerHandle handle =
+ BackgroundTracingManager::GetInstance()->RegisterTriggerType(
+ "preemptive_test");
+
+ EXPECT_TRUE(BackgroundTracingManager::GetInstance()->SetActiveScenario(
+ std::move(config), base::DoNothing(),
+ BackgroundTracingManager::NO_DATA_FILTERING));
+
+ background_tracing_helper.WaitForTracingEnabled();
+
+ TestTriggerHelper trigger_helper;
+ BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
+ handle, trigger_helper.receive_closure(true));
+
+ WaitForCondition(
+ base::BindRepeating([]() {
+ return BackgroundTracingManager::GetInstance()->HasTraceToUpload();
+ }),
+ "trace received");
+
+ std::string trace_data =
+ BackgroundTracingManager::GetInstance()->GetLatestTraceToUpload();
+
+ BackgroundTracingManager::GetInstance()->AbortScenarioForTesting();
+ background_tracing_helper.WaitForScenarioAborted();
+
+ tracing::PrivacyFilteringCheck checker;
+ checker.CheckProtoForUnexpectedFields(trace_data);
+ EXPECT_GT(checker.stats().track_event, 0u);
+ EXPECT_EQ(checker.stats().process_desc, 0u);
+ EXPECT_GT(checker.stats().thread_desc, 0u);
+ EXPECT_TRUE(checker.stats().has_interned_names);
+ EXPECT_TRUE(checker.stats().has_interned_categories);
+ EXPECT_TRUE(checker.stats().has_interned_source_locations);
+}
+
} // namespace content
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.cc b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
index 8bb32561368..0acb99c8c80 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
@@ -162,18 +162,19 @@ bool BackgroundTracingManagerImpl::HasActiveScenario() {
}
bool BackgroundTracingManagerImpl::HasTraceToUpload() {
- // TODO(oysteine): This should return the collected trace once we have the new
- // coordinator API to collect protos. https://crbug.com/925142.
- // Note: This can be called on any thread and needs to be thread safe.
- return !trace_to_upload_for_testing_.empty();
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return !trace_to_upload_.empty();
}
std::string BackgroundTracingManagerImpl::GetLatestTraceToUpload() {
- // TODO(oysteine): This should return the collected trace once we have the new
- // coordinator API to collect protos. https://crbug.com/925142.
- // Note: This can be called on any thread and needs to be thread safe.
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::string ret;
- ret.swap(trace_to_upload_for_testing_);
+ ret.swap(trace_to_upload_);
+
+ if (active_scenario_) {
+ active_scenario_->OnFinalizeComplete(true);
+ }
+
return ret;
}
@@ -241,8 +242,18 @@ bool BackgroundTracingManagerImpl::IsTracingForTesting() {
}
void BackgroundTracingManagerImpl::SetTraceToUploadForTesting(
- base::StringPiece data) {
- trace_to_upload_for_testing_ = data.data();
+ std::unique_ptr<std::string> trace_data) {
+ SetTraceToUpload(std::move(trace_data));
+}
+
+void BackgroundTracingManagerImpl::SetTraceToUpload(
+ std::unique_ptr<std::string> trace_data) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (trace_data) {
+ trace_to_upload_.swap(*trace_data);
+ } else {
+ trace_to_upload_.clear();
+ }
}
void BackgroundTracingManagerImpl::ValidateStartupScenario() {
@@ -368,6 +379,10 @@ BackgroundTracingManagerImpl::GenerateMetadataDict() {
return metadata_dict;
}
+void BackgroundTracingManagerImpl::AbortScenarioForTesting() {
+ AbortScenario();
+}
+
void BackgroundTracingManagerImpl::AbortScenario() {
if (active_scenario_) {
active_scenario_->AbortScenario();
@@ -377,7 +392,10 @@ void BackgroundTracingManagerImpl::AbortScenario() {
void BackgroundTracingManagerImpl::OnScenarioAborted() {
DCHECK(active_scenario_);
- active_scenario_.reset();
+ // Don't synchronously delete to avoid use-after-free issues in
+ // BackgroundTracingActiveScenario.
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
+ std::move(active_scenario_));
for (auto* observer : background_tracing_observers_) {
observer->OnScenarioAborted();
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.h b/chromium/content/browser/tracing/background_tracing_manager_impl.h
index 1c50eb5df14..b021c541bc4 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.h
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.h
@@ -78,7 +78,7 @@ class BackgroundTracingManagerImpl : public BackgroundTracingManager {
bool SetActiveScenario(std::unique_ptr<BackgroundTracingConfig>,
ReceiveCallback,
DataFiltering data_filtering) override;
- CONTENT_EXPORT void AbortScenario() override;
+ void AbortScenario();
bool HasActiveScenario() override;
// Named triggers
@@ -92,6 +92,7 @@ class BackgroundTracingManagerImpl : public BackgroundTracingManager {
StartedFinalizingCallback callback);
bool HasTraceToUpload() override;
std::string GetLatestTraceToUpload() override;
+ void SetTraceToUpload(std::unique_ptr<std::string> trace_data);
// Add/remove EnabledStateObserver.
CONTENT_EXPORT void AddEnabledStateObserver(EnabledStateObserver* observer);
@@ -116,9 +117,9 @@ class BackgroundTracingManagerImpl : public BackgroundTracingManager {
CONTENT_EXPORT void InvalidateTriggerHandlesForTesting();
CONTENT_EXPORT bool IsTracingForTesting();
void WhenIdle(IdleCallback idle_callback) override;
-
+ CONTENT_EXPORT void AbortScenarioForTesting() override;
CONTENT_EXPORT void SetTraceToUploadForTesting(
- base::StringPiece data) override;
+ std::unique_ptr<std::string> trace_data) override;
private:
friend class base::NoDestructor<BackgroundTracingManagerImpl>;
@@ -147,8 +148,9 @@ class BackgroundTracingManagerImpl : public BackgroundTracingManager {
IdleCallback idle_callback_;
base::RepeatingClosure tracing_enabled_callback_for_testing_;
+
// This field contains serialized trace log proto.
- std::string trace_to_upload_for_testing_;
+ std::string trace_to_upload_;
DISALLOW_COPY_AND_ASSIGN(BackgroundTracingManagerImpl);
};
diff --git a/chromium/content/browser/tracing/cast_tracing_agent.cc b/chromium/content/browser/tracing/cast_tracing_agent.cc
index 770f64c7910..1e485809a23 100644
--- a/chromium/content/browser/tracing/cast_tracing_agent.cc
+++ b/chromium/content/browser/tracing/cast_tracing_agent.cc
@@ -16,7 +16,8 @@
#include "chromecast/tracing/system_tracing_common.h"
#include "content/public/browser/browser_thread.h"
#include "services/service_manager/public/cpp/connector.h"
-#include "services/tracing/public/cpp/perfetto/producer_client.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_producer.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
#include "services/tracing/public/mojom/constants.mojom.h"
#include "services/tracing/public/mojom/perfetto_service.mojom.h"
#include "third_party/perfetto/include/perfetto/tracing/core/trace_writer.h"
@@ -155,21 +156,21 @@ namespace {
using ChromeEventBundleHandle =
protozero::MessageHandle<perfetto::protos::pbzero::ChromeEventBundle>;
-class CastDataSource : public tracing::ProducerClient::DataSourceBase {
+class CastDataSource : public tracing::PerfettoTracedProcess::DataSourceBase {
public:
static CastDataSource* GetInstance() {
static base::NoDestructor<CastDataSource> instance;
return instance.get();
}
- // Called from the tracing::ProducerClient on its sequence.
+ // Called from the tracing::PerfettoProducer on its sequence.
void StartTracing(
- tracing::ProducerClient* producer_client,
+ tracing::PerfettoProducer* producer,
const perfetto::DataSourceConfig& data_source_config) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(perfetto_sequence_checker_);
- DCHECK(!producer_client_);
+ DCHECK(!producer_);
DCHECK(!session_);
- producer_client_ = producer_client;
+ producer_ = producer;
target_buffer_ = data_source_config.target_buffer();
session_ = std::make_unique<CastSystemTracingSession>(worker_task_runner_);
session_->StartTracing(data_source_config.chrome_config().trace_config(),
@@ -177,10 +178,10 @@ class CastDataSource : public tracing::ProducerClient::DataSourceBase {
base::Unretained(this)));
}
- // Called from the tracing::ProducerClient on its sequence.
+ // Called from the tracing::PerfettoProducer on its sequence.
void StopTracing(base::OnceClosure stop_complete_callback) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(perfetto_sequence_checker_);
- DCHECK(producer_client_);
+ DCHECK(producer_);
DCHECK(session_);
if (!session_started_) {
session_started_callback_ =
@@ -189,7 +190,7 @@ class CastDataSource : public tracing::ProducerClient::DataSourceBase {
return;
}
- trace_writer_ = producer_client_->CreateTraceWriter(target_buffer_);
+ trace_writer_ = producer_->CreateTraceWriter(target_buffer_);
DCHECK(trace_writer_);
stop_complete_callback_ = std::move(stop_complete_callback);
session_->StopTracing(base::BindRepeating(&CastDataSource::OnTraceData,
@@ -242,7 +243,7 @@ class CastDataSource : public tracing::ProducerClient::DataSourceBase {
trace_writer_.reset();
session_.reset();
session_started_ = false;
- producer_client_ = nullptr;
+ producer_ = nullptr;
std::move(stop_complete_callback_).Run();
}
}
@@ -258,7 +259,7 @@ class CastDataSource : public tracing::ProducerClient::DataSourceBase {
std::unique_ptr<perfetto::TraceWriter> trace_writer_;
base::OnceClosure stop_complete_callback_;
uint32_t target_buffer_ = 0;
- tracing::ProducerClient* producer_client_ = nullptr;
+ tracing::PerfettoProducer* producer_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(CastDataSource);
};
@@ -272,7 +273,8 @@ CastTracingAgent::CastTracingAgent()
worker_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {
- tracing::ProducerClient::Get()->AddDataSource(CastDataSource::GetInstance());
+ tracing::PerfettoTracedProcess::Get()->AddDataSource(
+ CastDataSource::GetInstance());
}
CastTracingAgent::~CastTracingAgent() = default;
diff --git a/chromium/content/browser/tracing/cros_tracing_agent.cc b/chromium/content/browser/tracing/cros_tracing_agent.cc
index e6d179ea598..60de0dbf345 100644
--- a/chromium/content/browser/tracing/cros_tracing_agent.cc
+++ b/chromium/content/browser/tracing/cros_tracing_agent.cc
@@ -19,7 +19,8 @@
#include "chromeos/dbus/debug_daemon_client.h"
#include "content/public/browser/browser_task_traits.h"
#include "services/service_manager/public/cpp/connector.h"
-#include "services/tracing/public/cpp/perfetto/producer_client.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_producer.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
#include "services/tracing/public/mojom/constants.mojom.h"
#include "services/tracing/public/mojom/perfetto_service.mojom.h"
#include "third_party/perfetto/include/perfetto/tracing/core/trace_writer.h"
@@ -92,25 +93,25 @@ namespace {
using ChromeEventBundleHandle =
protozero::MessageHandle<perfetto::protos::pbzero::ChromeEventBundle>;
-class CrOSDataSource : public tracing::ProducerClient::DataSourceBase {
+class CrOSDataSource : public tracing::PerfettoTracedProcess::DataSourceBase {
public:
static CrOSDataSource* GetInstance() {
static base::NoDestructor<CrOSDataSource> instance;
return instance.get();
}
- // Called from the tracing::ProducerClient on its sequence.
+ // Called from the tracing::PerfettoProducer on its sequence.
void StartTracing(
- tracing::ProducerClient* producer_client,
+ tracing::PerfettoProducer* perfetto_producer,
const perfetto::DataSourceConfig& data_source_config) override {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&CrOSDataSource::StartTracingOnUI,
- base::Unretained(this), producer_client,
+ base::Unretained(this), perfetto_producer,
data_source_config));
}
- // Called from the tracing::ProducerClient on its sequence.
+ // Called from the tracing::PerfettoProducer on its sequence.
void StopTracing(base::OnceClosure stop_complete_callback) override {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
@@ -131,12 +132,12 @@ class CrOSDataSource : public tracing::ProducerClient::DataSourceBase {
DETACH_FROM_SEQUENCE(ui_sequence_checker_);
}
- void StartTracingOnUI(tracing::ProducerClient* producer_client,
+ void StartTracingOnUI(tracing::PerfettoProducer* producer,
const perfetto::DataSourceConfig& data_source_config) {
DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
- DCHECK(!producer_client_);
+ DCHECK(!producer_);
DCHECK(!session_);
- producer_client_ = producer_client;
+ producer_ = producer;
target_buffer_ = data_source_config.target_buffer();
session_ = std::make_unique<CrOSSystemTracingSession>();
session_->StartTracing(
@@ -154,7 +155,7 @@ class CrOSDataSource : public tracing::ProducerClient::DataSourceBase {
void StopTracingOnUI(base::OnceClosure stop_complete_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
- DCHECK(producer_client_);
+ DCHECK(producer_);
DCHECK(session_);
if (!session_started_) {
on_session_started_callback_ =
@@ -173,7 +174,7 @@ class CrOSDataSource : public tracing::ProducerClient::DataSourceBase {
const scoped_refptr<base::RefCountedString>& events) {
if (events && !events->data().empty()) {
std::unique_ptr<perfetto::TraceWriter> trace_writer =
- producer_client_->CreateTraceWriter(target_buffer_);
+ producer_->CreateTraceWriter(target_buffer_);
DCHECK(trace_writer);
{
perfetto::TraceWriter::TracePacketHandle trace_packet_handle =
@@ -195,13 +196,14 @@ class CrOSDataSource : public tracing::ProducerClient::DataSourceBase {
void OnTraceDataOnUI(base::OnceClosure stop_complete_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
- auto* producer_client = producer_client_;
session_.reset();
session_started_ = false;
- producer_client_ = nullptr;
+ producer_ = nullptr;
- producer_client->GetTaskRunner()->task_runner()->PostTask(
- FROM_HERE, std::move(stop_complete_callback));
+ tracing::PerfettoTracedProcess::Get()
+ ->GetTaskRunner()
+ ->GetOrCreateTaskRunner()
+ ->PostTask(FROM_HERE, std::move(stop_complete_callback));
}
SEQUENCE_CHECKER(ui_sequence_checker_);
@@ -209,7 +211,7 @@ class CrOSDataSource : public tracing::ProducerClient::DataSourceBase {
bool session_started_ = false;
base::OnceClosure on_session_started_callback_;
uint32_t target_buffer_ = 0;
- tracing::ProducerClient* producer_client_ = nullptr;
+ tracing::PerfettoProducer* producer_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(CrOSDataSource);
};
@@ -220,7 +222,8 @@ CrOSTracingAgent::CrOSTracingAgent()
: BaseAgent(tracing::mojom::kSystemTraceEventLabel,
tracing::mojom::TraceDataType::STRING,
base::kNullProcessId) {
- tracing::ProducerClient::Get()->AddDataSource(CrOSDataSource::GetInstance());
+ tracing::PerfettoTracedProcess::Get()->AddDataSource(
+ CrOSDataSource::GetInstance());
}
CrOSTracingAgent::~CrOSTracingAgent() = default;
diff --git a/chromium/content/browser/tracing/memory_tracing_browsertest.cc b/chromium/content/browser/tracing/memory_tracing_browsertest.cc
index a6f027b9a6f..395c4b62bd3 100644
--- a/chromium/content/browser/tracing/memory_tracing_browsertest.cc
+++ b/chromium/content/browser/tracing/memory_tracing_browsertest.cc
@@ -80,7 +80,7 @@ class MemoryTracingTest : public ContentBrowserTest {
&MemoryTracingTest::OnGlobalMemoryDumpDone, base::Unretained(this),
base::ThreadTaskRunnerHandle::Get(), closure, request_index);
if (from_renderer_thread) {
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&memory_instrumentation::MemoryInstrumentation::
RequestGlobalDumpAndAppendToTrace,
base::Unretained(
diff --git a/chromium/content/browser/tracing/perfetto_file_tracer.cc b/chromium/content/browser/tracing/perfetto_file_tracer.cc
index b977c4dc573..2f2f3f7b24b 100644
--- a/chromium/content/browser/tracing/perfetto_file_tracer.cc
+++ b/chromium/content/browser/tracing/perfetto_file_tracer.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/task/post_task.h"
#include "base/threading/scoped_blocking_call.h"
#include "components/tracing/common/trace_startup_config.h"
@@ -16,6 +17,7 @@
#include "content/public/common/service_manager_connection.h"
#include "mojo/public/cpp/system/data_pipe_drainer.h"
#include "services/service_manager/public/cpp/connector.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_config.h"
#include "services/tracing/public/mojom/constants.mojom.h"
#include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h"
#include "third_party/perfetto/protos/perfetto/config/trace_config.pb.h"
@@ -83,51 +85,34 @@ PerfettoFileTracer::PerfettoFileTracer()
: background_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
- background_drainer_(background_task_runner_),
- binding_(this),
- weak_factory_(this) {
+ background_drainer_(background_task_runner_) {
ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
tracing::mojom::kServiceName, &consumer_host_);
- perfetto::TraceConfig trace_config;
+ const auto& chrome_config =
+ tracing::TraceStartupConfig::GetInstance()->GetTraceConfig();
+ // The output is always proto based. So, enable privacy filtering if argument
+ // filter is enabled.
+ bool privacy_filtering = chrome_config.IsArgumentFilterEnabled();
+ perfetto::TraceConfig trace_config =
+ tracing::GetDefaultPerfettoConfig(chrome_config, privacy_filtering);
+
int duration_in_seconds =
tracing::TraceStartupConfig::GetInstance()->GetStartupDuration();
trace_config.set_duration_ms(duration_in_seconds * 1000);
// We just need a single global trace buffer, for our data.
- trace_config.add_buffers()->set_size_kb(32 * 1024);
-
- // We need data from two different sources to get the complete trace
- // we're interested in both, written into the single buffer we
- // configure above.
-
- // This source is the actual trace events themselves coming
- // from the base::TraceLog
- auto* trace_event_config = trace_config.add_data_sources()->mutable_config();
- trace_event_config->set_name(tracing::mojom::kTraceEventDataSourceName);
- trace_event_config->set_target_buffer(0);
- auto* chrome_config = trace_event_config->mutable_chrome_config();
-
- // The Chrome config string is passed straight through to base::TraceLog
- // and defines which tracing categories should be enabled.
- auto chrome_raw_config =
- tracing::TraceStartupConfig::GetInstance()->GetTraceConfig().ToString();
- chrome_config->set_trace_config(chrome_raw_config);
-
- // The second data source we're interested in is the global metadata.
- auto* trace_metadata_config =
- trace_config.add_data_sources()->mutable_config();
- trace_metadata_config->set_name(tracing::mojom::kMetaDataSourceName);
- trace_metadata_config->set_target_buffer(0);
-
- tracing::mojom::TracingSessionPtr tracing_session;
- binding_.Bind(mojo::MakeRequest(&tracing_session));
+ trace_config.mutable_buffers()->front().set_size_kb(32 * 1024);
+
+ tracing::mojom::TracingSessionClientPtr tracing_session_client;
+ binding_.Bind(mojo::MakeRequest(&tracing_session_client));
binding_.set_connection_error_handler(base::BindOnce(
&PerfettoFileTracer::OnTracingSessionEnded, base::Unretained(this)));
- consumer_host_->EnableTracing(std::move(tracing_session),
- std::move(trace_config));
-
+ consumer_host_->EnableTracing(
+ mojo::MakeRequest(&tracing_session_host_),
+ std::move(tracing_session_client), std::move(trace_config),
+ tracing::mojom::TracingClientPriority::kBackground);
ReadBuffers();
}
@@ -135,6 +120,10 @@ PerfettoFileTracer::~PerfettoFileTracer() = default;
void PerfettoFileTracer::OnTracingEnabled() {}
+void PerfettoFileTracer::OnTracingDisabled() {
+ has_been_disabled_ = true;
+}
+
void PerfettoFileTracer::OnNoMorePackets(bool queued_after_disable) {
DCHECK(consumer_host_);
// If this callback happens as the result of a ReadBuffers() call
@@ -158,7 +147,7 @@ void PerfettoFileTracer::ReadBuffers() {
DCHECK(consumer_host_);
mojo::DataPipe data_pipe;
- consumer_host_->ReadBuffers(
+ tracing_session_host_->ReadBuffers(
std::move(data_pipe.producer_handle),
base::BindOnce(
[](PerfettoFileTracer* file_tracing, bool queued_after_disable) {
@@ -171,7 +160,8 @@ void PerfettoFileTracer::ReadBuffers() {
}
void PerfettoFileTracer::OnTracingSessionEnded() {
- has_been_disabled_ = true;
+ binding_.Close();
+ tracing_session_host_.reset();
}
} // namespace content
diff --git a/chromium/content/browser/tracing/perfetto_file_tracer.h b/chromium/content/browser/tracing/perfetto_file_tracer.h
index e6ca8ac77f1..b53993b60de 100644
--- a/chromium/content/browser/tracing/perfetto_file_tracer.h
+++ b/chromium/content/browser/tracing/perfetto_file_tracer.h
@@ -23,15 +23,18 @@ class BackgroundDrainer;
// as the backend, rather than TraceLog. It will directly stream
// protos to a file specified with the '--perfetto-output-file'
// switch.
-class PerfettoFileTracer : public tracing::mojom::TracingSession {
+class PerfettoFileTracer : public tracing::mojom::TracingSessionClient {
public:
PerfettoFileTracer();
~PerfettoFileTracer() override;
static bool ShouldEnable();
- // tracing::mojom::TracingSession implementation:
+ // tracing::mojom::TracingSessionClient implementation:
void OnTracingEnabled() override;
+ void OnTracingDisabled() override;
+
+ bool is_finished_for_testing() const { return !background_drainer_; }
private:
void OnNoMorePackets(bool queued_after_disable);
@@ -41,11 +44,12 @@ class PerfettoFileTracer : public tracing::mojom::TracingSession {
const scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
base::SequenceBound<BackgroundDrainer> background_drainer_;
- mojo::Binding<tracing::mojom::TracingSession> binding_;
+ mojo::Binding<tracing::mojom::TracingSessionClient> binding_{this};
+ tracing::mojom::TracingSessionHostPtr tracing_session_host_;
tracing::mojom::ConsumerHostPtr consumer_host_;
bool has_been_disabled_ = false;
- base::WeakPtrFactory<PerfettoFileTracer> weak_factory_;
+ base::WeakPtrFactory<PerfettoFileTracer> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PerfettoFileTracer);
};
diff --git a/chromium/content/browser/tracing/startup_tracing_browsertest.cc b/chromium/content/browser/tracing/startup_tracing_browsertest.cc
index 2bda79444e5..e067ff1f74f 100644
--- a/chromium/content/browser/tracing/startup_tracing_browsertest.cc
+++ b/chromium/content/browser/tracing/startup_tracing_browsertest.cc
@@ -4,16 +4,21 @@
#include "base/files/file_util.h"
#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/tracing/common/trace_startup_config.h"
#include "components/tracing/common/tracing_switches.h"
-#include "content/public/browser/tracing_controller.h"
+#include "content/browser/tracing/perfetto_file_tracer.h"
+#include "content/browser/tracing/tracing_controller_impl.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "services/tracing/perfetto/privacy_filtering_check.h"
+#include "services/tracing/public/cpp/perfetto/trace_event_data_source.h"
#include "services/tracing/public/cpp/trace_startup.h"
+#include "services/tracing/public/cpp/tracing_features.h"
namespace content {
@@ -22,7 +27,7 @@ namespace {
// Wait until |condition| returns true.
void WaitForCondition(base::RepeatingCallback<bool()> condition,
const std::string& description) {
- const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(30);
+ const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(15);
const base::TimeTicks start_time = base::TimeTicks::Now();
while (!condition.Run() && (base::TimeTicks::Now() - start_time < kTimeout)) {
base::RunLoop run_loop;
@@ -36,7 +41,10 @@ void WaitForCondition(base::RepeatingCallback<bool()> condition,
} // namespace
-class StartupTracingControllerTest : public ContentBrowserTest {
+class CommandlineStartupTracingTest : public ContentBrowserTest {
+ public:
+ CommandlineStartupTracingTest() = default;
+
void SetUpCommandLine(base::CommandLine* command_line) override {
base::CreateTemporaryFile(&temp_file_path_);
command_line->AppendSwitch(switches::kTraceStartup);
@@ -55,10 +63,13 @@ class StartupTracingControllerTest : public ContentBrowserTest {
protected:
base::FilePath temp_file_path_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CommandlineStartupTracingTest);
};
-IN_PROC_BROWSER_TEST_F(StartupTracingControllerTest, TestStartupTracing) {
- NavigateToURL(shell(), GetTestUrl("", "title.html"));
+IN_PROC_BROWSER_TEST_F(CommandlineStartupTracingTest, TestStartupTracing) {
+ NavigateToURL(shell(), GetTestUrl("", "title1.html"));
WaitForCondition(base::BindRepeating([]() {
return !TracingController::GetInstance()->IsTracing();
}),
@@ -79,4 +90,122 @@ IN_PROC_BROWSER_TEST_F(StartupTracingControllerTest, TestStartupTracing) {
std::string::npos);
}
+class StartupTracingInProcessTest : public ContentBrowserTest {
+ public:
+ StartupTracingInProcessTest() {
+ scoped_feature_list_.InitWithFeatures(
+ /*enabled_features=*/{features::kTracingPerfettoBackend,
+ features::kTracingServiceInProcess},
+ /*disabled_features=*/{});
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+class LargeTraceEventData : public base::trace_event::ConvertableToTraceFormat {
+ public:
+ LargeTraceEventData() = default;
+ ~LargeTraceEventData() override = default;
+
+ const size_t kLargeMessageSize = 100 * 1024;
+ void AppendAsTraceFormat(std::string* out) const override {
+ std::string large_string(kLargeMessageSize, '.');
+ out->append(large_string);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LargeTraceEventData);
+};
+
+// This will fill a massive amount of startup tracing data into a
+// StartupTraceWriter, which Perfetto will then have to sync copy into
+// the SMB once the full tracing service starts up. This is to catch common
+// deadlocks.
+IN_PROC_BROWSER_TEST_F(StartupTracingInProcessTest,
+ DISABLED_TestFilledStartupBuffer) {
+ tracing::TraceEventDataSource::GetInstance()->SetupStartupTracing(
+ /*privacy_filtering_enabled=*/false);
+
+ auto config = tracing::TraceStartupConfig::GetInstance()
+ ->GetDefaultBrowserStartupConfig();
+ uint8_t modes = base::trace_event::TraceLog::RECORDING_MODE;
+ base::trace_event::TraceLog::GetInstance()->SetEnabled(config, modes);
+
+ for (int i = 0; i < 1024; ++i) {
+ auto data = std::make_unique<LargeTraceEventData>();
+ TRACE_EVENT1("toplevel", "bar", "data", std::move(data));
+ }
+
+ config.SetTraceBufferSizeInKb(12);
+
+ base::RunLoop wait_for_tracing;
+ TracingControllerImpl::GetInstance()->StartTracing(
+ config, wait_for_tracing.QuitClosure());
+ wait_for_tracing.Run();
+
+ NavigateToURL(shell(), GetTestUrl("", "title1.html"));
+
+ base::RunLoop wait_for_stop;
+ TracingControllerImpl::GetInstance()->StopTracing(
+ TracingController::CreateStringEndpoint(base::BindRepeating(
+ [](base::RepeatingClosure quit_callback,
+ std::unique_ptr<const base::DictionaryValue> metadata,
+ base::RefCountedString* data) { quit_callback.Run(); },
+ wait_for_stop.QuitClosure())));
+ wait_for_stop.Run();
+}
+
+class BackgroundStartupTracingTest : public ContentBrowserTest {
+ public:
+ BackgroundStartupTracingTest() = default;
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ base::CreateTemporaryFile(&temp_file_path_);
+ auto* startup_config = tracing::TraceStartupConfig::GetInstance();
+ startup_config->is_enabled_from_background_tracing_ = true;
+ startup_config->EnableFromBackgroundTracing();
+ startup_config->startup_duration_ = 3;
+ tracing::EnableStartupTracingIfNeeded();
+ command_line->AppendSwitchASCII(switches::kPerfettoOutputFile,
+ temp_file_path_.AsUTF8Unsafe());
+ }
+
+ protected:
+ base::FilePath temp_file_path_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BackgroundStartupTracingTest);
+};
+
+#if !defined(OS_ANDROID)
+#define MAYBE_TestStartupTracing DISABLED_TestStartupTracing
+#else
+#define MAYBE_TestStartupTracing TestStartupTracing
+#endif
+IN_PROC_BROWSER_TEST_F(BackgroundStartupTracingTest, MAYBE_TestStartupTracing) {
+ NavigateToURL(shell(), GetTestUrl("", "title1.html"));
+
+ EXPECT_FALSE(tracing::TraceStartupConfig::GetInstance()->IsEnabled());
+ EXPECT_FALSE(TracingController::GetInstance()->IsTracing());
+ WaitForCondition(base::BindRepeating([]() {
+ return TracingControllerImpl::GetInstance()
+ ->perfetto_file_tracer_for_testing()
+ ->is_finished_for_testing();
+ }),
+ "finish file write");
+
+ std::string trace;
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ ASSERT_TRUE(base::ReadFileToString(temp_file_path_, &trace));
+ tracing::PrivacyFilteringCheck checker;
+ checker.CheckProtoForUnexpectedFields(trace);
+ EXPECT_GT(checker.stats().track_event, 0u);
+ EXPECT_EQ(checker.stats().process_desc, 0u);
+ EXPECT_GT(checker.stats().thread_desc, 0u);
+ EXPECT_TRUE(checker.stats().has_interned_names);
+ EXPECT_TRUE(checker.stats().has_interned_categories);
+ EXPECT_TRUE(checker.stats().has_interned_source_locations);
+}
+
} // namespace content
diff --git a/chromium/content/browser/tracing/tracing_controller_browsertest.cc b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
index e46520c5587..e9a1ea0219d 100644
--- a/chromium/content/browser/tracing/tracing_controller_browsertest.cc
+++ b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
@@ -493,4 +493,10 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, MAYBE_SystemTraceEvents) {
EXPECT_TRUE(last_data().find("systemTraceEvents") != std::string::npos);
}
+IN_PROC_BROWSER_TEST_F(TracingControllerTest, ProcessesPresentInTrace) {
+ TestStartAndStopTracingString();
+ EXPECT_TRUE(last_data().find("CrBrowserMain") != std::string::npos);
+ EXPECT_TRUE(last_data().find("CrRendererMain") != std::string::npos);
+}
+
} // namespace content
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.cc b/chromium/content/browser/tracing/tracing_controller_impl.cc
index d6bf5bfb5d0..c7d2b04ebc0 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl.cc
@@ -470,7 +470,7 @@ void TracingControllerImpl::FinalizeStartupTracingIfNeeded() {
// complete. See also crbug.com/944107.
// TODO(eseckler): Avoid the nestedRunLoop here somehow.
base::RunLoop run_loop;
- StopTracing(CreateFileEndpoint(
+ bool success = StopTracing(CreateFileEndpoint(
startup_trace_file.value(),
base::BindRepeating(
[](base::FilePath trace_file, base::OnceClosure quit_closure) {
@@ -478,6 +478,8 @@ void TracingControllerImpl::FinalizeStartupTracingIfNeeded() {
std::move(quit_closure).Run();
},
startup_trace_file.value(), run_loop.QuitClosure())));
+ if (!success)
+ return;
run_loop.Run();
}
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.h b/chromium/content/browser/tracing/tracing_controller_impl.h
index 58242048fee..c91a3b73315 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.h
+++ b/chromium/content/browser/tracing/tracing_controller_impl.h
@@ -84,6 +84,10 @@ class TracingControllerImpl : public TracingController,
// exists.
void FinalizeStartupTracingIfNeeded();
+ const PerfettoFileTracer* perfetto_file_tracer_for_testing() const {
+ return perfetto_file_tracer_.get();
+ }
+
private:
friend std::default_delete<TracingControllerImpl>;
diff --git a/chromium/content/browser/tracing/tracing_ui.cc b/chromium/content/browser/tracing/tracing_ui.cc
index 76826b167de..4d305f53520 100644
--- a/chromium/content/browser/tracing/tracing_ui.cc
+++ b/chromium/content/browser/tracing/tracing_ui.cc
@@ -177,12 +177,6 @@ TracingUI::TracingUI(WebUI* web_ui)
web_ui->GetWebContents()->GetBrowserContext();
WebUIDataSource* source = WebUIDataSource::Create(kChromeUITracingHost);
- source->UseGzip(base::BindRepeating([](const std::string& path) {
- return path != "json/begin_recording" && path != "json/categories" &&
- path != "json/end_recording_compressed" &&
- path != "json/get_buffer_percent_full" &&
- path != "json/get_buffer_status";
- }));
source->SetJsonPath("strings.js");
source->SetDefaultResource(IDR_TRACING_HTML);
source->AddResourcePath("tracing.js", IDR_TRACING_JS);
diff --git a/chromium/content/browser/url_loader_factory_getter.cc b/chromium/content/browser/url_loader_factory_getter.cc
index 34380861e71..9b1c3e1b7a1 100644
--- a/chromium/content/browser/url_loader_factory_getter.cc
+++ b/chromium/content/browser/url_loader_factory_getter.cc
@@ -58,7 +58,8 @@ class URLLoaderFactoryGetter::URLLoaderFactoryForIOThread
bool is_corb_enabled)
: factory_getter_(std::move(factory_getter)),
is_corb_enabled_(is_corb_enabled) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO) ||
+ BrowserThread::CurrentlyOn(BrowserThread::IO));
}
explicit URLLoaderFactoryForIOThread(
@@ -167,7 +168,8 @@ URLLoaderFactoryGetter::GetNetworkFactory() {
scoped_refptr<network::SharedURLLoaderFactory>
URLLoaderFactoryGetter::GetNetworkFactoryWithCORBEnabled() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO) ||
+ BrowserThread::CurrentlyOn(BrowserThread::IO));
return base::MakeRefCounted<URLLoaderFactoryForIOThread>(
base::WrapRefCounted(this), true);
}
diff --git a/chromium/content/browser/utility_process_host.cc b/chromium/content/browser/utility_process_host.cc
index 56f8ef5d1f3..bec943a4229 100644
--- a/chromium/content/browser/utility_process_host.cc
+++ b/chromium/content/browser/utility_process_host.cc
@@ -376,6 +376,7 @@ bool UtilityProcessHost::StartProcess() {
network::switches::kIgnoreCertificateErrorsSPKIList,
network::switches::kIgnoreUrlFetcherCertRequests,
network::switches::kLogNetLog,
+ network::switches::kNetLogCaptureMode,
network::switches::kNoReferrers,
network::switches::kExplicitlyAllowedPorts,
service_manager::switches::kNoSandbox,
@@ -397,13 +398,13 @@ bool UtilityProcessHost::StartProcess() {
switches::kUseFakeMjpegDecodeAccelerator,
switches::kUseFileForFakeVideoCapture,
switches::kUseMockCertVerifierForTesting,
+ switches::kMockCertVerifierDefaultResultForTesting,
switches::kUtilityStartupDialog,
switches::kUseGL,
switches::kV,
switches::kVModule,
#if defined(OS_ANDROID)
switches::kEnableReachedCodeProfiler,
- switches::kOrderfileMemoryOptimization,
#endif
// These flags are used by the audio service:
switches::kAudioBufferSize,
diff --git a/chromium/content/browser/wake_lock/wake_lock_browsertest.cc b/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
deleted file mode 100644
index c60c4565a47..00000000000
--- a/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
+++ /dev/null
@@ -1,401 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/run_loop.h"
-#include "base/test/test_timeouts.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/content_browser_test.h"
-#include "content/public/test/content_browser_test_utils.h"
-#include "content/public/test/test_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"
-
-namespace content {
-
-namespace {
-
-const char kBlinkWakeLockFeature[] = "WakeLock";
-
-void OnHasWakeLock(bool* out, bool has_wakelock) {
- *out = has_wakelock;
- base::RunLoop::QuitCurrentDeprecated();
-}
-
-} // namespace
-
-class WakeLockTest : public ContentBrowserTest {
- public:
- void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
- kBlinkWakeLockFeature);
- command_line->AppendSwitch(switches::kSitePerProcess);
- }
-
- void SetUpOnMainThread() override {
- host_resolver()->AddRule("*", "127.0.0.1");
- EXPECT_TRUE(embedded_test_server()->Start());
- // To prevent occlusion events from changing page visibility.
- GetWebContents()->IncrementCapturerCount(gfx::Size());
- }
-
- void TearDownOnMainThread() override {
- GetWebContents()->DecrementCapturerCount();
- }
-
- protected:
- WebContents* GetWebContents() { return shell()->web_contents(); }
-
- WebContentsImpl* GetWebContentsImpl() {
- return static_cast<WebContentsImpl*>(GetWebContents());
- }
-
- RenderFrameHost* GetMainFrame() { return GetWebContents()->GetMainFrame(); }
-
- FrameTreeNode* GetNestedFrameNode() {
- FrameTreeNode* root = GetWebContentsImpl()->GetFrameTree()->root();
- CHECK_EQ(1U, root->child_count());
- return root->child_at(0);
- }
-
- RenderFrameHost* GetNestedFrame() {
- return GetNestedFrameNode()->current_frame_host();
- }
-
- device::mojom::WakeLock* GetRendererWakeLock() {
- return GetWebContentsImpl()->GetRendererWakeLock();
- }
-
- bool HasWakeLock() {
- bool has_wakelock = false;
- base::RunLoop run_loop;
-
- GetRendererWakeLock()->HasWakeLockForTests(
- base::BindOnce(&OnHasWakeLock, &has_wakelock));
- run_loop.Run();
- return has_wakelock;
- }
-
- void WaitForPossibleUpdate() {
- // As Mojo channels have no common FIFO order in respect to each other and
- // to the Chromium IPC, we cannot assume that when screen.keepAwake state
- // is changed from within a script, mojom::WakeLock will receive an
- // update request before ExecuteScript() returns. Therefore, some time slack
- // is needed to make sure that mojom::WakeLock has received any
- // possible update requests before checking the resulting wake lock state.
- base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- RunAllPendingInMessageLoop();
- }
-
- void ScreenWakeLockInMainFrame() {
- EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = true;"));
- WaitForPossibleUpdate();
- EXPECT_TRUE(HasWakeLock());
- }
-
- bool EvaluateAsBool(const ToRenderFrameHost& adapter,
- const std::string& expr) {
- bool result;
- CHECK(ExecuteScriptAndExtractBool(
- adapter, "window.domAutomationController.send(" + expr + ");",
- &result));
- return result;
- }
-};
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, WakeLockApiIsPresent) {
- NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html"));
- EXPECT_TRUE(
- EvaluateAsBool(GetMainFrame(), "typeof screen.keepAwake !== undefined"));
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, LockAndUnlockScreenInMainFrame) {
- NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html"));
-
- // Should not have screen wake lock initially.
- EXPECT_FALSE(HasWakeLock());
-
- // Check attribute 'screen.keepAwake' in main frame.
- EXPECT_FALSE(EvaluateAsBool(GetMainFrame(), "screen.keepAwake"));
-
- // Set keep awake flag in main frame.
- EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = true;"));
- WaitForPossibleUpdate();
-
- // Keep awake flag should be set in main frame.
- EXPECT_TRUE(EvaluateAsBool(GetMainFrame(), "screen.keepAwake"));
-
- // Should create screen wake lock.
- EXPECT_TRUE(HasWakeLock());
-
- // Reset keep awake flag in main frame.
- EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = false;"));
- WaitForPossibleUpdate();
-
- // Keep awake flag should not be set in main frame.
- EXPECT_FALSE(EvaluateAsBool(GetMainFrame(), "screen.keepAwake"));
-
- // Should release screen wake lock.
- EXPECT_FALSE(HasWakeLock());
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, MultipleLockThenUnlock) {
- NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html"));
-
- // Set keep awake flag.
- EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = true;"));
- WaitForPossibleUpdate();
-
- // Set keep awake flag again.
- EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = true;"));
- WaitForPossibleUpdate();
-
- // Screen should still be locked.
- EXPECT_TRUE(HasWakeLock());
-
- // Reset keep awake flag.
- EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = false;"));
- WaitForPossibleUpdate();
-
- // Should release screen wake lock.
- EXPECT_FALSE(HasWakeLock());
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, LockInMainFrameAndNestedFrame) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/frame_tree/2-4.html"));
- EXPECT_FALSE(HasWakeLock());
-
- // Lock screen in nested frame.
- EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;"));
- WaitForPossibleUpdate();
-
- // Should create screen wake lock.
- EXPECT_TRUE(HasWakeLock());
-
- // screen.keepAwake should be false in the main frame.
- EXPECT_FALSE(EvaluateAsBool(GetMainFrame(), "screen.keepAwake"));
-
- // Lock screen in main frame.
- EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = true;"));
- WaitForPossibleUpdate();
-
- // screen.keepAwake should be true in the main frame.
- EXPECT_TRUE(EvaluateAsBool(GetMainFrame(), "screen.keepAwake"));
-
- // Screen wake lock should not change.
- EXPECT_TRUE(HasWakeLock());
-
- // Unlock screen in nested frame.
- EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = false;"));
- WaitForPossibleUpdate();
-
- // Screen wake lock should be present, as the main frame is still requesting
- // it.
- EXPECT_TRUE(HasWakeLock());
-
- // Unlock screen in main frame.
- EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = false;"));
- WaitForPossibleUpdate();
-
- // Screen wake lock should be released, as no frames are requesting it.
- EXPECT_FALSE(HasWakeLock());
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, FrameRemoved) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/frame_tree/2-4.html"));
- EXPECT_FALSE(HasWakeLock());
-
- // Lock screen in nested frame.
- EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;"));
- WaitForPossibleUpdate();
-
- EXPECT_TRUE(HasWakeLock());
-
- // Remove nested frame.
- EXPECT_TRUE(ExecuteScript(GetMainFrame(),
- "var iframe = document.getElementById('3-1-id');"
- "iframe.parentNode.removeChild(iframe);"));
-
- // Screen wake lock should be released.
- EXPECT_FALSE(HasWakeLock());
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterTabCrashed) {
- NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html"));
- ScreenWakeLockInMainFrame();
-
- // Crash the tab.
- CrashTab(GetWebContents());
-
- // Screen wake lock should be released.
- EXPECT_FALSE(HasWakeLock());
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterNavigation) {
- NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html"));
- ScreenWakeLockInMainFrame();
-
- // Navigate to a different document.
- NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
-
- // Screen wake lock should be released after navigation.
- EXPECT_FALSE(HasWakeLock());
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterNavigationToSelf) {
- NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html"));
- ScreenWakeLockInMainFrame();
-
- // Navigate to the same document.
- NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html"));
-
- // Screen wake lock should be released after navigation to the same URL.
- EXPECT_FALSE(HasWakeLock());
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, KeepLockAfterInPageNavigation) {
- GURL test_url(
- embedded_test_server()->GetURL("/session_history/fragment.html"));
- GURL test_in_page_url(test_url.spec() + "#a");
-
- NavigateToURL(shell(), test_url);
- ScreenWakeLockInMainFrame();
-
- NavigateToURL(shell(), test_in_page_url);
- EXPECT_TRUE(HasWakeLock());
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterReload) {
- NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html"));
- ScreenWakeLockInMainFrame();
-
- shell()->Reload();
- WaitForLoadStop(GetWebContents());
-
- // Screen wake lock should be released after reload.
- EXPECT_FALSE(HasWakeLock());
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, BrowserInitiatedFrameNavigation) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/frame_tree/2-4.html"));
-
- EXPECT_FALSE(HasWakeLock());
-
- // Lock screen in nested frame.
- EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;"));
- WaitForPossibleUpdate();
-
- // Screen wake lock should be present.
- EXPECT_TRUE(HasWakeLock());
-
- // Navigate the nested frame (browser-initiated).
- NavigateFrameToURL(GetNestedFrameNode(),
- embedded_test_server()->GetURL("/simple_page.html"));
- WaitForPossibleUpdate();
-
- // Screen wake lock should be released.
- EXPECT_FALSE(HasWakeLock());
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, RendererInitiatedFrameNavigation) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/frame_tree/2-4.html"));
-
- EXPECT_FALSE(HasWakeLock());
-
- // Lock screen in nested frame.
- EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;"));
- WaitForPossibleUpdate();
-
- // Screen wake lock should be present.
- EXPECT_TRUE(HasWakeLock());
-
- // Navigate the nested frame (renderer-initiated).
- NavigateIframeToURL(GetWebContents(), "3-1-id",
- embedded_test_server()->GetURL("/simple_page.html"));
- WaitForPossibleUpdate();
-
- // Screen wake lock should be released.
- EXPECT_FALSE(HasWakeLock());
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, OutOfProcessFrame) {
- NavigateToURL(shell(), embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(a)"));
- EXPECT_FALSE(HasWakeLock());
-
- // Ensure that the nested frame is same-process.
- EXPECT_FALSE(GetNestedFrame()->IsCrossProcessSubframe());
-
- // Lock screen in same-site nested frame.
- EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;"));
- WaitForPossibleUpdate();
- EXPECT_TRUE(HasWakeLock());
-
- // Grab a watcher for the RenderFrameHost of the first site.
- RenderFrameDeletedObserver frame_observer(
- GetNestedFrameNode()->current_frame_host());
-
- // Navigate nested frame to a cross-site document.
- NavigateFrameToURL(GetNestedFrameNode(), embedded_test_server()->GetURL(
- "b.com", "/simple_page.html"));
- WaitForPossibleUpdate();
-
- // Ensure that a new process has been created for the nested frame.
- EXPECT_TRUE(GetNestedFrame()->IsCrossProcessSubframe());
-
- // While the navigation to the second URL has completed, the teardown of the
- // host-side objects for the first URL may not have yet. The WakeLock will
- // only be released once the first renderer is cleaned up since it is held
- // by that renderer.
- // TODO(crbug.com/899384): This races with the new renderer then, would it
- // cause us to release a WakeLock that it requested before the old renderer
- // was torn down?
- frame_observer.WaitUntilDeleted();
-
- // Screen wake lock should be released.
- EXPECT_FALSE(HasWakeLock());
-
- // Lock screen in the cross-site nested frame.
- EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;"));
- WaitForPossibleUpdate();
-
- // Screen wake lock should be created.
- EXPECT_TRUE(HasWakeLock());
-}
-
-IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterCrashOutOfProcessFrame) {
- // Load a page with cross-site iframe.
- NavigateToURL(shell(), embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(b)"));
- EXPECT_FALSE(HasWakeLock());
-
- // Ensure that a new process has been created for the nested frame.
- EXPECT_TRUE(GetNestedFrame()->IsCrossProcessSubframe());
-
- // Lock screen in cross-site nested frame.
- EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;"));
- WaitForPossibleUpdate();
- EXPECT_TRUE(HasWakeLock());
-
- // Crash process that owns the out-of-process frame.
- RenderProcessHostWatcher watcher(
- GetNestedFrame()->GetProcess(),
- RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
- GetNestedFrame()->GetProcess()->Shutdown(0);
- watcher.Wait();
-
- // Screen wake lock should be released.
- EXPECT_FALSE(HasWakeLock());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/web_contents/DEPS b/chromium/content/browser/web_contents/DEPS
new file mode 100644
index 00000000000..533dfe3e16a
--- /dev/null
+++ b/chromium/content/browser/web_contents/DEPS
@@ -0,0 +1,6 @@
+specific_include_rules = {
+ ".*_mac.*": [
+ "+components/remote_cocoa",
+ "+content/app_shim_remote_cocoa",
+ ],
+}
diff --git a/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc b/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc
index 2bbebeb9c01..01fa8857e21 100644
--- a/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc
+++ b/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc
@@ -653,16 +653,16 @@ void GestureNavSimple::OnOverscrollModeChange(OverscrollMode old_mode,
UmaNavigationType::NAVIGATION_TYPE_COUNT);
const bool is_touchpad = source == OverscrollSource::TOUCHPAD;
- const float start_threshold = OverscrollConfig::GetThreshold(
- is_touchpad ? OverscrollConfig::Threshold::kStartTouchpad
- : OverscrollConfig::Threshold::kStartTouchscreen);
+ const float start_threshold =
+ is_touchpad ? OverscrollConfig::kStartTouchpadThresholdDips
+ : OverscrollConfig::kStartTouchscreenThresholdDips;
const gfx::Size size = GetDisplaySize();
const int max_size = std::max(size.width(), size.height());
completion_threshold_ =
- max_size * OverscrollConfig::GetThreshold(
- is_touchpad
- ? OverscrollConfig::Threshold::kCompleteTouchpad
- : OverscrollConfig::Threshold::kCompleteTouchscreen) -
+ max_size *
+ (is_touchpad
+ ? OverscrollConfig::kCompleteTouchpadThresholdPercent
+ : OverscrollConfig::kCompleteTouchscreenThresholdPercent) -
start_threshold;
DCHECK_LE(0, completion_threshold_);
diff --git a/chromium/content/browser/web_contents/frame_tree_node_id_registry.cc b/chromium/content/browser/web_contents/frame_tree_node_id_registry.cc
new file mode 100644
index 00000000000..b3ef78a5896
--- /dev/null
+++ b/chromium/content/browser/web_contents/frame_tree_node_id_registry.cc
@@ -0,0 +1,45 @@
+// 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_contents/frame_tree_node_id_registry.h"
+
+#include "base/bind_helpers.h"
+#include "content/public/browser/web_contents.h"
+
+namespace content {
+
+using WebContentsGetter = FrameTreeNodeIdRegistry::WebContentsGetter;
+
+// static
+FrameTreeNodeIdRegistry* FrameTreeNodeIdRegistry::GetInstance() {
+ static base::NoDestructor<FrameTreeNodeIdRegistry> instance;
+ return instance.get();
+}
+
+void FrameTreeNodeIdRegistry::Add(const base::UnguessableToken& id,
+ const int frame_tree_node_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ bool inserted = (map_.emplace(id, frame_tree_node_id)).second;
+ CHECK(inserted);
+}
+
+void FrameTreeNodeIdRegistry::Remove(const base::UnguessableToken& id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ map_.erase(id);
+}
+
+WebContentsGetter FrameTreeNodeIdRegistry::GetWebContentsGetter(
+ const base::UnguessableToken& id) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto iter = map_.find(id);
+ if (iter == map_.end())
+ return base::NullCallback();
+ return base::BindRepeating(&WebContents::FromFrameTreeNodeId, iter->second);
+}
+
+FrameTreeNodeIdRegistry::FrameTreeNodeIdRegistry() = default;
+
+FrameTreeNodeIdRegistry::~FrameTreeNodeIdRegistry() = default;
+
+} // namespace content
diff --git a/chromium/content/browser/web_contents/frame_tree_node_id_registry.h b/chromium/content/browser/web_contents/frame_tree_node_id_registry.h
new file mode 100644
index 00000000000..a74ea4db350
--- /dev/null
+++ b/chromium/content/browser/web_contents/frame_tree_node_id_registry.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_WEB_CONTENTS_FRAME_TREE_NODE_ID_REGISTRY_H_
+#define CONTENT_BROWSER_WEB_CONTENTS_FRAME_TREE_NODE_ID_REGISTRY_H_
+
+#include <map>
+
+#include "base/callback.h"
+#include "base/no_destructor.h"
+#include "base/sequence_checker.h"
+#include "base/unguessable_token.h"
+
+namespace content {
+
+class WebContents;
+
+// A global map of UnguessableToken to FrameTreeNode id. This registry lives
+// and is used only on the IO thread, as it's convenient for the current user
+// of the class (ServiceWorkerProviderHost, which should move to the UI thread
+// eventually). This is currently used to map a network request to a frame so
+// that the network service can tell the browser to display tab-level UI
+// required for the request in certain cases, including client certificates and
+// basic HTTP authentication.
+//
+// It uses FrameTreeNode rather than RenderFrameHost because the lookup can
+// happen for browser-initiated navigation requests, where a RenderFrameHost
+// might not have been created yet.
+//
+// Warning: A corresponding frame may have changed security contexts since it
+// was added. It's useful for looking up a WebContents or determining if it's a
+// main frame or not, but callers should not make assumptions that it's in the
+// same renderer process or origin as when it was added to the registry.
+// To prevent a potential risk, the registry doesn't provide
+// |static int /* FrameTreeNode id */ Get(const base::UnguessableToken& id)|.
+class FrameTreeNodeIdRegistry {
+ public:
+ using WebContentsGetter = base::RepeatingCallback<WebContents*()>;
+
+ static FrameTreeNodeIdRegistry* GetInstance();
+
+ void Add(const base::UnguessableToken& id, const int frame_tree_node_id);
+ void Remove(const base::UnguessableToken&);
+ // Returns null callback if not found.
+ WebContentsGetter GetWebContentsGetter(
+ const base::UnguessableToken& id) const;
+
+ private:
+ friend class base::NoDestructor<FrameTreeNodeIdRegistry>;
+
+ FrameTreeNodeIdRegistry();
+ ~FrameTreeNodeIdRegistry();
+
+ std::map<base::UnguessableToken, int> map_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+ DISALLOW_COPY_AND_ASSIGN(FrameTreeNodeIdRegistry);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEB_CONTENTS_FRAME_TREE_NODE_ID_REGISTRY_H_
diff --git a/chromium/content/browser/web_contents/javascript_dialog_navigation_deferrer.cc b/chromium/content/browser/web_contents/javascript_dialog_navigation_deferrer.cc
new file mode 100644
index 00000000000..edfb2c7e0b4
--- /dev/null
+++ b/chromium/content/browser/web_contents/javascript_dialog_navigation_deferrer.cc
@@ -0,0 +1,69 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_contents/javascript_dialog_navigation_deferrer.h"
+
+#include "content/browser/frame_host/navigation_handle_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+
+namespace content {
+
+// static
+std::unique_ptr<NavigationThrottle>
+JavaScriptDialogNavigationThrottle::MaybeCreateThrottleFor(
+ NavigationHandle* navigation_handle) {
+ // Don't prevent the user from navigating away from the page.
+ if (navigation_handle->IsInMainFrame() &&
+ (!navigation_handle->IsRendererInitiated() ||
+ navigation_handle->HasUserGesture())) {
+ return nullptr;
+ }
+
+ return std::make_unique<JavaScriptDialogNavigationThrottle>(
+ navigation_handle);
+}
+
+JavaScriptDialogNavigationThrottle::JavaScriptDialogNavigationThrottle(
+ NavigationHandle* navigation_handle)
+ : NavigationThrottle(navigation_handle) {}
+
+NavigationThrottle::ThrottleCheckResult
+JavaScriptDialogNavigationThrottle::WillProcessResponse() {
+ // Don't defer downloads, which don't leave the page.
+ if (navigation_handle()->IsDownload())
+ return PROCEED;
+
+ JavaScriptDialogNavigationDeferrer* deferrer =
+ static_cast<WebContentsImpl*>(navigation_handle()->GetWebContents())
+ ->GetJavaScriptDialogNavigationDeferrer();
+ if (!deferrer)
+ return PROCEED;
+
+ deferrer->AddThrottle(this);
+ return DEFER;
+}
+
+void JavaScriptDialogNavigationThrottle::Resume() {
+ NavigationThrottle::Resume();
+}
+
+const char* JavaScriptDialogNavigationThrottle::GetNameForLogging() {
+ return "JavaScriptDialogNavigationThrottle";
+}
+
+JavaScriptDialogNavigationDeferrer::JavaScriptDialogNavigationDeferrer() {}
+
+JavaScriptDialogNavigationDeferrer::~JavaScriptDialogNavigationDeferrer() {
+ for (auto& throttle : throttles_) {
+ if (throttle)
+ throttle->Resume();
+ }
+}
+
+void JavaScriptDialogNavigationDeferrer::AddThrottle(
+ JavaScriptDialogNavigationThrottle* throttle) {
+ throttles_.push_back(throttle->AsWeakPtr());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/web_contents/javascript_dialog_navigation_deferrer.h b/chromium/content/browser/web_contents/javascript_dialog_navigation_deferrer.h
new file mode 100644
index 00000000000..1e5e09deb9d
--- /dev/null
+++ b/chromium/content/browser/web_contents/javascript_dialog_navigation_deferrer.h
@@ -0,0 +1,64 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_CONTENTS_JAVASCRIPT_DIALOG_NAVIGATION_DEFERRER_H_
+#define CONTENT_BROWSER_WEB_CONTENTS_JAVASCRIPT_DIALOG_NAVIGATION_DEFERRER_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/navigation_throttle.h"
+
+namespace content {
+
+// Throttle registered for most navigations in a WebContents, so that they can
+// be deferred during a dialog if a JavaScriptDialogNavigationDeferrer (below)
+// exists at response time.
+class JavaScriptDialogNavigationThrottle
+ : public NavigationThrottle,
+ public base::SupportsWeakPtr<JavaScriptDialogNavigationThrottle> {
+ public:
+ // Registers a throttle for most navigations in a tab, unless they target the
+ // main frame with a user gesture or will be a download.
+ static std::unique_ptr<NavigationThrottle> MaybeCreateThrottleFor(
+ NavigationHandle* navigation_handle);
+ explicit JavaScriptDialogNavigationThrottle(
+ NavigationHandle* navigation_handle);
+ ~JavaScriptDialogNavigationThrottle() override = default;
+
+ // NavigationThrottle methods:
+ ThrottleCheckResult WillProcessResponse() override;
+ void Resume() override;
+ const char* GetNameForLogging() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(JavaScriptDialogNavigationThrottle);
+};
+
+// Prevents navigations in a WebContents that is showing a modal dialog,
+// unless it is a user-initiated main frame navigation (in which case the dialog
+// will be auto-dismissed when the navigation completes).
+class JavaScriptDialogNavigationDeferrer {
+ public:
+ JavaScriptDialogNavigationDeferrer();
+ ~JavaScriptDialogNavigationDeferrer();
+
+ private:
+ friend class JavaScriptDialogNavigationThrottle;
+
+ // Only called by JavaScriptDialogNavigationThrottle::WillProcessResponse, in
+ // the case that a dialog is showing at response time.
+ void AddThrottle(JavaScriptDialogNavigationThrottle* throttle);
+
+ // Stores a weak reference to a throttle for each deferred navigation.
+ std::vector<base::WeakPtr<JavaScriptDialogNavigationThrottle>> throttles_;
+
+ DISALLOW_COPY_AND_ASSIGN(JavaScriptDialogNavigationDeferrer);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEB_CONTENTS_JAVASCRIPT_DIALOG_NAVIGATION_DEFERRER_H_
diff --git a/chromium/content/browser/web_contents/web_contents_android.cc b/chromium/content/browser/web_contents/web_contents_android.cc
index d48a6cc2b96..7d469fd5e7e 100644
--- a/chromium/content/browser/web_contents/web_contents_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_android.cc
@@ -257,6 +257,8 @@ WebContentsAndroid::~WebContentsAndroid() {
DCHECK(g_allocated_web_contents_androids.Get().find(this) !=
g_allocated_web_contents_androids.Get().end());
g_allocated_web_contents_androids.Get().erase(this);
+ for (auto& observer : destruction_observers_)
+ observer.WebContentsAndroidDestroyed(this);
Java_WebContentsImpl_clearNativePtr(AttachCurrentThread(), obj_);
}
@@ -265,6 +267,21 @@ WebContentsAndroid::GetJavaObject() {
return base::android::ScopedJavaLocalRef<jobject>(obj_);
}
+void WebContentsAndroid::ClearNativeReference(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj) {
+ return web_contents_->ClearWebContentsAndroid();
+}
+
+void WebContentsAndroid::AddDestructionObserver(DestructionObserver* observer) {
+ destruction_observers_.AddObserver(observer);
+}
+
+void WebContentsAndroid::RemoveDestructionObserver(
+ DestructionObserver* observer) {
+ destruction_observers_.RemoveObserver(observer);
+}
+
base::android::ScopedJavaLocalRef<jobject>
WebContentsAndroid::GetTopLevelNativeWindow(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
@@ -615,6 +632,11 @@ jint WebContentsAndroid::GetThemeColor(JNIEnv* env,
return web_contents_->GetThemeColor().value_or(SK_ColorTRANSPARENT);
}
+jint WebContentsAndroid::GetLoadProgress(JNIEnv* env,
+ const JavaParamRef<jobject>& obj) {
+ return web_contents_->GetLoadProgress() * 100;
+}
+
void WebContentsAndroid::RequestSmartClipExtract(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
@@ -900,4 +922,12 @@ void WebContentsAndroid::SetDisplayCutoutSafeArea(
gfx::Insets(top, left, bottom, right));
}
+void WebContentsAndroid::NotifyRendererPreferenceUpdate(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj) {
+ RenderViewHost* rvh = web_contents_->GetRenderViewHost();
+ DCHECK(rvh);
+ rvh->OnWebkitPreferencesChanged();
+}
+
} // 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 d9d1a37b79d..e8ee623674d 100644
--- a/chromium/content/browser/web_contents/web_contents_android.h
+++ b/chromium/content/browser/web_contents/web_contents_android.h
@@ -13,7 +13,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/supports_user_data.h"
#include "content/browser/frame_host/navigation_controller_android.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/common/content_export.h"
@@ -27,17 +26,18 @@ class WebContentsImpl;
// Android wrapper around WebContents that provides safer passage from java and
// back to native and provides java with a means of communicating with its
// native counterpart.
-class CONTENT_EXPORT WebContentsAndroid
- : public base::SupportsUserData::Data {
+class CONTENT_EXPORT WebContentsAndroid {
public:
explicit WebContentsAndroid(WebContentsImpl* web_contents);
- ~WebContentsAndroid() override;
+ ~WebContentsAndroid();
WebContentsImpl* web_contents() const { return web_contents_; }
base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
// Methods called from Java
+ void ClearNativeReference(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj);
base::android::ScopedJavaLocalRef<jobject> GetTopLevelNativeWindow(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
@@ -158,6 +158,9 @@ class CONTENT_EXPORT WebContentsAndroid
jint GetThemeColor(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
+ jint GetLoadProgress(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj);
+
void RequestSmartClipExtract(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
@@ -258,9 +261,22 @@ class CONTENT_EXPORT WebContentsAndroid
int left,
int bottom,
int right);
+ void NotifyRendererPreferenceUpdate(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj);
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid();
+ class DestructionObserver : public base::CheckedObserver {
+ public:
+ // Invoked when the Java reference to the WebContents is being destroyed.
+ virtual void WebContentsAndroidDestroyed(
+ WebContentsAndroid* web_contents_android) = 0;
+ };
+
+ void AddDestructionObserver(DestructionObserver* observer);
+ void RemoveDestructionObserver(DestructionObserver* observer);
+
private:
void OnFinishGetContentBitmap(const base::android::JavaRef<jobject>& obj,
const base::android::JavaRef<jobject>& callback,
@@ -283,6 +299,8 @@ class CONTENT_EXPORT WebContentsAndroid
NavigationControllerAndroid navigation_controller_;
base::android::ScopedJavaGlobalRef<jobject> obj_;
+ base::ObserverList<DestructionObserver> destruction_observers_;
+
base::WeakPtrFactory<WebContentsAndroid> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(WebContentsAndroid);
diff --git a/chromium/content/browser/web_contents/web_contents_getter_registry.cc b/chromium/content/browser/web_contents/web_contents_getter_registry.cc
deleted file mode 100644
index ec363066a5d..00000000000
--- a/chromium/content/browser/web_contents/web_contents_getter_registry.cc
+++ /dev/null
@@ -1,51 +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_contents/web_contents_getter_registry.h"
-
-#include "base/no_destructor.h"
-
-namespace content {
-
-using WebContentsGetter = WebContentsGetterRegistry::WebContentsGetter;
-
-// static
-WebContentsGetterRegistry* WebContentsGetterRegistry::GetInstance() {
- static base::NoDestructor<WebContentsGetterRegistry> instance;
- return instance.get();
-}
-
-void WebContentsGetterRegistry::Add(
- const base::UnguessableToken& id,
- const WebContentsGetter& web_contents_getter) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- bool inserted = (map_.emplace(id, web_contents_getter)).second;
- CHECK(inserted);
-}
-
-void WebContentsGetterRegistry::Remove(const base::UnguessableToken& id) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- map_.erase(id);
-}
-
-const WebContentsGetter& WebContentsGetterRegistry::Get(
- const base::UnguessableToken& id) const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- auto iter = map_.find(id);
- if (iter == map_.end())
- return GetNullGetter();
- return iter->second;
-}
-
-WebContentsGetterRegistry::WebContentsGetterRegistry() = default;
-
-WebContentsGetterRegistry::~WebContentsGetterRegistry() = default;
-
-// static
-const WebContentsGetter& WebContentsGetterRegistry::GetNullGetter() {
- static const base::NoDestructor<WebContentsGetter> null_getter;
- return *null_getter;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_getter_registry.h b/chromium/content/browser/web_contents/web_contents_getter_registry.h
deleted file mode 100644
index de6ad4491de..00000000000
--- a/chromium/content/browser/web_contents/web_contents_getter_registry.h
+++ /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.
-
-#ifndef CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_GETTER_REGISTRY_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_GETTER_REGISTRY_H_
-
-#include "base/callback_forward.h"
-#include "base/containers/flat_map.h"
-#include "base/sequence_checker.h"
-#include "base/unguessable_token.h"
-#include "content/public/browser/web_contents.h"
-
-namespace content {
-
-// A global map of UnguessableToken to WebContentsGetter. Unlike most other
-// WebContents related objects, this registry lives and is used only on the IO
-// thread, as it's convenient for the current user of the class
-// (ServiceWorkerProviderHost, which should move to the UI thread eventually).
-// However, the WebContentsGetter callbacks must only be run on the UI thread.
-class WebContentsGetterRegistry {
- public:
- using WebContentsGetter = base::RepeatingCallback<WebContents*()>;
-
- static WebContentsGetterRegistry* GetInstance();
-
- void Add(const base::UnguessableToken& id,
- const WebContentsGetter& web_contents_getter);
- void Remove(const base::UnguessableToken&);
- // Returns null getter if not found.
- const WebContentsGetter& Get(const base::UnguessableToken& id) const;
-
- private:
- friend class base::NoDestructor<WebContentsGetterRegistry>;
-
- WebContentsGetterRegistry();
- ~WebContentsGetterRegistry();
-
- static const WebContentsGetter& GetNullGetter();
-
- base::flat_map<base::UnguessableToken, WebContentsGetter> map_;
-
- SEQUENCE_CHECKER(sequence_checker_);
- DISALLOW_COPY_AND_ASSIGN(WebContentsGetterRegistry);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_GETTER_REGISTRY_H_
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index afb23ccce9d..5d4b92af30e 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -84,6 +84,7 @@
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/browser/screen_orientation/screen_orientation_provider.h"
#include "content/browser/site_instance_impl.h"
+#include "content/browser/web_contents/javascript_dialog_navigation_deferrer.h"
#include "content/browser/web_contents/web_contents_view_child_frame.h"
#include "content/browser/web_contents/web_contents_view_guest.h"
#include "content/browser/webui/generic_handler.h"
@@ -187,10 +188,6 @@ namespace {
const int kMinimumDelayBetweenLoadingUpdatesMS = 100;
const char kDotGoogleDotCom[] = ".google.com";
-#if defined(OS_ANDROID)
-const void* const kWebContentsAndroidKey = &kWebContentsAndroidKey;
-#endif
-
base::LazyInstance<std::vector<
WebContentsImpl::FriendWrapper::CreatedCallback>>::DestructorAtExit
g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
@@ -613,6 +610,8 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
registry_.AddInterface(base::BindRepeating(
&WebContentsImpl::OnColorChooserFactoryRequest, base::Unretained(this)));
+
+ dark_mode_observer_.Start();
}
WebContentsImpl::~WebContentsImpl() {
@@ -717,6 +716,12 @@ WebContentsImpl::~WebContentsImpl() {
for (auto& observer : observers_)
observer.RenderViewDeleted(root->current_host());
+#if defined(OS_ANDROID)
+ // For simplicity, destroy the Java WebContents before we notify of the
+ // destruction of the WebContents.
+ ClearWebContentsAndroid();
+#endif
+
for (auto& observer : observers_)
observer.WebContentsDestroyed();
@@ -864,9 +869,6 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHostImpl* render_view_host,
IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission,
OnRequestPpapiBrokerPermission)
#endif
-#if defined(OS_ANDROID)
- IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog, OnOpenDateTimeDialog)
-#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -1936,11 +1938,10 @@ void WebContentsImpl::ReattachToOuterWebContentsFrame() {
}
void WebContentsImpl::DidChangeVisibleSecurityState() {
- if (delegate_) {
+ if (delegate_)
delegate_->VisibleSecurityStateChanged(this);
- for (auto& observer : observers_)
- observer.DidChangeVisibleSecurityState();
- }
+ for (auto& observer : observers_)
+ observer.DidChangeVisibleSecurityState();
}
void WebContentsImpl::NotifyPreferencesChanged() {
@@ -2105,7 +2106,7 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
manifest_manager_host_.reset(new ManifestManagerHost(this));
#if defined(OS_ANDROID)
- date_time_chooser_.reset(new DateTimeChooserAndroid());
+ date_time_chooser_.reset(new DateTimeChooserAndroid(this));
#endif
// BrowserPluginGuest::Init needs to be called after this WebContents has
@@ -3213,23 +3214,6 @@ device::mojom::WakeLockContext* WebContentsImpl::GetWakeLockContext() {
return wake_lock_context_host_->GetWakeLockContext();
}
-device::mojom::WakeLock* WebContentsImpl::GetRendererWakeLock() {
- // WebContents creates a long-lived connection to one WakeLock.
- // All the frames' requests will be added into the BindingSet of
- // WakeLock via this connection.
- if (!renderer_wake_lock_) {
- device::mojom::WakeLockContext* wake_lock_context = GetWakeLockContext();
- if (!wake_lock_context) {
- return nullptr;
- }
- wake_lock_context->GetWakeLock(
- device::mojom::WakeLockType::kPreventDisplaySleep,
- device::mojom::WakeLockReason::kOther, "Wake Lock API",
- mojo::MakeRequest(&renderer_wake_lock_));
- }
- return renderer_wake_lock_.get();
-}
-
#if defined(OS_ANDROID)
void WebContentsImpl::GetNFC(device::mojom::NFCRequest request) {
if (!nfc_host_)
@@ -3659,6 +3643,8 @@ void WebContentsImpl::Paste() {
return;
focused_frame->GetFrameInputHandler()->Paste();
+ for (auto& observer : observers_)
+ observer.OnPaste();
RecordAction(base::UserMetricsAction("Paste"));
}
@@ -3668,6 +3654,8 @@ void WebContentsImpl::PasteAndMatchStyle() {
return;
focused_frame->GetFrameInputHandler()->PasteAndMatchStyle();
+ for (auto& observer : observers_)
+ observer.OnPaste();
RecordAction(base::UserMetricsAction("PasteAndMatchStyle"));
}
@@ -4841,16 +4829,6 @@ void WebContentsImpl::OnUpdatePageImportanceSignals(
page_importance_signals_ = signals;
}
-#if defined(OS_ANDROID)
-void WebContentsImpl::OnOpenDateTimeDialog(
- RenderViewHostImpl* source,
- const ViewHostMsg_DateTimeDialogValue_Params& value) {
- date_time_chooser_->ShowDialog(
- GetTopLevelNativeWindow(), source, value.dialog_type, value.dialog_value,
- value.minimum, value.maximum, value.step, value.suggestions);
-}
-#endif
-
void WebContentsImpl::OnDomOperationResponse(RenderFrameHostImpl* source,
const std::string& json_string) {
// TODO(nick, lukasza): The notification below should probably be updated to
@@ -5356,6 +5334,10 @@ void WebContentsImpl::RunJavaScriptDialog(RenderFrameHost* render_frame_host,
if (delegate_)
dialog_manager_ = delegate_->GetJavaScriptDialogManager(this);
+ // While a JS message dialog is showing, defer commits in this WebContents.
+ javascript_dialog_navigation_deferrer_ =
+ std::make_unique<JavaScriptDialogNavigationDeferrer>();
+
// Suppress JavaScript dialogs when requested. Also suppress messages when
// showing an interstitial as it's shown over the previous page and we don't
// want the hidden page's dialogs to interfere with the interstitial.
@@ -5433,6 +5415,11 @@ void WebContentsImpl::RunBeforeUnloadConfirm(
if (delegate_)
dialog_manager_ = delegate_->GetJavaScriptDialogManager(this);
+ // While a JS beforeunload dialog is showing, defer commits in this
+ // WebContents.
+ javascript_dialog_navigation_deferrer_ =
+ std::make_unique<JavaScriptDialogNavigationDeferrer>();
+
bool should_suppress = ShowingInterstitialPage() || !rfhi->is_active() ||
(delegate_ && delegate_->ShouldSuppressDialogs(this));
bool has_non_devtools_handlers = delegate_ && dialog_manager_;
@@ -5586,9 +5573,13 @@ WebContentsImpl* WebContentsImpl::GetOuterWebContents() {
std::vector<WebContents*> WebContentsImpl::GetInnerWebContents() {
std::vector<WebContents*> all_inner_contents;
if (browser_plugin_embedder_) {
- GetBrowserContext()->GetGuestManager()->ForEachGuest(
- this,
- base::BindRepeating(&GetInnerWebContentsHelper, &all_inner_contents));
+ BrowserPluginGuestManager* guest_manager =
+ GetBrowserContext()->GetGuestManager();
+ if (guest_manager) {
+ guest_manager->ForEachGuest(
+ this,
+ base::BindRepeating(&GetInnerWebContentsHelper, &all_inner_contents));
+ }
}
const auto& inner_contents = node_.GetInnerWebContents();
all_inner_contents.insert(all_inner_contents.end(), inner_contents.begin(),
@@ -5863,8 +5854,22 @@ void WebContentsImpl::DidChangeLoadProgress() {
std::vector<std::unique_ptr<NavigationThrottle>>
WebContentsImpl::CreateThrottlesForNavigation(
NavigationHandle* navigation_handle) {
- return GetContentClient()->browser()->CreateThrottlesForNavigation(
+ auto throttles = GetContentClient()->browser()->CreateThrottlesForNavigation(
navigation_handle);
+
+ // This is not a normal place to be adding a throttle. However, in the case
+ // javascript dialogs, related logic is present in the web_contents/ layer,
+ // and the purpose of the throttle is to ensure that navigation commits are
+ // deferred for the entire WebContents. Most throttles are either added by
+ // the embederrer outside of content/, or are per-frame and added by
+ // NavigationThrottleRunner.
+ std::unique_ptr<content::NavigationThrottle> dialog_throttle =
+ JavaScriptDialogNavigationThrottle::MaybeCreateThrottleFor(
+ navigation_handle);
+ if (dialog_throttle)
+ throttles.push_back(std::move(dialog_throttle));
+
+ return throttles;
}
std::unique_ptr<NavigationUIData> WebContentsImpl::GetNavigationUIData(
@@ -6203,13 +6208,14 @@ void WebContentsImpl::OnFocusedElementChangedInFrame(
Details<FocusedNodeDetails>(&details));
}
-bool WebContentsImpl::DidAddMessageToConsole(int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id) {
+bool WebContentsImpl::DidAddMessageToConsole(
+ blink::mojom::ConsoleMessageLevel log_level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id) {
if (!delegate_)
return false;
- return delegate_->DidAddMessageToConsole(this, level, message, line_no,
+ return delegate_->DidAddMessageToConsole(this, log_level, message, line_no,
source_id);
}
@@ -6297,6 +6303,29 @@ void WebContentsImpl::RendererResponsive(
delegate_->RendererResponsive(this, render_widget_host);
}
+void WebContentsImpl::SubframeCrashed(
+ blink::mojom::FrameVisibility visibility) {
+ // If a subframe crashed on a hidden tab, mark the tab for reload to avoid
+ // showing a sad frame to the user if they ever switch back to that tab. Do
+ // this for subframes that are either visible in viewport or visible but
+ // scrolled out of view, but skip subframes that are not rendered (e.g., via
+ // "display:none"), since in that case the user wouldn't see a sad frame
+ // anyway.
+ bool did_mark_for_reload = false;
+ if (IsHidden() && visibility != blink::mojom::FrameVisibility::kNotRendered &&
+ base::FeatureList::IsEnabled(
+ features::kReloadHiddenTabsWithCrashedSubframes)) {
+ controller_.SetNeedsReload(
+ NavigationControllerImpl::NeedsReloadType::kCrashedSubframe);
+ did_mark_for_reload = true;
+ UMA_HISTOGRAM_ENUMERATION(
+ "Stability.ChildFrameCrash.TabMarkedForReload.Visibility", visibility);
+ }
+
+ UMA_HISTOGRAM_BOOLEAN("Stability.ChildFrameCrash.TabMarkedForReload",
+ did_mark_for_reload);
+}
+
void WebContentsImpl::BeforeUnloadFiredFromRenderManager(
bool proceed, const base::TimeTicks& proceed_time,
bool* proceed_to_fire_unload) {
@@ -6463,13 +6492,15 @@ WebContentsImpl::GetJavaWebContents() {
}
WebContentsAndroid* WebContentsImpl::GetWebContentsAndroid() {
- WebContentsAndroid* web_contents_android =
- static_cast<WebContentsAndroid*>(GetUserData(kWebContentsAndroidKey));
- if (!web_contents_android) {
- web_contents_android = new WebContentsAndroid(this);
- SetUserData(kWebContentsAndroidKey, base::WrapUnique(web_contents_android));
+ if (!web_contents_android_) {
+ web_contents_android_ = std::make_unique<WebContentsAndroid>(this);
}
- return web_contents_android;
+ return web_contents_android_.get();
+}
+
+void WebContentsImpl::ClearWebContentsAndroid() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ web_contents_android_.reset();
}
void WebContentsImpl::ActivateNearestFindResult(float x,
@@ -6525,6 +6556,8 @@ void WebContentsImpl::OnDialogClosed(int render_process_id,
render_frame_id);
last_dialog_suppressed_ = dialog_was_suppressed;
+ javascript_dialog_navigation_deferrer_.reset();
+
if (is_showing_before_unload_dialog_ && !success) {
// It is possible for the current RenderFrameHost to have changed in the
// meantime. Do not reset the navigation state in that case.
@@ -6914,6 +6947,13 @@ void WebContentsImpl::AudioContextPlaybackStopped(RenderFrameHost* host,
observer.AudioContextPlaybackStopped(audio_context_id);
}
+RenderFrameHostImpl* WebContentsImpl::GetMainFrameForInnerDelegate(
+ FrameTreeNode* frame_tree_node) {
+ if (auto* web_contents = node_.GetInnerWebContentsInFrame(frame_tree_node))
+ return web_contents->GetMainFrame();
+ return nullptr;
+}
+
void WebContentsImpl::UpdateWebContentsVisibility(Visibility visibility) {
// Occlusion is disabled when |features::kWebContentsOcclusion| is disabled
// (for power and speed impact assessment) or when
@@ -7058,4 +7098,8 @@ void WebContentsImpl::SetVisibilityForChildViews(bool visible) {
GetMainFrame()->SetVisibilityForChildViews(visible);
}
+void WebContentsImpl::OnDarkModeChanged(bool dark_mode) {
+ NotifyPreferencesChanged();
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_impl.h b/chromium/content/browser/web_contents/web_contents_impl.h
index 9be280b6e06..a93c238c96c 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -56,7 +56,6 @@
#include "net/http/http_response_headers.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/device/public/mojom/geolocation_context.mojom.h"
-#include "services/device/public/mojom/wake_lock.mojom.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/public/mojom/choosers/color_chooser.mojom.h"
#include "third_party/blink/public/mojom/page/display_cutout.mojom.h"
@@ -66,14 +65,14 @@
#include "ui/base/page_transition_types.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/native_theme/dark_mode_observer.h"
+#include "ui/native_theme/native_theme.h"
#if defined(OS_ANDROID)
#include "content/browser/android/nfc_host.h"
#include "content/public/browser/android/child_process_importance.h"
#endif
-struct ViewHostMsg_DateTimeDialogValue_Params;
-
namespace service_manager {
class InterfaceProvider;
}
@@ -86,6 +85,7 @@ class DisplayCutoutHostImpl;
class FindRequestManager;
class InterstitialPageImpl;
class JavaScriptDialogManager;
+class JavaScriptDialogNavigationDeferrer;
class LoaderIOThreadNotifier;
class ManifestManagerHost;
class MediaWebContentsObserver;
@@ -463,7 +463,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
#if defined(OS_ANDROID)
base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() override;
- virtual WebContentsAndroid* GetWebContentsAndroid();
+ WebContentsAndroid* GetWebContentsAndroid();
+ void ClearWebContentsAndroid();
void ActivateNearestFindResult(float x, float y) override;
void RequestFindMatchRects(int current_version) override;
service_manager::InterfaceProvider* GetJavaInterfaces() override;
@@ -539,7 +540,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
int browser_plugin_instance_id) override;
device::mojom::GeolocationContext* GetGeolocationContext() override;
device::mojom::WakeLockContext* GetWakeLockContext() override;
- device::mojom::WakeLock* GetRendererWakeLock() override;
#if defined(OS_ANDROID)
void GetNFC(device::mojom::NFCRequest request) override;
#endif
@@ -606,6 +606,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
int context_id) override;
void AudioContextPlaybackStopped(RenderFrameHost* host,
int context_id) override;
+ RenderFrameHostImpl* GetMainFrameForInnerDelegate(
+ FrameTreeNode* frame_tree_node) override;
// RenderViewHostDelegate ----------------------------------------------------
RenderViewHostDelegateView* GetDelegateView() override;
@@ -626,7 +628,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
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,
+ bool DidAddMessageToConsole(blink::mojom::ConsoleMessageLevel log_level,
const base::string16& message,
int32_t line_no,
const base::string16& source_id) override;
@@ -760,6 +762,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
RenderWidgetHostImpl* render_widget_host,
base::RepeatingClosure hang_monitor_restarter) override;
void RendererResponsive(RenderWidgetHostImpl* render_widget_host) override;
+ void SubframeCrashed(blink::mojom::FrameVisibility visibility) override;
void RequestToLockMouse(RenderWidgetHostImpl* render_widget_host,
bool user_gesture,
bool last_unlocked_by_target,
@@ -1034,6 +1037,10 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// call this directly.
void OnAppCacheAccessed(const GURL& manifest_url, bool blocked_by_policy);
+ JavaScriptDialogNavigationDeferrer* GetJavaScriptDialogNavigationDeferrer() {
+ return javascript_dialog_navigation_deferrer_.get();
+ }
+
private:
friend class WebContentsObserver;
friend class WebContents; // To implement factory methods.
@@ -1255,11 +1262,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
const std::string& protocol,
const GURL& url,
bool user_gesture);
-#if defined(OS_ANDROID)
- void OnOpenDateTimeDialog(
- RenderViewHostImpl* source,
- const ViewHostMsg_DateTimeDialogValue_Params& value);
-#endif
void OnDomOperationResponse(RenderFrameHostImpl* source,
const std::string& json_string);
void OnUpdatePageImportanceSignals(RenderFrameHostImpl* source,
@@ -1470,6 +1472,10 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// |current_fullscreen_frame_| and notify observers whenever it changes.
void FullscreenFrameSetUpdated();
+ // Called by DarkModeObserver when the dark mode state changes; triggers a
+ // preference update.
+ void OnDarkModeChanged(bool dark_mode);
+
// Data for core operation ---------------------------------------------------
// Delegate for notifying our owner about stuff. Not owned by us.
@@ -1510,6 +1516,10 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// is closed.
bool created_with_opener_;
+#if defined(OS_ANDROID)
+ std::unique_ptr<WebContentsAndroid> web_contents_android_;
+#endif
+
// Helper classes ------------------------------------------------------------
// Contains information about the WebContents tree structure.
@@ -1738,8 +1748,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
std::unique_ptr<WakeLockContextHost> wake_lock_context_host_;
- device::mojom::WakeLockPtr renderer_wake_lock_;
-
service_manager::BinderRegistry registry_;
mojo::BindingSet<blink::mojom::ColorChooserFactory>
@@ -1862,11 +1870,23 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// WebContents can be found by using GetOuterWebContents().
Portal* portal_ = nullptr;
+ // Observe dark mode native theme changes to notify the renderer about
+ // preferred color scheme changes.
+ ui::DarkModeObserver dark_mode_observer_{
+ ui::NativeTheme::GetInstanceForWeb(),
+ base::BindRepeating(&WebContentsImpl::OnDarkModeChanged,
+ base::Unretained(this))};
+
// TODO(crbug.com/934637): Remove this field when pdf/any inner web contents
// user gesture is properly propagated. This is a temporary fix for history
// intervention to be disabled for pdfs (crbug.com/965434).
bool had_inner_webcontents_;
+ // Prevents navigations in this contents while a javascript modal dialog is
+ // showing.
+ std::unique_ptr<JavaScriptDialogNavigationDeferrer>
+ javascript_dialog_navigation_deferrer_;
+
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 b4b07f552bd..84ca6c56bc1 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -552,7 +552,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, OpenURLSubframe) {
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
AppendingFrameInWebUIDoesNotCrash) {
- const GURL kWebUIUrl("chrome://tracing");
+ const GURL kWebUIUrl(GetWebUIURL("tracing"));
const char kJSCodeForAppendingFrame[] =
"document.body.appendChild(document.createElement('iframe'));";
@@ -873,7 +873,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
// Kill the renderer process so when the navigate again, it will be a fresh
// renderer with an empty in-memory cache.
- NavigateToURL(shell(), GURL("chrome:crash"));
+ NavigateToURL(shell(), GetWebUIURL("crash"));
// Reload that URL, the subresource should be served from the network cache.
before = base::TimeTicks::Now();
@@ -999,7 +999,7 @@ class WebContentsSplitCacheBrowserTest : public WebContentsImplBrowserTest {
// valid and return if the script was cached or not.
bool TestResourceLoad(const GURL& url, const GURL& sub_frame) {
// Kill the renderer to clear the in-memory cache.
- NavigateToURL(shell(), GURL("chrome:crash"));
+ NavigateToURL(shell(), GetWebUIURL("crash"));
// Observe network requests.
ResourceLoadObserver observer(shell());
@@ -1200,7 +1200,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
observer.resource_load_infos()[1]->network_info->network_accessed);
observer.Reset();
- NavigateToURL(shell(), GURL("chrome://gpu"));
+ NavigateToURL(shell(), GetWebUIURL("gpu"));
ASSERT_LE(1U, observer.resource_load_infos().size());
for (const mojom::ResourceLoadInfoPtr& resource_load_info :
observer.resource_load_infos()) {
@@ -1679,8 +1679,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
// Test that view source mode for a webui page can be opened.
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ViewSourceWebUI) {
- const std::string kUrl =
- "view-source:chrome://" + std::string(kChromeUIGpuHost);
+ const std::string kUrl = "view-source:" + GetWebUIURLString(kChromeUIGpuHost);
const GURL kGURL(kUrl);
NavigateToURL(shell(), kGURL);
EXPECT_EQ(base::ASCIIToUTF16(kUrl), shell()->web_contents()->GetTitle());
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 c1bfa28800f..227e15df85b 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -165,7 +165,7 @@ class TestInterstitialPage : public InterstitialPageImpl {
error_code);
}
- bool is_showing() const {
+ bool is_showing() {
return static_cast<TestRenderWidgetHostView*>(
GetMainFrame()->GetRenderViewHost()->GetWidget()->GetView())
->is_showing();
@@ -400,7 +400,7 @@ TEST_F(WebContentsImplTest, UpdateTitleBeforeFirstNavigation) {
}
TEST_F(WebContentsImplTest, DontUseTitleFromPendingEntry) {
- const GURL kGURL("chrome://blah");
+ const GURL kGURL(GetWebUIURL("blah"));
controller().LoadURL(
kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(base::string16(), contents()->GetTitle());
@@ -412,7 +412,7 @@ TEST_F(WebContentsImplTest, DontUseTitleFromPendingEntry) {
}
TEST_F(WebContentsImplTest, UseTitleFromPendingEntryIfSet) {
- const GURL kGURL("chrome://blah");
+ const GURL kGURL(GetWebUIURL("blah"));
const base::string16 title = base::ASCIIToUTF16("My Title");
controller().LoadURL(
kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
@@ -426,9 +426,9 @@ TEST_F(WebContentsImplTest, UseTitleFromPendingEntryIfSet) {
// Browser initiated navigations to view-source URLs of WebUI pages should work.
TEST_F(WebContentsImplTest, DirectNavigationToViewSourceWebUI) {
- const GURL kGURL("view-source:chrome://blah/");
+ const GURL kGURL("view-source:" + GetWebUIURLString("blah/"));
// NavigationControllerImpl rewrites view-source URLs, simulating that here.
- const GURL kRewrittenURL("chrome://blah");
+ const GURL kRewrittenURL(GetWebUIURL("blah"));
process()->sink().ClearMessages();
@@ -531,7 +531,6 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
auto new_site_navigation =
NavigationSimulator::CreateBrowserInitiated(url2, contents());
new_site_navigation->ReadyToCommit();
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(url, contents()->GetLastCommittedURL());
EXPECT_EQ(url2, contents()->GetVisibleURL());
@@ -542,9 +541,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
&pending_rvh_delete_count);
// DidNavigate from the pending page.
- contents()->TestDidNavigateWithSequenceNumber(
- pending_rfh, entry_id, true, url2, Referrer(), ui::PAGE_TRANSITION_TYPED,
- false, 1, 1);
+ new_site_navigation->Commit();
SiteInstance* instance2 = contents()->GetSiteInstance();
// Keep the number of active frames in pending_rfh's SiteInstance
@@ -560,7 +557,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
EXPECT_EQ(nullptr, contents()->GetPendingMainFrame());
// We keep a proxy for the original RFH's SiteInstance.
EXPECT_TRUE(contents()->GetRenderManagerForTesting()->GetRenderFrameProxyHost(
- orig_rfh->GetSiteInstance()));
+ instance1));
EXPECT_EQ(orig_rvh_delete_count, 0);
// Going back should switch SiteInstances again. The first SiteInstance is
@@ -569,24 +566,20 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
auto back_navigation =
NavigationSimulator::CreateHistoryNavigation(-1, contents());
back_navigation->ReadyToCommit();
- entry_id = controller().GetPendingEntry()->GetUniqueID();
TestRenderFrameHost* goback_rfh = contents()->GetPendingMainFrame();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
// DidNavigate from the back action.
- contents()->TestDidNavigateWithSequenceNumber(
- goback_rfh, entry_id, false, url, Referrer(), ui::PAGE_TRANSITION_TYPED,
- false, 2, 0);
+ back_navigation->Commit();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(goback_rfh, main_test_rfh());
EXPECT_EQ(url, contents()->GetLastCommittedURL());
EXPECT_EQ(url, contents()->GetVisibleURL());
EXPECT_EQ(instance1, contents()->GetSiteInstance());
// There should be a proxy for the pending RFH SiteInstance.
- EXPECT_TRUE(contents()->GetRenderManagerForTesting()->
- GetRenderFrameProxyHost(pending_rfh->GetSiteInstance()));
+ EXPECT_TRUE(contents()->GetRenderManagerForTesting()->GetRenderFrameProxyHost(
+ instance2));
EXPECT_EQ(pending_rvh_delete_count, 0);
- pending_rfh->OnSwappedOut();
// Close contents and ensure RVHs are deleted.
DeleteContents();
@@ -657,35 +650,27 @@ TEST_F(WebContentsImplTest, NavigateTwoTabsCrossSite) {
// Navigate first contents to a new site.
const GURL url2a("http://www.yahoo.com");
- controller().LoadURL(url2a, Referrer(), ui::PAGE_TRANSITION_LINK,
- std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- contents()->GetMainFrame()->PrepareForCommit();
- TestRenderFrameHost* pending_rfh_a = contents()->GetPendingMainFrame();
- if (AreAllSitesIsolatedForTesting())
- EXPECT_TRUE(contents()->CrossProcessNavigationPending());
- contents()->TestDidNavigate(pending_rfh_a, entry_id, true, url2a,
- ui::PAGE_TRANSITION_LINK);
+ auto navigation1 =
+ NavigationSimulator::CreateBrowserInitiated(url2a, contents());
+ navigation1->SetTransition(ui::PAGE_TRANSITION_LINK);
+ navigation1->ReadyToCommit();
+ EXPECT_TRUE(contents()->CrossProcessNavigationPending());
+ navigation1->Commit();
SiteInstance* instance2a = contents()->GetSiteInstance();
EXPECT_NE(instance1, instance2a);
// Navigate second contents to the same site as the first tab.
- const GURL url2b("http://mail.yahoo.com");
- contents2->GetController().LoadURL(url2b, Referrer(),
- ui::PAGE_TRANSITION_LINK, std::string());
- entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID();
- TestRenderFrameHost* rfh2 = contents2->GetMainFrame();
- rfh2->PrepareForCommit();
- TestRenderFrameHost* pending_rfh_b = contents2->GetPendingMainFrame();
- EXPECT_NE(nullptr, pending_rfh_b);
- if (AreAllSitesIsolatedForTesting())
- EXPECT_TRUE(contents2->CrossProcessNavigationPending());
+ const GURL url2b("http://www.yahoo.com/foo");
+ auto navigation2 =
+ NavigationSimulator::CreateBrowserInitiated(url2b, contents2.get());
+ navigation2->SetTransition(ui::PAGE_TRANSITION_LINK);
+ navigation2->ReadyToCommit();
+ EXPECT_TRUE(contents2->CrossProcessNavigationPending());
// NOTE(creis): We used to be in danger of showing a crash page here if the
// second contents hadn't navigated somewhere first (bug 1145430). That case
// is now covered by the CrossSiteBoundariesAfterCrash test.
- contents2->TestDidNavigate(pending_rfh_b, entry_id, true, url2b,
- ui::PAGE_TRANSITION_LINK);
+ navigation2->Commit();
SiteInstance* instance2b = contents2->GetSiteInstance();
EXPECT_NE(instance1, instance2b);
@@ -1597,8 +1582,10 @@ TEST_F(WebContentsImplTest,
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial
- controller().LoadURL(GURL("http://www.evil.com"), Referrer(),
- ui::PAGE_TRANSITION_TYPED, std::string());
+ GURL evil_url = GURL("http://www.evil.com");
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(evil_url, contents());
+ navigation->Start();
// Show an interstitial.
TestInterstitialPage::InterstitialState state =
@@ -1634,15 +1621,13 @@ TEST_F(WebContentsImplTest,
// Simulate the navigation to the page, that's when the interstitial gets
// hidden.
- GURL url3("http://www.thepage.com/two");
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, true, url3);
+ navigation->Commit();
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
entry = controller().GetVisibleEntry();
ASSERT_NE(nullptr, entry);
- EXPECT_TRUE(entry->GetURL() == url3);
+ EXPECT_EQ(evil_url, entry->GetURL());
EXPECT_EQ(2, controller().GetEntryCount());
@@ -2109,7 +2094,8 @@ TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
// Let's make sure interstitial2 is working as intended.
interstitial2->Proceed();
GURL landing_url("http://www.thepage.com/two");
- main_test_rfh()->SendNavigate(0, true, landing_url);
+ NavigationSimulator::NavigateAndCommitFromDocument(landing_url,
+ main_test_rfh());
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
@@ -2168,7 +2154,8 @@ TEST_F(WebContentsImplTest, ShowInterstitialProceedShowInterstitial) {
// Let's make sure interstitial2 is working as intended.
interstitial2->Proceed();
GURL landing_url("http://www.thepage.com/two");
- main_test_rfh()->SendNavigate(0, true, landing_url);
+ NavigationSimulator::NavigateAndCommitFromDocument(landing_url,
+ main_test_rfh());
RunAllPendingInMessageLoop();
EXPECT_TRUE(deleted2);
@@ -2479,7 +2466,8 @@ TEST_F(WebContentsImplTest, FilterURLs) {
other_contents->NavigateAndCommit(url_normalized);
// Check that an IPC with about:whatever is correctly normalized.
- other_contents->TestDidFailLoadWithError(url_from_ipc, 1, base::string16());
+ other_contents->GetMainFrame()->DidFailLoadWithError(url_from_ipc, 1,
+ base::string16());
EXPECT_EQ(url_blocked, other_observer.last_url());
}
@@ -2895,7 +2883,7 @@ TEST_F(WebContentsImplTest, ActiveContentsCountChangeBrowsingInstance) {
EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
// Navigate to a URL with WebUI. This will change BrowsingInstances.
- const GURL kWebUIUrl = GURL("chrome://gpu");
+ const GURL kWebUIUrl = GURL(GetWebUIURL(kChromeUIGpuHost));
auto web_ui_navigation =
NavigationSimulator::CreateBrowserInitiated(kWebUIUrl, contents.get());
web_ui_navigation->Start();
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 74f537d1161..ee5760ecbe0 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc
@@ -6,6 +6,8 @@
#include <stddef.h>
#include <stdint.h>
+#include <string>
+#include <utility>
#include "base/auto_reset.h"
#include "base/command_line.h"
@@ -34,6 +36,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/guest_mode.h"
+#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_source.h"
@@ -69,7 +72,6 @@
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/dragdrop/os_exchange_data_provider_factory.h"
#include "ui/base/hit_test.h"
-#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/compositor/layer.h"
#include "ui/display/screen.h"
@@ -278,6 +280,38 @@ void PrepareDragData(const DropData& drop_data,
}
}
+#if defined(OS_WIN)
+// Function returning whether this drop target should extract virtual file data
+// from the data store.
+// (1) As with real files, only add virtual files if the drag did not originate
+// in the renderer process. Without this, if an anchor element is dragged and
+// then dropped on the same page, the browser will navigate to the URL
+// referenced by the anchor. That is because virtual ".url" file data
+// (internet shortcut) is added to the data object on drag start, and if
+// script doesn't handle the drop, the browser behaves just as if a .url file
+// were dragged in from the desktop. Filtering out virtual files if the drag
+// is renderer tainted also prevents the possibility of a compromised renderer
+// gaining access to the backing temp file paths.
+// (2) Even if the drag is not renderer tainted, also exclude virtual files
+// if the UniformResourceLocatorW clipboard format is found in the data object.
+// Drags initiated in the browser process, such as dragging a bookmark from
+// the bookmark bar, will add a virtual .url file to the data object using the
+// CFSTR_FILEDESCRIPTORW/CFSTR_FILECONTENTS formats, which represents an
+// internet shortcut intended to be dropped on the desktop. But this causes a
+// regression in the behavior of the extensions page (see
+// https://crbug.com/963392). The primary scenario for introducing virtual file
+// support was for dragging items out of Outlook.exe for upload to a file
+// hosting service. The Outlook drag source does not add url data to the data
+// object.
+// TODO(https://crbug.com/958273): DragDrop: Extend virtual filename support
+// to DropData, for parity with real filename support.
+// TODO(https://crbug.com/964461): Drag and drop: Should support both virtual
+// file and url data on drop.
+bool ShouldIncludeVirtualFiles(const DropData& drop_data) {
+ return !drop_data.did_originate_from_renderer && drop_data.url.is_empty();
+}
+#endif
+
// Utility to fill a DropData object from ui::OSExchangeData.
void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) {
drop_data->did_originate_from_renderer = data.DidOriginateFromRenderer();
@@ -306,6 +340,14 @@ void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) {
data.GetFilenames(&drop_data->filenames);
+#if defined(OS_WIN)
+ // Get a list of virtual files for later retrieval when a drop is performed
+ // (will return empty vector if there are any non-virtual files in the data
+ // store).
+ if (ShouldIncludeVirtualFiles(*drop_data))
+ data.GetVirtualFilenames(&drop_data->filenames);
+#endif
+
base::Pickle pickle;
std::vector<DropData::FileSystemFileInfo> file_system_files;
if (data.GetPickledData(GetFileSystemFileFormatType(), &pickle) &&
@@ -357,6 +399,120 @@ aura::Window* GetHostWindow(aura::Window* window) {
} // namespace
+#if defined(OS_WIN)
+// A web contents observer that watches for navigations while an async drop
+// operation is in progress during virtual file data retrieval and temp file
+// creation. Navigations may cause completion of the drop to be disallowed. The
+// class also serves to cache the drop parameters as they were at the beginning
+// of the drop. This is needed for checking that the drop target is still valid
+// when the async operation completes, and if so, passing the parameters on to
+// the render widget host to complete the drop.
+class WebContentsViewAura::AsyncDropNavigationObserver
+ : public WebContentsObserver {
+ public:
+ AsyncDropNavigationObserver(WebContents* watched_contents,
+ std::unique_ptr<DropData> drop_data,
+ RenderWidgetHostImpl* target_rwh,
+ const gfx::PointF& client_pt,
+ const gfx::PointF& screen_pt,
+ int key_modifiers);
+
+ // WebContentsObserver:
+ void DidFinishNavigation(NavigationHandle* navigation_handle) override;
+
+ // Was a navigation observed while the async drop was being processed that
+ // should disallow the drop?
+ bool drop_allowed() const { return drop_allowed_; }
+
+ DropData* drop_data() const { return drop_data_.get(); }
+ RenderWidgetHostImpl* target_rwh() const { return target_rwh_.get(); }
+ const gfx::PointF& client_pt() const { return client_pt_; }
+ const gfx::PointF& screen_pt() const { return screen_pt_; }
+ int key_modifiers() const { return key_modifiers_; }
+
+ private:
+ bool drop_allowed_;
+
+ // Data cached at the start of the drop operation and needed to complete the
+ // drop.
+ std::unique_ptr<DropData> drop_data_;
+ base::WeakPtr<RenderWidgetHostImpl> target_rwh_;
+ const gfx::PointF client_pt_;
+ const gfx::PointF screen_pt_;
+ const int key_modifiers_;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncDropNavigationObserver);
+};
+
+WebContentsViewAura::AsyncDropNavigationObserver::AsyncDropNavigationObserver(
+ WebContents* watched_contents,
+ std::unique_ptr<DropData> drop_data,
+ RenderWidgetHostImpl* target_rwh,
+ const gfx::PointF& client_pt,
+ const gfx::PointF& screen_pt,
+ int key_modifiers)
+ : WebContentsObserver(watched_contents),
+ drop_allowed_(true),
+ drop_data_(std::move(drop_data)),
+ target_rwh_(target_rwh->GetWeakPtr()),
+ client_pt_(client_pt),
+ screen_pt_(screen_pt),
+ key_modifiers_(key_modifiers) {}
+
+void WebContentsViewAura::AsyncDropNavigationObserver::DidFinishNavigation(
+ NavigationHandle* navigation_handle) {
+ // This method is called every time any navigation completes in the observed
+ // web contents, including subframe navigations. In the case of a subframe
+ // navigation, we can't readily determine on the browser process side if the
+ // navigated subframe is the intended drop target. Err on the side of security
+ // and disallow the drop if any navigation commits to a different url.
+ if (navigation_handle->HasCommitted() &&
+ (navigation_handle->GetURL() != navigation_handle->GetPreviousURL())) {
+ drop_allowed_ = false;
+ }
+}
+
+// Deletes registered temp files asynchronously when the object goes out of
+// scope (when the WebContentsViewAura is deleted on tab closure).
+class WebContentsViewAura::AsyncDropTempFileDeleter {
+ public:
+ AsyncDropTempFileDeleter() = default;
+ ~AsyncDropTempFileDeleter();
+ void RegisterFile(const base::FilePath& path);
+
+ private:
+ void DeleteAllFilesAsync() const;
+ void DeleteFileAsync(const base::FilePath& path) const;
+
+ std::vector<base::FilePath> scoped_files_to_delete_;
+ DISALLOW_COPY_AND_ASSIGN(AsyncDropTempFileDeleter);
+};
+
+WebContentsViewAura::AsyncDropTempFileDeleter::~AsyncDropTempFileDeleter() {
+ DeleteAllFilesAsync();
+}
+
+void WebContentsViewAura::AsyncDropTempFileDeleter::RegisterFile(
+ const base::FilePath& path) {
+ scoped_files_to_delete_.push_back(path);
+}
+
+void WebContentsViewAura::AsyncDropTempFileDeleter::DeleteAllFilesAsync()
+ const {
+ for (const auto& path : scoped_files_to_delete_)
+ DeleteFileAsync(path);
+}
+
+void WebContentsViewAura::AsyncDropTempFileDeleter::DeleteFileAsync(
+ const base::FilePath& path) const {
+ base::PostTaskWithTraits(FROM_HERE,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
+ base::BindOnce(base::IgnoreResult(&base::DeleteFile),
+ std::move(path), false));
+}
+#endif
+
class WebContentsViewAura::WindowObserver
: public aura::WindowObserver, public aura::WindowTreeHostObserver {
public:
@@ -511,10 +667,7 @@ void WebContentsViewAura::InstallCreateHookForTests(
WebContentsViewAura::WebContentsViewAura(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate)
- : is_mus_browser_plugin_guest_(web_contents->GetBrowserPluginGuest() !=
- nullptr &&
- features::IsMultiProcessMash()),
- web_contents_(web_contents),
+ : web_contents_(web_contents),
delegate_(delegate),
current_drag_op_(blink::kWebDragOperationNone),
drag_dest_delegate_(nullptr),
@@ -570,10 +723,9 @@ void WebContentsViewAura::EndDrag(RenderWidgetHost* source_rwh,
if (screen_position_client)
screen_position_client->ConvertPointFromScreen(window, &client_loc);
- // |client_loc| and |screen_loc| are in the root coordinate space, for
- // non-root RenderWidgetHosts they need to be transformed.
+ // |client_loc| is in the root coordinate space, for non-root
+ // RenderWidgetHosts it needs to be transformed.
gfx::PointF transformed_point = client_loc;
- gfx::PointF transformed_screen_point = screen_loc;
if (source_rwh && web_contents_->GetRenderWidgetHostView()) {
static_cast<RenderWidgetHostViewBase*>(
web_contents_->GetRenderWidgetHostView())
@@ -581,17 +733,10 @@ void WebContentsViewAura::EndDrag(RenderWidgetHost* source_rwh,
client_loc,
static_cast<RenderWidgetHostViewBase*>(source_rwh->GetView()),
&transformed_point);
- static_cast<RenderWidgetHostViewBase*>(
- web_contents_->GetRenderWidgetHostView())
- ->TransformPointToCoordSpaceForView(
- screen_loc,
- static_cast<RenderWidgetHostViewBase*>(source_rwh->GetView()),
- &transformed_screen_point);
}
web_contents_->DragSourceEndedAt(transformed_point.x(), transformed_point.y(),
- transformed_screen_point.x(),
- transformed_screen_point.y(), ops,
+ screen_loc.x(), screen_loc.y(), ops,
source_rwh);
web_contents_->SystemDragEnded(source_rwh);
@@ -639,32 +784,17 @@ bool WebContentsViewAura::IsValidDragTarget(
// WebContentsViewAura, WebContentsView implementation:
gfx::NativeView WebContentsViewAura::GetNativeView() const {
- if (!is_mus_browser_plugin_guest_)
- return window_.get();
- DCHECK(web_contents_->GetOuterWebContents());
- return web_contents_->GetOuterWebContents()->GetView()->GetNativeView();
+ return window_.get();
}
gfx::NativeView WebContentsViewAura::GetContentNativeView() const {
- if (!is_mus_browser_plugin_guest_) {
- RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
- return rwhv ? rwhv->GetNativeView() : nullptr;
- }
- DCHECK(web_contents_->GetOuterWebContents());
- return web_contents_->GetOuterWebContents()
- ->GetView()
- ->GetContentNativeView();
+ RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
+ return rwhv ? rwhv->GetNativeView() : nullptr;
}
gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const {
- if (!is_mus_browser_plugin_guest_) {
- gfx::NativeWindow window = window_->GetToplevelWindow();
- return window ? window : delegate_->GetNativeWindow();
- }
- DCHECK(web_contents_->GetOuterWebContents());
- return web_contents_->GetOuterWebContents()
- ->GetView()
- ->GetTopLevelNativeWindow();
+ gfx::NativeWindow window = window_->GetToplevelWindow();
+ return window ? window : delegate_->GetNativeWindow();
}
void WebContentsViewAura::GetContainerBounds(gfx::Rect* out) const {
@@ -752,9 +882,8 @@ gfx::Rect WebContentsViewAura::GetViewBounds() const {
void WebContentsViewAura::CreateAuraWindow(aura::Window* context) {
DCHECK(aura::Env::HasInstance());
DCHECK(!window_);
- window_ = std::make_unique<aura::Window>(
- this, aura::client::WINDOW_TYPE_CONTROL,
- context ? context->env() : aura::Env::GetInstance());
+ window_ =
+ std::make_unique<aura::Window>(this, aura::client::WINDOW_TYPE_CONTROL);
window_->set_owned_by_parent(false);
window_->SetName("WebContentsViewAura");
window_->Init(ui::LAYER_NOT_DRAWN);
@@ -807,8 +936,7 @@ void WebContentsViewAura::CreateView(const gfx::Size& initial_size,
// if the bookmark bar is not shown and you create a new tab). The right
// value is set shortly after this, so its safe to ignore.
- if (!is_mus_browser_plugin_guest_)
- CreateAuraWindow(context);
+ CreateAuraWindow(context);
// delegate_->GetDragDestDelegate() creates a new delegate on every call.
// Hence, we save a reference to it locally. Similar model is used on other
@@ -834,8 +962,8 @@ RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
g_create_render_widget_host_view
? g_create_render_widget_host_view(render_widget_host,
is_guest_view_hack)
- : new RenderWidgetHostViewAura(render_widget_host, is_guest_view_hack,
- is_mus_browser_plugin_guest_);
+ : new RenderWidgetHostViewAura(render_widget_host,
+ is_guest_view_hack);
view->InitAsChild(GetRenderWidgetHostViewParent());
RenderWidgetHostImpl* host_impl =
@@ -844,9 +972,6 @@ RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
if (!host_impl->is_hidden())
view->Show();
- if (is_mus_browser_plugin_guest_)
- return view;
-
// We listen to drag drop events in the newly created view's window.
aura::client::SetDragDropDelegate(view->GetNativeView(), this);
@@ -861,20 +986,14 @@ RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) {
- // Popups are not created as embedded windows in mus, so
- // |is_mus_browser_plugin_guest| is always false for them.
- const bool is_mus_browser_plugin_guest = false;
- return new RenderWidgetHostViewAura(render_widget_host, false,
- is_mus_browser_plugin_guest);
+ return new RenderWidgetHostViewAura(render_widget_host, false);
}
void WebContentsViewAura::SetPageTitle(const base::string16& title) {
- if (!is_mus_browser_plugin_guest_) {
- window_->SetTitle(title);
- aura::Window* child_window = GetContentNativeView();
- if (child_window)
- child_window->SetTitle(title);
- }
+ window_->SetTitle(title);
+ aura::Window* child_window = GetContentNativeView();
+ if (child_window)
+ child_window->SetTitle(title);
}
void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) {
@@ -1114,6 +1233,10 @@ void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
// WebContentsViewAura, aura::client::DragDropDelegate implementation:
void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
+#if defined(OS_WIN)
+ async_drop_navigation_observer_.reset();
+#endif
+
gfx::PointF transformed_pt;
RenderWidgetHostImpl* target_rwh =
web_contents_->GetInputEventRouter()->GetRenderWidgetHostAtPoint(
@@ -1164,11 +1287,16 @@ int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
if (!IsValidDragTarget(target_rwh))
return ui::DragDropTypes::DRAG_NONE;
+ aura::Window* root_window = GetNativeView()->GetRootWindow();
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(root_window);
gfx::PointF screen_pt = event.root_location_f();
+ if (screen_position_client)
+ screen_position_client->ConvertPointToScreen(root_window, &screen_pt);
+
if (target_rwh != current_rwh_for_drag_.get()) {
if (current_rwh_for_drag_) {
gfx::PointF transformed_leave_point = event.location_f();
- gfx::PointF transformed_screen_point = screen_pt;
static_cast<RenderWidgetHostViewBase*>(
web_contents_->GetRenderWidgetHostView())
->TransformPointToCoordSpaceForView(
@@ -1176,14 +1304,8 @@ int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
static_cast<RenderWidgetHostViewBase*>(
current_rwh_for_drag_->GetView()),
&transformed_leave_point);
- static_cast<RenderWidgetHostViewBase*>(
- web_contents_->GetRenderWidgetHostView())
- ->TransformPointToCoordSpaceForView(
- screen_pt, static_cast<RenderWidgetHostViewBase*>(
- current_rwh_for_drag_->GetView()),
- &transformed_screen_point);
current_rwh_for_drag_->DragTargetDragLeave(transformed_leave_point,
- transformed_screen_point);
+ screen_pt);
}
OnDragEntered(event);
}
@@ -1240,16 +1362,123 @@ int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
if (!current_drop_data_)
return ui::DragDropTypes::DRAG_NONE;
- target_rwh->DragTargetDrop(
- *current_drop_data_, transformed_pt,
- gfx::PointF(display::Screen::GetScreen()->GetCursorScreenPoint()),
- ui::EventFlagsToWebEventModifiers(event.flags()));
- if (drag_dest_delegate_)
- drag_dest_delegate_->OnDrop();
+ const int key_modifiers = ui::EventFlagsToWebEventModifiers(event.flags());
+#if defined(OS_WIN)
+ if (ShouldIncludeVirtualFiles(*current_drop_data_) &&
+ event.data().HasVirtualFilenames()) {
+ // Asynchronously retrieve the actual content of any virtual files now (this
+ // step is not needed for "real" files already on the file system, e.g.
+ // those dropped on Chromium from the desktop). When all content has been
+ // written to temporary files, the OnGotVirtualFilesAsTempFiles
+ // callback will be invoked and the drop communicated to the renderer
+ // process.
+ auto callback =
+ base::BindOnce(&WebContentsViewAura::OnGotVirtualFilesAsTempFiles,
+ weak_ptr_factory_.GetWeakPtr());
+
+ // GetVirtualFilesAsTempFiles will immediately return false if there are no
+ // virtual files to retrieve (all items are folders e.g.) and no callback
+ // will be received.
+ if (event.data().GetVirtualFilesAsTempFiles(std::move(callback))) {
+ // Cache the parameters as they were at the time of the drop. This is
+ // needed for checking that the drop target is still valid when the async
+ // operation completes.
+ async_drop_navigation_observer_ =
+ std::make_unique<AsyncDropNavigationObserver>(
+ web_contents_, std::move(current_drop_data_), target_rwh,
+ transformed_pt, screen_pt, key_modifiers);
+
+ return ConvertFromWeb(current_drag_op_);
+ }
+ }
+
+#endif
+ CompleteDrop(target_rwh, *current_drop_data_, transformed_pt, screen_pt,
+ key_modifiers);
current_drop_data_.reset();
return ConvertFromWeb(current_drag_op_);
}
+void WebContentsViewAura::CompleteDrop(RenderWidgetHostImpl* target_rwh,
+ const DropData& drop_data,
+ const gfx::PointF& client_pt,
+ const gfx::PointF& screen_pt,
+ int key_modifiers) {
+ target_rwh->DragTargetDrop(drop_data, client_pt, screen_pt, key_modifiers);
+ if (drag_dest_delegate_)
+ drag_dest_delegate_->OnDrop();
+
+ if (!drop_callback_for_testing_.is_null()) {
+ std::move(drop_callback_for_testing_)
+ .Run(target_rwh, drop_data, client_pt, screen_pt, key_modifiers,
+ /*drop_allowed*/ true);
+ }
+}
+
+void WebContentsViewAura::RegisterDropCallbackForTesting(
+ DropCallbackForTesting callback) {
+ drop_callback_for_testing_ = std::move(callback);
+}
+
+#if defined(OS_WIN)
+void WebContentsViewAura::OnGotVirtualFilesAsTempFiles(
+ const std::vector<std::pair<base::FilePath, base::FilePath>>&
+ filepaths_and_names) {
+ DCHECK(!filepaths_and_names.empty());
+
+ if (!async_drop_navigation_observer_)
+ return;
+
+ std::unique_ptr<AsyncDropNavigationObserver> drop_observer(
+ std::move(async_drop_navigation_observer_));
+
+ RenderWidgetHostImpl* target_rwh = drop_observer->target_rwh();
+ DropData* drop_data = drop_observer->drop_data();
+
+ // Security check--don't allow the drop if a navigation occurred since the
+ // drop was initiated or the render widget host has changed or it is not a
+ // valid target.
+ if (!drop_observer->drop_allowed() ||
+ !(target_rwh && target_rwh == current_rwh_for_drag_.get() &&
+ IsValidDragTarget(target_rwh))) {
+ // Signal test code that the drop is disallowed
+ if (!drop_callback_for_testing_.is_null()) {
+ std::move(drop_callback_for_testing_)
+ .Run(target_rwh, *drop_data, drop_observer->client_pt(),
+ drop_observer->screen_pt(), drop_observer->key_modifiers(),
+ drop_observer->drop_allowed());
+ }
+
+ return;
+ }
+
+ // The vector of filenames will still have items added during dragenter
+ // (script is allowed to enumerate the files in the data store but not
+ // retrieve the file contents in dragenter). But the temp file path in the
+ // FileInfo structs will just be a placeholder. Clear out the vector before
+ // replacing it with FileInfo structs that have the paths to the retrieved
+ // file contents.
+ drop_data->filenames.clear();
+
+ // Ensure we have temp file deleter.
+ if (!async_drop_temp_file_deleter_) {
+ async_drop_temp_file_deleter_ =
+ std::make_unique<AsyncDropTempFileDeleter>();
+ }
+
+ for (const auto& filepath_and_name : filepaths_and_names) {
+ drop_data->filenames.push_back(
+ ui::FileInfo(filepath_and_name.first, filepath_and_name.second));
+
+ // Make sure the temp file eventually gets cleaned up.
+ async_drop_temp_file_deleter_->RegisterFile(filepath_and_name.first);
+ }
+
+ CompleteDrop(target_rwh, *drop_data, drop_observer->client_pt(),
+ drop_observer->screen_pt(), drop_observer->key_modifiers());
+}
+#endif
+
int WebContentsViewAura::GetTopControlsHeight() const {
WebContentsDelegate* delegate = web_contents_->GetDelegate();
if (!delegate)
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 a1395dab81d..46ca496af77 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.h
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.h
@@ -6,12 +6,14 @@
#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_AURA_H_
#include <memory>
+#include <utility>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/common/buildflags.h"
@@ -62,6 +64,16 @@ class CONTENT_EXPORT WebContentsViewAura
RenderWidgetHostViewCreateFunction create_render_widget_host_view);
private:
+ friend class WebContentsViewAuraTest;
+ FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, EnableDisableOverscroll);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, DragDropFiles);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest,
+ DragDropFilesOriginateFromRenderer);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, DragDropVirtualFiles);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest,
+ DragDropVirtualFilesOriginateFromRenderer);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, DragDropUrlData);
+
class WindowObserver;
~WebContentsViewAura() override;
@@ -181,11 +193,40 @@ class CONTENT_EXPORT WebContentsViewAura
void OnDragExited() override;
int OnPerformDrop(const ui::DropTargetEvent& event) override;
- FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, EnableDisableOverscroll);
-
- const bool is_mus_browser_plugin_guest_;
+ // Completes a drop operation by communicating the drop data to the renderer
+ // process.
+ void CompleteDrop(RenderWidgetHostImpl* target_rwh,
+ const DropData& drop_data,
+ const gfx::PointF& client_pt,
+ const gfx::PointF& screen_pt,
+ int key_modifiers);
+
+ // For unit testing, registers a callback for when a drop operation
+ // completes.
+ using DropCallbackForTesting =
+ base::OnceCallback<void(RenderWidgetHostImpl* target_rwh,
+ const DropData& drop_data,
+ const gfx::PointF& client_pt,
+ const gfx::PointF& screen_pt,
+ int key_modifiers,
+ bool drop_allowed)>;
+ void RegisterDropCallbackForTesting(DropCallbackForTesting callback);
+
+#if defined(OS_WIN)
+ // Callback for asynchronous retrieval of virtual files.
+ void OnGotVirtualFilesAsTempFiles(
+ const std::vector<std::pair</*temp path*/ base::FilePath,
+ /*display name*/ base::FilePath>>&
+ filepaths_and_names);
+
+ class AsyncDropNavigationObserver;
+ std::unique_ptr<AsyncDropNavigationObserver> async_drop_navigation_observer_;
+
+ class AsyncDropTempFileDeleter;
+ std::unique_ptr<AsyncDropTempFileDeleter> async_drop_temp_file_deleter_;
+#endif
+ DropCallbackForTesting drop_callback_for_testing_;
- // NOTE: this is null when running in mus and |is_mus_browser_plugin_guest_|.
std::unique_ptr<aura::Window> window_;
std::unique_ptr<WindowObserver> window_observer_;
@@ -229,6 +270,12 @@ class CONTENT_EXPORT WebContentsViewAura
bool init_rwhv_with_null_parent_for_testing_;
+#if defined(OS_WIN)
+ // Used to ensure that the virtual files retrieval callback bound to this
+ // object is canceled when this object is destroyed.
+ base::WeakPtrFactory<WebContentsViewAura> weak_ptr_factory_{this};
+#endif
+
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAura);
};
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index a151ac771e6..fd229b8a3e6 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
@@ -329,7 +329,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
blink::WebInputEvent::GetStaticTimeStampForTests(),
blink::WebGestureDevice::kTouchscreen);
gesture_scroll_begin.data.scroll_begin.delta_hint_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0.f;
gesture_scroll_begin.data.scroll_begin.delta_y_hint = 0.f;
GetRenderWidgetHost()->ForwardGestureEvent(gesture_scroll_begin);
@@ -340,10 +340,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
blink::WebInputEvent::GetStaticTimeStampForTests(),
blink::WebGestureDevice::kTouchscreen);
gesture_scroll_update.data.scroll_update.delta_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
gesture_scroll_update.data.scroll_update.delta_y = 0.f;
- float start_threshold = OverscrollConfig::GetThreshold(
- OverscrollConfig::Threshold::kStartTouchscreen);
+ float start_threshold = OverscrollConfig::kStartTouchscreenThresholdDips;
gesture_scroll_update.data.scroll_update.delta_x = start_threshold + 1;
GetRenderWidgetHost()->ForwardGestureEvent(gesture_scroll_update);
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc b/chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc
index 426ffbfe188..03b712ec6a2 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc
@@ -5,11 +5,15 @@
#include "content/browser/web_contents/web_contents_view_aura.h"
#include <memory>
+#include <string>
#include "base/command_line.h"
+#include "base/files/file_util.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/test/scoped_command_line.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_features.h"
#include "content/public/test/test_renderer_host.h"
@@ -18,16 +22,40 @@
#include "ui/aura/test/test_windows.h"
#include "ui/aura/test/window_test_api.h"
#include "ui/aura/window.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/drop_target_event.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/display/display_switches.h"
#include "ui/gfx/geometry/rect.h"
+#if defined(OS_WIN)
+#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
+#endif
+
namespace content {
namespace {
constexpr gfx::Rect kBounds = gfx::Rect(0, 0, 20, 20);
+constexpr gfx::PointF kClientPt = {5, 10};
+constexpr gfx::PointF kScreenPt = {17, 3};
} // namespace
class WebContentsViewAuraTest : public RenderViewHostTestHarness {
+ public:
+ void OnDropComplete(RenderWidgetHostImpl* target_rwh,
+ const DropData& drop_data,
+ const gfx::PointF& client_pt,
+ const gfx::PointF& screen_pt,
+ int key_modifiers,
+ bool drop_allowed) {
+ // Cache the data for verification.
+ drop_complete_data_ = std::make_unique<DropCompleteData>(
+ target_rwh, drop_data, client_pt, screen_pt, key_modifiers,
+ drop_allowed);
+
+ std::move(async_drop_closure_).Run();
+ }
+
protected:
WebContentsViewAuraTest() = default;
~WebContentsViewAuraTest() override = default;
@@ -49,26 +77,64 @@ class WebContentsViewAuraTest : public RenderViewHostTestHarness {
RenderViewHostTestHarness::TearDown();
}
- WebContentsViewAura* view() {
+ WebContentsViewAura* GetView() {
WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents());
return static_cast<WebContentsViewAura*>(contents->GetView());
}
aura::Window* GetNativeView() { return web_contents()->GetNativeView(); }
+ void CheckDropData(WebContentsViewAura* view) const {
+ EXPECT_EQ(nullptr, view->current_drop_data_);
+ ASSERT_NE(nullptr, drop_complete_data_);
+ EXPECT_TRUE(drop_complete_data_->drop_allowed);
+ EXPECT_EQ(view->current_rwh_for_drag_.get(),
+ drop_complete_data_->target_rwh.get());
+ EXPECT_EQ(kClientPt, drop_complete_data_->client_pt);
+ // Screen point of event is ignored, instead cursor position used.
+ EXPECT_EQ(gfx::PointF(), drop_complete_data_->screen_pt);
+ EXPECT_EQ(0, drop_complete_data_->key_modifiers);
+ }
+
// |occluding_window_| occludes |web_contents()| when it's shown.
std::unique_ptr<aura::Window> occluding_window_;
+ // A closure indicating that async drop operation has completed.
+ base::OnceClosure async_drop_closure_;
+
+ struct DropCompleteData {
+ DropCompleteData(RenderWidgetHostImpl* target_rwh,
+ const DropData& drop_data,
+ const gfx::PointF& client_pt,
+ const gfx::PointF& screen_pt,
+ int key_modifiers,
+ bool drop_allowed)
+ : target_rwh(target_rwh->GetWeakPtr()),
+ drop_data(drop_data),
+ client_pt(client_pt),
+ screen_pt(screen_pt),
+ key_modifiers(key_modifiers),
+ drop_allowed(drop_allowed) {}
+
+ base::WeakPtr<RenderWidgetHostImpl> target_rwh;
+ const DropData drop_data;
+ const gfx::PointF client_pt;
+ const gfx::PointF screen_pt;
+ const int key_modifiers;
+ const bool drop_allowed;
+ };
+ std::unique_ptr<DropCompleteData> drop_complete_data_;
+
private:
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest);
};
TEST_F(WebContentsViewAuraTest, EnableDisableOverscroll) {
- WebContentsViewAura* wcva = view();
- wcva->SetOverscrollControllerEnabled(false);
- EXPECT_FALSE(wcva->gesture_nav_simple_);
- wcva->SetOverscrollControllerEnabled(true);
- EXPECT_TRUE(wcva->gesture_nav_simple_);
+ WebContentsViewAura* view = GetView();
+ view->SetOverscrollControllerEnabled(false);
+ EXPECT_FALSE(view->gesture_nav_simple_);
+ view->SetOverscrollControllerEnabled(true);
+ EXPECT_TRUE(view->gesture_nav_simple_);
}
TEST_F(WebContentsViewAuraTest, ShowHideParent) {
@@ -90,4 +156,348 @@ TEST_F(WebContentsViewAuraTest, OccludeView) {
EXPECT_EQ(web_contents()->GetVisibility(), Visibility::VISIBLE);
}
+TEST_F(WebContentsViewAuraTest, DragDropFiles) {
+ WebContentsViewAura* view = GetView();
+ ui::OSExchangeData data;
+
+ const base::string16 string_data = base::ASCIIToUTF16("Some string data");
+ data.SetString(string_data);
+
+#if defined(OS_WIN)
+ const std::vector<ui::FileInfo> test_file_infos = {
+ {base::FilePath(FILE_PATH_LITERAL("C:\\tmp\\test_file1")),
+ base::FilePath()},
+ {base::FilePath(FILE_PATH_LITERAL("C:\\tmp\\test_file2")),
+ base::FilePath()},
+ {
+ base::FilePath(FILE_PATH_LITERAL("C:\\tmp\\test_file3")),
+ base::FilePath(),
+ },
+ };
+#else
+ const std::vector<ui::FileInfo> test_file_infos = {
+ {base::FilePath(FILE_PATH_LITERAL("/tmp/test_file1")), base::FilePath()},
+ {base::FilePath(FILE_PATH_LITERAL("/tmp/test_file2")), base::FilePath()},
+ {base::FilePath(FILE_PATH_LITERAL("/tmp/test_file3")), base::FilePath()},
+ };
+#endif
+ data.SetFilenames(test_file_infos);
+
+ ui::DropTargetEvent event(data, kClientPt, kScreenPt,
+ ui::DragDropTypes::DRAG_COPY);
+
+ // Simulate drag enter.
+ EXPECT_EQ(nullptr, view->current_drop_data_);
+ view->OnDragEntered(event);
+ ASSERT_NE(nullptr, view->current_drop_data_);
+
+#if defined(USE_X11)
+ // By design, OSExchangeDataProviderAuraX11::GetString returns an empty string
+ // if file data is also present.
+ EXPECT_TRUE(view->current_drop_data_->text.string().empty());
+#else
+ EXPECT_EQ(string_data, view->current_drop_data_->text.string());
+#endif
+
+ std::vector<ui::FileInfo> retrieved_file_infos =
+ view->current_drop_data_->filenames;
+ ASSERT_EQ(test_file_infos.size(), retrieved_file_infos.size());
+ for (size_t i = 0; i < retrieved_file_infos.size(); i++) {
+ EXPECT_EQ(test_file_infos[i].path, retrieved_file_infos[i].path);
+ EXPECT_EQ(test_file_infos[i].display_name,
+ retrieved_file_infos[i].display_name);
+ }
+
+ // Simulate drop.
+ auto callback = base::BindOnce(&WebContentsViewAuraTest::OnDropComplete,
+ base::Unretained(this));
+ view->RegisterDropCallbackForTesting(std::move(callback));
+
+ base::RunLoop run_loop;
+ async_drop_closure_ = run_loop.QuitClosure();
+
+ view->OnPerformDrop(event);
+ run_loop.Run();
+
+ CheckDropData(view);
+
+#if defined(USE_X11)
+ // By design, OSExchangeDataProviderAuraX11::GetString returns an empty string
+ // if file data is also present.
+ EXPECT_TRUE(drop_complete_data_->drop_data.text.string().empty());
+#else
+ EXPECT_EQ(string_data, drop_complete_data_->drop_data.text.string());
+#endif
+
+ retrieved_file_infos = drop_complete_data_->drop_data.filenames;
+ ASSERT_EQ(test_file_infos.size(), retrieved_file_infos.size());
+ for (size_t i = 0; i < retrieved_file_infos.size(); i++) {
+ EXPECT_EQ(test_file_infos[i].path, retrieved_file_infos[i].path);
+ EXPECT_EQ(test_file_infos[i].display_name,
+ retrieved_file_infos[i].display_name);
+ }
+}
+
+#if defined(OS_WIN) || defined(USE_X11)
+TEST_F(WebContentsViewAuraTest, DragDropFilesOriginateFromRenderer) {
+ WebContentsViewAura* view = GetView();
+ ui::OSExchangeData data;
+
+ const base::string16 string_data = base::ASCIIToUTF16("Some string data");
+ data.SetString(string_data);
+
+#if defined(OS_WIN)
+ const std::vector<ui::FileInfo> test_file_infos = {
+ {base::FilePath(FILE_PATH_LITERAL("C:\\tmp\\test_file1")),
+ base::FilePath()},
+ {base::FilePath(FILE_PATH_LITERAL("C:\\tmp\\test_file2")),
+ base::FilePath()},
+ {
+ base::FilePath(FILE_PATH_LITERAL("C:\\tmp\\test_file3")),
+ base::FilePath(),
+ },
+ };
+#else
+ const std::vector<ui::FileInfo> test_file_infos = {
+ {base::FilePath(FILE_PATH_LITERAL("/tmp/test_file1")), base::FilePath()},
+ {base::FilePath(FILE_PATH_LITERAL("/tmp/test_file2")), base::FilePath()},
+ {base::FilePath(FILE_PATH_LITERAL("/tmp/test_file3")), base::FilePath()},
+ };
+#endif
+ data.SetFilenames(test_file_infos);
+
+ // Simulate the drag originating in the renderer process, in which case
+ // any file data should be filtered out (anchor drag scenario).
+ data.MarkOriginatedFromRenderer();
+
+ ui::DropTargetEvent event(data, kClientPt, kScreenPt,
+ ui::DragDropTypes::DRAG_COPY);
+
+ // Simulate drag enter.
+ EXPECT_EQ(nullptr, view->current_drop_data_);
+ view->OnDragEntered(event);
+ ASSERT_NE(nullptr, view->current_drop_data_);
+
+#if defined(USE_X11)
+ // By design, OSExchangeDataProviderAuraX11::GetString returns an empty string
+ // if file data is also present.
+ EXPECT_TRUE(view->current_drop_data_->text.string().empty());
+#else
+ EXPECT_EQ(string_data, view->current_drop_data_->text.string());
+#endif
+
+ ASSERT_TRUE(view->current_drop_data_->filenames.empty());
+
+ // Simulate drop.
+ auto callback = base::BindOnce(&WebContentsViewAuraTest::OnDropComplete,
+ base::Unretained(this));
+ view->RegisterDropCallbackForTesting(std::move(callback));
+
+ base::RunLoop run_loop;
+ async_drop_closure_ = run_loop.QuitClosure();
+
+ view->OnPerformDrop(event);
+ run_loop.Run();
+
+ CheckDropData(view);
+
+#if defined(USE_X11)
+ // By design, OSExchangeDataProviderAuraX11::GetString returns an empty string
+ // if file data is also present.
+ EXPECT_TRUE(drop_complete_data_->drop_data.text.string().empty());
+#else
+ EXPECT_EQ(string_data, drop_complete_data_->drop_data.text.string());
+#endif
+
+ ASSERT_TRUE(drop_complete_data_->drop_data.filenames.empty());
+}
+#endif
+
+#if defined(OS_WIN)
+TEST_F(WebContentsViewAuraTest, DragDropVirtualFiles) {
+ WebContentsViewAura* view = GetView();
+ ui::OSExchangeData data;
+
+ const base::string16 string_data = base::ASCIIToUTF16("Some string data");
+ data.SetString(string_data);
+
+ const std::vector<std::pair<base::FilePath, std::string>>
+ test_filenames_and_contents = {
+ {base::FilePath(FILE_PATH_LITERAL("filename.txt")),
+ std::string("just some data")},
+ {base::FilePath(FILE_PATH_LITERAL("another filename.txt")),
+ std::string("just some data\0with\0nulls", 25)},
+ {base::FilePath(FILE_PATH_LITERAL("and another filename.txt")),
+ std::string("just some more data")},
+ };
+
+ data.provider().SetVirtualFileContentsForTesting(test_filenames_and_contents,
+ TYMED_ISTREAM);
+
+ ui::DropTargetEvent event(data, kClientPt, kScreenPt,
+ ui::DragDropTypes::DRAG_COPY);
+
+ // Simulate drag enter.
+ EXPECT_EQ(nullptr, view->current_drop_data_);
+ view->OnDragEntered(event);
+ ASSERT_NE(nullptr, view->current_drop_data_);
+
+ EXPECT_EQ(string_data, view->current_drop_data_->text.string());
+
+ const base::FilePath path_placeholder(FILE_PATH_LITERAL("temp.tmp"));
+ std::vector<ui::FileInfo> retrieved_file_infos =
+ view->current_drop_data_->filenames;
+ ASSERT_EQ(test_filenames_and_contents.size(), retrieved_file_infos.size());
+ for (size_t i = 0; i < retrieved_file_infos.size(); i++) {
+ EXPECT_EQ(test_filenames_and_contents[i].first,
+ retrieved_file_infos[i].display_name);
+ EXPECT_EQ(path_placeholder, retrieved_file_infos[i].path);
+ }
+
+ // Simulate drop (completes asynchronously since virtual file data is
+ // present).
+ auto callback = base::BindOnce(&WebContentsViewAuraTest::OnDropComplete,
+ base::Unretained(this));
+ view->RegisterDropCallbackForTesting(std::move(callback));
+
+ base::RunLoop run_loop;
+ async_drop_closure_ = run_loop.QuitClosure();
+
+ view->OnPerformDrop(event);
+ run_loop.Run();
+
+ CheckDropData(view);
+
+ EXPECT_EQ(string_data, drop_complete_data_->drop_data.text.string());
+
+ std::string read_contents;
+ base::FilePath temp_dir;
+ EXPECT_TRUE(base::GetTempDir(&temp_dir));
+
+ retrieved_file_infos = drop_complete_data_->drop_data.filenames;
+ ASSERT_EQ(test_filenames_and_contents.size(), retrieved_file_infos.size());
+ for (size_t i = 0; i < retrieved_file_infos.size(); i++) {
+ EXPECT_EQ(test_filenames_and_contents[i].first,
+ retrieved_file_infos[i].display_name);
+ // Check if the temp files that back the virtual files are actually created
+ // in the temp directory. Need to compare long file paths here because
+ // GetTempDir can return a short ("8.3") path if the test is run
+ // under a username that is too long.
+ EXPECT_EQ(base::MakeLongFilePath(temp_dir),
+ base::MakeLongFilePath(retrieved_file_infos[i].path.DirName()));
+ EXPECT_EQ(test_filenames_and_contents[i].first.Extension(),
+ retrieved_file_infos[i].path.Extension());
+ EXPECT_TRUE(
+ base::ReadFileToString(retrieved_file_infos[i].path, &read_contents));
+ EXPECT_EQ(test_filenames_and_contents[i].second, read_contents);
+ }
+}
+
+TEST_F(WebContentsViewAuraTest, DragDropVirtualFilesOriginateFromRenderer) {
+ WebContentsViewAura* view = GetView();
+ ui::OSExchangeData data;
+
+ const base::string16 string_data = base::ASCIIToUTF16("Some string data");
+ data.SetString(string_data);
+
+ const std::vector<std::pair<base::FilePath, std::string>>
+ test_filenames_and_contents = {
+ {base::FilePath(FILE_PATH_LITERAL("filename.txt")),
+ std::string("just some data")},
+ {base::FilePath(FILE_PATH_LITERAL("another filename.txt")),
+ std::string("just some data\0with\0nulls", 25)},
+ {base::FilePath(FILE_PATH_LITERAL("and another filename.txt")),
+ std::string("just some more data")},
+ };
+
+ data.provider().SetVirtualFileContentsForTesting(test_filenames_and_contents,
+ TYMED_ISTREAM);
+
+ // Simulate the drag originating in the renderer process, in which case
+ // any file data should be filtered out (anchor drag scenario).
+ data.MarkOriginatedFromRenderer();
+
+ ui::DropTargetEvent event(data, kClientPt, kScreenPt,
+ ui::DragDropTypes::DRAG_COPY);
+
+ // Simulate drag enter.
+ EXPECT_EQ(nullptr, view->current_drop_data_);
+ view->OnDragEntered(event);
+ ASSERT_NE(nullptr, view->current_drop_data_);
+
+ EXPECT_EQ(string_data, view->current_drop_data_->text.string());
+
+ ASSERT_TRUE(view->current_drop_data_->filenames.empty());
+
+ // Simulate drop (completes asynchronously since virtual file data is
+ // present).
+ auto callback = base::BindOnce(&WebContentsViewAuraTest::OnDropComplete,
+ base::Unretained(this));
+ view->RegisterDropCallbackForTesting(std::move(callback));
+
+ base::RunLoop run_loop;
+ async_drop_closure_ = run_loop.QuitClosure();
+
+ view->OnPerformDrop(event);
+ run_loop.Run();
+
+ CheckDropData(view);
+
+ EXPECT_EQ(string_data, drop_complete_data_->drop_data.text.string());
+
+ ASSERT_TRUE(drop_complete_data_->drop_data.filenames.empty());
+}
+
+TEST_F(WebContentsViewAuraTest, DragDropUrlData) {
+ WebContentsViewAura* view = GetView();
+ ui::OSExchangeData data;
+
+ const std::string url_spec = "https://www.wikipedia.org/";
+ const GURL url(url_spec);
+ const base::string16 url_title = base::ASCIIToUTF16("Wikipedia");
+ data.SetURL(url, url_title);
+
+ // SetUrl should also add a virtual .url (internet shortcut) file.
+ std::vector<ui::FileInfo> file_infos;
+ EXPECT_TRUE(data.GetVirtualFilenames(&file_infos));
+ ASSERT_EQ(1ULL, file_infos.size());
+ EXPECT_EQ(base::FilePath(url_title + base::ASCIIToUTF16(".url")),
+ file_infos[0].display_name);
+
+ ui::DropTargetEvent event(data, kClientPt, kScreenPt,
+ ui::DragDropTypes::DRAG_COPY);
+
+ // Simulate drag enter.
+ EXPECT_EQ(nullptr, view->current_drop_data_);
+ view->OnDragEntered(event);
+ ASSERT_NE(nullptr, view->current_drop_data_);
+
+ EXPECT_EQ(url_spec, view->current_drop_data_->url);
+ EXPECT_EQ(url_title, view->current_drop_data_->url_title);
+
+ // Virtual files should not have been retrieved if url data present.
+ ASSERT_TRUE(view->current_drop_data_->filenames.empty());
+
+ // Simulate drop (completes asynchronously since virtual file data is
+ // present).
+ auto callback = base::BindOnce(&WebContentsViewAuraTest::OnDropComplete,
+ base::Unretained(this));
+ view->RegisterDropCallbackForTesting(std::move(callback));
+
+ base::RunLoop run_loop;
+ async_drop_closure_ = run_loop.QuitClosure();
+
+ view->OnPerformDrop(event);
+ run_loop.Run();
+
+ CheckDropData(view);
+
+ EXPECT_EQ(url_spec, drop_complete_data_->drop_data.url);
+ EXPECT_EQ(url_title, drop_complete_data_->drop_data.url_title);
+
+ // Virtual files should not have been retrieved if url data present.
+ ASSERT_TRUE(drop_complete_data_->drop_data.filenames.empty());
+}
+#endif
+
} // namespace content
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 9d91d225fd9..ecaf30bcb7b 100644
--- a/chromium/content/browser/web_contents/web_contents_view_guest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_guest.cc
@@ -21,7 +21,6 @@
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/common/drop_data.h"
-#include "ui/base/ui_base_features.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@@ -74,17 +73,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 (!features::IsMultiProcessMash())
- parent_view->GetNativeView()->AddChild(platform_view_->GetNativeView());
+ parent_view->GetNativeView()->AddChild(platform_view_->GetNativeView());
#endif // defined(USE_AURA)
}
void WebContentsViewGuest::OnGuestDetached(WebContentsView* old_parent_view) {
#if defined(USE_AURA)
- if (!features::IsMultiProcessMash()) {
- old_parent_view->GetNativeView()->RemoveChild(
- platform_view_->GetNativeView());
- }
+ old_parent_view->GetNativeView()->RemoveChild(
+ platform_view_->GetNativeView());
#endif // defined(USE_AURA)
}
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 4266d4c817d..1b577eacbcc 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.h
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.h
@@ -19,8 +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 "content/common/web_contents_ns_view_bridge.mojom.h"
#include "content/public/browser/visibility.h"
-#include "content/public/common/web_contents_ns_view_bridge.mojom.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#import "ui/base/cocoa/views_hostable.h"
#include "ui/gfx/geometry/size.h"
@@ -94,6 +94,7 @@ class WebContentsViewMac : public WebContentsView,
RenderWidgetHostImpl* source_rwh) override;
void UpdateDragCursor(blink::WebDragOperation operation) override;
void GotFocus(RenderWidgetHostImpl* render_widget_host) override;
+ void LostFocus(RenderWidgetHostImpl* render_widget_host) override;
void TakeFocus(bool reverse) override;
void ShowContextMenu(RenderFrameHost* render_frame_host,
const ContextMenuParams& params) override;
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 2d24491812f..c6adcdd2b33 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm
@@ -14,6 +14,10 @@
#include "base/message_loop/message_loop_current.h"
#import "base/message_loop/message_pump_mac.h"
#include "base/threading/thread_restrictions.h"
+#include "components/remote_cocoa/browser/ns_view_ids.h"
+#include "components/remote_cocoa/common/bridge_factory.mojom.h"
+#include "content/app_shim_remote_cocoa/web_contents_ns_view_bridge.h"
+#import "content/app_shim_remote_cocoa/web_contents_view_cocoa.h"
#include "content/browser/download/drag_download_file.h"
#include "content/browser/download/drag_download_util.h"
#include "content/browser/frame_host/popup_menu_helper_mac.h"
@@ -22,17 +26,13 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/web_contents/web_contents_ns_view_bridge.h"
-#import "content/browser/web_contents/web_contents_view_cocoa.h"
#import "content/browser/web_contents/web_drag_dest_mac.h"
+#include "content/common/web_contents_ns_view_bridge.mojom-shared.h"
#include "content/public/browser/interstitial_page.h"
-#include "content/public/browser/ns_view_bridge_factory_host.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_view_delegate.h"
-#include "content/public/common/web_contents_ns_view_bridge.mojom-shared.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "ui/base/cocoa/cocoa_base_utils.h"
-#include "ui/base/cocoa/ns_view_ids.h"
#include "ui/gfx/mac/coordinate_conversion.h"
using blink::WebDragOperation;
@@ -89,7 +89,7 @@ WebContentsViewMac::WebContentsViewMac(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate)
: web_contents_(web_contents),
delegate_(delegate),
- ns_view_id_(ui::NSViewIds::GetNewId()),
+ ns_view_id_(remote_cocoa::GetNewNSViewId()),
ns_view_client_binding_(this),
deferred_close_weak_ptr_factory_(this) {}
@@ -246,6 +246,10 @@ void WebContentsViewMac::GotFocus(RenderWidgetHostImpl* render_widget_host) {
web_contents_->NotifyWebContentsFocused(render_widget_host);
}
+void WebContentsViewMac::LostFocus(RenderWidgetHostImpl* render_widget_host) {
+ web_contents_->NotifyWebContentsLostFocus(render_widget_host);
+}
+
// This is called when the renderer asks us to take focus back (i.e., it has
// iterated past the last focusable element on the page).
void WebContentsViewMac::TakeFocus(bool reverse) {
@@ -347,11 +351,8 @@ RenderWidgetHostViewBase* WebContentsViewMac::CreateViewForWidget(
// Add the RenderWidgetHostView to the ui::Layer heirarchy.
child_views_.push_back(view->GetWeakPtr());
if (views_host_) {
- NSViewBridgeFactoryHost* factory_host =
- NSViewBridgeFactoryHost::GetFromHostId(
- views_host_->GetViewsFactoryHostId());
-
- view->MigrateNSViewBridge(factory_host, ns_view_id_);
+ auto* remote_cocoa_application = views_host_->GetRemoteCocoaApplication();
+ view->MigrateNSViewBridge(remote_cocoa_application, ns_view_id_);
view->SetParentUiLayer(views_host_->GetUiLayer());
view->SetParentAccessibilityElement(views_host_accessibility_element_);
}
@@ -622,25 +623,31 @@ void WebContentsViewMac::DragPromisedFileTo(
void WebContentsViewMac::ViewsHostableAttach(ViewsHostableView::Host* host) {
views_host_ = host;
// Create an NSView in the target process, if one exists.
- uint64_t factory_host_id = views_host_->GetViewsFactoryHostId();
- NSViewBridgeFactoryHost* factory_host =
- NSViewBridgeFactoryHost::GetFromHostId(factory_host_id);
- if (factory_host) {
+ auto* remote_cocoa_application = views_host_->GetRemoteCocoaApplication();
+ if (remote_cocoa_application) {
mojom::WebContentsNSViewClientAssociatedPtr client;
ns_view_client_binding_.Bind(mojo::MakeRequest(&client));
mojom::WebContentsNSViewBridgeAssociatedRequest bridge_request =
mojo::MakeRequest(&ns_view_bridge_remote_);
- factory_host->GetFactory()->CreateWebContentsNSViewBridge(
- ns_view_id_, client.PassInterface(), std::move(bridge_request));
+ // Cast from mojom::WebContentsNSViewClientPtr and
+ // mojom::WebContentsNSViewBridgeRequest to the public interfaces
+ // accepted by the application.
+ // TODO(ccameron): Remove the need for this cast.
+ // https://crbug.com/888290
+ mojo::AssociatedInterfacePtrInfo<remote_cocoa::mojom::StubInterface>
+ stub_client(client.PassInterface().PassHandle(), 0);
+ remote_cocoa::mojom::StubInterfaceAssociatedRequest stub_bridge_request(
+ bridge_request.PassHandle());
+
+ remote_cocoa_application->CreateWebContentsNSView(
+ ns_view_id_, std::move(stub_client), std::move(stub_bridge_request));
ns_view_bridge_remote_->SetParentNSView(views_host_->GetNSViewId());
// Because this view is being displayed from a remote process, reset the
// in-process NSView's client pointer, so that the in-process NSView will
// not call back into |this|.
[cocoa_view() setClient:nullptr];
- } else if (factory_host_id != NSViewBridgeFactoryHost::kLocalDirectHostId) {
- LOG(ERROR) << "Failed to look up NSViewBridgeFactoryHost!";
}
// TODO(https://crbug.com/933679): WebContentsNSViewBridge::SetParentView
@@ -650,7 +657,7 @@ void WebContentsViewMac::ViewsHostableAttach(ViewsHostableView::Host* host) {
// ns_view_bridge_local_->SetParentNSView(views_host_->GetNSViewId());
for (auto* rwhv_mac : GetChildViews()) {
- rwhv_mac->MigrateNSViewBridge(factory_host, ns_view_id_);
+ rwhv_mac->MigrateNSViewBridge(remote_cocoa_application, ns_view_id_);
rwhv_mac->SetParentUiLayer(views_host_->GetUiLayer());
}
}
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 a0ac2ad1928..01247071277 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
@@ -6,7 +6,7 @@
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
-#import "content/browser/web_contents/web_contents_view_cocoa.h"
+#import "content/app_shim_remote_cocoa/web_contents_view_cocoa.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/content/browser/web_contents/web_drag_dest_mac.mm b/chromium/content/browser/web_contents/web_drag_dest_mac.mm
index 9423f9c8a22..f4250007968 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_dest_mac.mm
@@ -12,11 +12,11 @@
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/web_contents_ns_view_bridge.mojom.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_drag_dest_delegate.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/drop_data.h"
-#include "content/public/common/web_contents_ns_view_bridge.mojom.h"
#include "third_party/blink/public/platform/web_input_event.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
#include "ui/base/clipboard/clipboard_constants.h"
diff --git a/chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm b/chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm
index fe426572944..962a73434fb 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm
+++ b/chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "content/browser/web_contents/web_drag_source_mac.h"
+#import "content/app_shim_remote_cocoa/web_drag_source_mac.h"
#include "base/memory/ref_counted.h"
#include "content/browser/web_contents/web_contents_impl.h"
diff --git a/chromium/content/browser/web_contents_binding_set_browsertest.cc b/chromium/content/browser/web_contents_binding_set_browsertest.cc
index 50b293fdb34..c375f877460 100644
--- a/chromium/content/browser/web_contents_binding_set_browsertest.cc
+++ b/chromium/content/browser/web_contents_binding_set_browsertest.cc
@@ -77,10 +77,11 @@ IN_PROC_BROWSER_TEST_F(WebContentsBindingSetBrowserTest, OverrideForTesting) {
// Now override the binder for this interface. It quits |run_loop| whenever
// an incoming interface request is received.
base::RunLoop run_loop;
- WebContentsBindingSet::GetForWebContents<
- mojom::BrowserAssociatedInterfaceTestDriver>(web_contents)
- ->SetBinderForTesting(
- std::make_unique<TestInterfaceBinder>(run_loop.QuitClosure()));
+ auto* binding_set = WebContentsBindingSet::GetForWebContents<
+ mojom::BrowserAssociatedInterfaceTestDriver>(web_contents);
+
+ TestInterfaceBinder test_binder(run_loop.QuitClosure());
+ binding_set->SetBinder(&test_binder);
// Simulate an inbound request for the test interface. This should get routed
// to the overriding binder and allow the test to complete.
@@ -92,6 +93,8 @@ IN_PROC_BROWSER_TEST_F(WebContentsBindingSetBrowserTest, OverrideForTesting) {
mojo::MakeRequestAssociatedWithDedicatedPipe(&override_client)
.PassHandle());
run_loop.Run();
+
+ binding_set->SetBinder(nullptr);
}
IN_PROC_BROWSER_TEST_F(WebContentsBindingSetBrowserTest, CloseOnFrameDeletion) {
diff --git a/chromium/content/browser/web_package/mock_signed_exchange_handler.cc b/chromium/content/browser/web_package/mock_signed_exchange_handler.cc
index d85f77eedbd..1b6829e7f97 100644
--- a/chromium/content/browser/web_package/mock_signed_exchange_handler.cc
+++ b/chromium/content/browser/web_package/mock_signed_exchange_handler.cc
@@ -20,13 +20,15 @@ MockSignedExchangeHandlerParams::MockSignedExchangeHandlerParams(
net::Error error,
const GURL& inner_url,
const std::string& mime_type,
- std::vector<std::string> response_headers)
+ std::vector<std::string> response_headers,
+ base::Optional<net::SHA256HashValue> header_integrity)
: outer_url(outer_url),
result(result),
error(error),
inner_url(inner_url),
mime_type(mime_type),
- response_headers(std::move(response_headers)) {}
+ response_headers(std::move(response_headers)),
+ header_integrity(std::move(header_integrity)) {}
MockSignedExchangeHandlerParams::MockSignedExchangeHandlerParams(
const MockSignedExchangeHandlerParams& other) = default;
@@ -35,7 +37,8 @@ MockSignedExchangeHandlerParams::~MockSignedExchangeHandlerParams() = default;
MockSignedExchangeHandler::MockSignedExchangeHandler(
const MockSignedExchangeHandlerParams& params,
std::unique_ptr<net::SourceStream> body,
- ExchangeHeadersCallback headers_callback) {
+ ExchangeHeadersCallback headers_callback)
+ : header_integrity_(params.header_integrity) {
network::ResourceResponseHead head;
if (params.error == net::OK) {
head.headers =
@@ -53,6 +56,11 @@ MockSignedExchangeHandler::MockSignedExchangeHandler(
params.inner_url, head, std::move(body)));
}
+base::Optional<net::SHA256HashValue>
+MockSignedExchangeHandler::ComputeHeaderIntegrity() const {
+ return header_integrity_;
+}
+
MockSignedExchangeHandler::~MockSignedExchangeHandler() {}
MockSignedExchangeHandlerFactory::MockSignedExchangeHandlerFactory(
diff --git a/chromium/content/browser/web_package/mock_signed_exchange_handler.h b/chromium/content/browser/web_package/mock_signed_exchange_handler.h
index 6c63e390d51..02038da7e96 100644
--- a/chromium/content/browser/web_package/mock_signed_exchange_handler.h
+++ b/chromium/content/browser/web_package/mock_signed_exchange_handler.h
@@ -9,6 +9,7 @@
#include <vector>
#include "content/browser/web_package/signed_exchange_handler.h"
+#include "net/base/hash_value.h"
#include "url/gurl.h"
namespace content {
@@ -18,12 +19,14 @@ class SignedExchangeCertFetcherFactory;
class MockSignedExchangeHandlerParams {
public:
// |mime_type| and |response_headers| are ignored if |error| is not net::OK.
- MockSignedExchangeHandlerParams(const GURL& outer_url,
- SignedExchangeLoadResult result,
- net::Error error,
- const GURL& inner_url,
- const std::string& mime_type,
- std::vector<std::string> response_headers);
+ MockSignedExchangeHandlerParams(
+ const GURL& outer_url,
+ SignedExchangeLoadResult result,
+ net::Error error,
+ const GURL& inner_url,
+ const std::string& mime_type,
+ std::vector<std::string> response_headers,
+ base::Optional<net::SHA256HashValue> header_integrity);
MockSignedExchangeHandlerParams(const MockSignedExchangeHandlerParams& other);
~MockSignedExchangeHandlerParams();
const GURL outer_url;
@@ -32,6 +35,7 @@ class MockSignedExchangeHandlerParams {
const GURL inner_url;
const std::string mime_type;
const std::vector<std::string> response_headers;
+ const base::Optional<net::SHA256HashValue> header_integrity;
};
class MockSignedExchangeHandler final : public SignedExchangeHandler {
@@ -39,9 +43,12 @@ class MockSignedExchangeHandler final : public SignedExchangeHandler {
MockSignedExchangeHandler(const MockSignedExchangeHandlerParams& params,
std::unique_ptr<net::SourceStream> body,
ExchangeHeadersCallback headers_callback);
- ~MockSignedExchangeHandler();
+ ~MockSignedExchangeHandler() override;
+ base::Optional<net::SHA256HashValue> ComputeHeaderIntegrity() const override;
private:
+ const base::Optional<net::SHA256HashValue> header_integrity_;
+
DISALLOW_COPY_AND_ASSIGN(MockSignedExchangeHandler);
};
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 b6ee73bd3e0..8537b8bbb2e 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc
@@ -5,17 +5,20 @@
#include "content/browser/web_package/signed_exchange_cert_fetcher.h"
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/format_macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
+#include "content/browser/data_url_loader_factory.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
#include "content/browser/web_package/signed_exchange_reporter.h"
#include "content/browser/web_package/signed_exchange_utils.h"
+#include "content/common/single_request_url_loader_factory.h"
#include "content/common/throttling_url_loader.h"
#include "content/public/common/resource_type.h"
#include "content/public/common/url_loader_throttle.h"
@@ -25,6 +28,7 @@
#include "net/base/load_flags.h"
#include "net/http/http_status_code.h"
#include "services/network/loader_util.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace content {
@@ -116,9 +120,7 @@ SignedExchangeCertFetcher::SignedExchangeCertFetcher(
static_cast<int>(ResourceType::kSubResource);
// Cert requests should not send credential informartion, because the default
// credentials mode of Fetch is "omit".
- resource_request_->load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA |
- net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES;
+ resource_request_->allow_credentials = false;
resource_request_->headers.SetHeader(network::kAcceptHeader,
kCertChainMimeType);
if (force_fetch) {
@@ -141,6 +143,15 @@ void SignedExchangeCertFetcher::Start() {
devtools_proxy_->CertificateRequestSent(*cert_request_id_,
*resource_request_);
}
+ // When NetworkService enabled, data URL is not handled by the passed
+ // URLRequestContext's SharedURLLoaderFactory.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
+ resource_request_->url.SchemeIs(url::kDataScheme)) {
+ shared_url_loader_factory_ =
+ base::MakeRefCounted<SingleRequestURLLoaderFactory>(
+ base::BindOnce(&SignedExchangeCertFetcher::OnDataURLRequest,
+ base::Unretained(this)));
+ }
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
std::move(shared_url_loader_factory_), std::move(throttles_),
0 /* routing_id */,
@@ -287,7 +298,7 @@ void SignedExchangeCertFetcher::OnUploadProgress(
}
void SignedExchangeCertFetcher::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
+ mojo_base::BigBuffer data) {
// Cert fetching doesn't use cached metadata.
NOTREACHED();
}
@@ -320,6 +331,17 @@ void SignedExchangeCertFetcher::OnComplete(
Abort();
}
+void SignedExchangeCertFetcher::OnDataURLRequest(
+ const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderRequest url_loader_request,
+ network::mojom::URLLoaderClientPtr url_loader_client_ptr) {
+ data_url_loader_factory_ = std::make_unique<DataURLLoaderFactory>();
+ data_url_loader_factory_->CreateLoaderAndStart(
+ std::move(url_loader_request), 0, 0, 0, resource_request,
+ std::move(url_loader_client_ptr),
+ net::MutableNetworkTrafficAnnotationTag(kCertFetcherTrafficAnnotation));
+}
+
void SignedExchangeCertFetcher::MaybeNotifyCompletionToDevtools(
const network::URLLoaderCompletionStatus& status) {
if (!devtools_proxy_ || has_notified_completion_to_devtools_)
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 7e3f3a318a2..6e46cc4fddd 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher.h
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher.h
@@ -20,6 +20,9 @@
namespace network {
class SharedURLLoaderFactory;
+namespace mojom {
+class URLLoaderFactory;
+} // namespace mojom
} // namespace network
namespace mojo {
@@ -94,12 +97,16 @@ class CONTENT_EXPORT SignedExchangeCertFetcher
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
+ void OnDataURLRequest(const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderRequest,
+ network::mojom::URLLoaderClientPtr);
+
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles_;
std::unique_ptr<network::ResourceRequest> resource_request_;
@@ -118,6 +125,8 @@ class CONTENT_EXPORT SignedExchangeCertFetcher
SignedExchangeReporter* reporter_;
base::Optional<base::UnguessableToken> cert_request_id_;
+ std::unique_ptr<network::mojom::URLLoaderFactory> data_url_loader_factory_;
+
DISALLOW_COPY_AND_ASSIGN(SignedExchangeCertFetcher);
};
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 8153505ef83..561c13770d4 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
@@ -4,6 +4,7 @@
#include "content/browser/web_package/signed_exchange_cert_fetcher.h"
+#include "base/base64.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/optional.h"
@@ -20,6 +21,7 @@
#include "net/cert/x509_util.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -188,11 +190,13 @@ class SignedExchangeCertFetcherTest : public testing::Test {
return net::x509_util::CryptoBufferAsStringPiece(cert.cert_buffer());
}
- static mojo::ScopedDataPipeConsumerHandle CreateTestDataFilledDataPipe() {
+ static std::string CreateTestData() {
scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
- const std::string message =
- CreateCertMessage(CreateCertMessageFromCert(*certificate));
+ return CreateCertMessage(CreateCertMessageFromCert(*certificate));
+ }
+ static mojo::ScopedDataPipeConsumerHandle CreateTestDataFilledDataPipe() {
+ auto message = CreateTestData();
mojo::DataPipe data_pipe(message.size());
CHECK(mojo::BlockingCopyFromString(message, data_pipe.producer_handle));
return std::move(data_pipe.consumer_handle);
@@ -264,9 +268,7 @@ TEST_F(SignedExchangeCertFetcherTest, Simple) {
EXPECT_EQ(url_, mock_loader_factory_.url_request()->url);
EXPECT_EQ(static_cast<int>(ResourceType::kSubResource),
mock_loader_factory_.url_request()->resource_type);
- EXPECT_EQ(net::LOAD_DO_NOT_SEND_AUTH_DATA | net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES,
- mock_loader_factory_.url_request()->load_flags);
+ EXPECT_FALSE(mock_loader_factory_.url_request()->allow_credentials);
EXPECT_TRUE(mock_loader_factory_.url_request()->request_initiator->opaque());
std::string accept;
EXPECT_TRUE(
@@ -322,10 +324,9 @@ TEST_F(SignedExchangeCertFetcherTest, ForceFetchAndFail) {
EXPECT_EQ(url_, mock_loader_factory_.url_request()->url);
EXPECT_EQ(static_cast<int>(ResourceType::kSubResource),
mock_loader_factory_.url_request()->resource_type);
- EXPECT_EQ(net::LOAD_DO_NOT_SEND_AUTH_DATA | net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DISABLE_CACHE |
- net::LOAD_BYPASS_CACHE,
+ EXPECT_EQ(net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_CACHE,
mock_loader_factory_.url_request()->load_flags);
+ EXPECT_FALSE(mock_loader_factory_.url_request()->allow_credentials);
mock_loader_factory_.client_ptr()->OnComplete(
network::URLLoaderCompletionStatus(net::ERR_INVALID_SIGNED_EXCHANGE));
@@ -780,19 +781,32 @@ TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_AfterReceivingBody) {
}
TEST_F(SignedExchangeCertFetcherTest, DataURL) {
- const GURL data_url = GURL("data:application/cert-chain+cbor,foobar");
+ std::string data_url_string = "data:application/cert-chain+cbor";
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ std::string output;
+ base::Base64Encode(CreateTestData(), &output);
+ data_url_string += ";base64," + output;
+ } else {
+ data_url_string += ",foobar";
+ }
+ const GURL data_url = GURL(data_url_string);
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);
+ // SignedExchangeCertFetcher directly creates DataURLLoaderFactory for data
+ // scheme.
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ 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));
+ }
- mock_loader_factory_.client_ptr()->OnStartLoadingResponseBody(
- CreateTestDataFilledDataPipe());
- mock_loader_factory_.client_ptr()->OnComplete(
- network::URLLoaderCompletionStatus(net::OK));
RunUntilIdle();
EXPECT_TRUE(callback_called_);
EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
@@ -805,11 +819,16 @@ 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);
+ // SignedExchangeCertFetcher directly creates DataURLLoaderFactory for data
+ // scheme.
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ 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_);
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 8b667cb8d9a..7237f875874 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
@@ -4,14 +4,22 @@
#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/no_destructor.h"
+#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "components/cbor/reader.h"
#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/browser/web_package/signed_exchange_utils.h"
+#include "content/public/browser/content_browser_client.h"
+#include "crypto/sha2.h"
+#include "net/cert/asn1_util.h"
#include "net/cert/x509_certificate.h"
+#include "net/cert/x509_util.h"
+#include "services/network/public/cpp/network_switches.h"
namespace content {
@@ -170,4 +178,69 @@ SignedExchangeCertificateChain::SignedExchangeCertificateChain(
SignedExchangeCertificateChain::~SignedExchangeCertificateChain() = default;
+bool SignedExchangeCertificateChain::ShouldIgnoreErrors() const {
+ return IgnoreErrorsSPKIList::ShouldIgnoreErrors(cert_);
+}
+
+std::unique_ptr<SignedExchangeCertificateChain::IgnoreErrorsSPKIList>&
+SignedExchangeCertificateChain::IgnoreErrorsSPKIList::GetInstance() {
+ static base::NoDestructor<std::unique_ptr<IgnoreErrorsSPKIList>> instance(
+ std::make_unique<IgnoreErrorsSPKIList>(
+ *base::CommandLine::ForCurrentProcess()));
+ return *instance;
+}
+
+std::unique_ptr<SignedExchangeCertificateChain::IgnoreErrorsSPKIList>
+SignedExchangeCertificateChain::IgnoreErrorsSPKIList::SetInstanceForTesting(
+ std::unique_ptr<IgnoreErrorsSPKIList> p) {
+ GetInstance().swap(p);
+ return p;
+}
+
+SignedExchangeCertificateChain::IgnoreErrorsSPKIList::IgnoreErrorsSPKIList(
+ const std::string& spki_list) {
+ Parse(spki_list);
+}
+
+SignedExchangeCertificateChain::IgnoreErrorsSPKIList::IgnoreErrorsSPKIList(
+ const base::CommandLine& command_line) {
+ if (!GetContentClient()->browser()->CanIgnoreCertificateErrorIfNeeded())
+ return;
+ Parse(command_line.GetSwitchValueASCII(
+ network::switches::kIgnoreCertificateErrorsSPKIList));
+}
+
+void SignedExchangeCertificateChain::IgnoreErrorsSPKIList::Parse(
+ const std::string& spki_list) {
+ hash_set_ =
+ network::IgnoreErrorsCertVerifier::MakeWhitelist(base::SplitString(
+ spki_list, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL));
+}
+
+SignedExchangeCertificateChain::IgnoreErrorsSPKIList::~IgnoreErrorsSPKIList() =
+ default;
+
+// static
+bool SignedExchangeCertificateChain::IgnoreErrorsSPKIList::ShouldIgnoreErrors(
+ scoped_refptr<net::X509Certificate> certificate) {
+ return GetInstance()->ShouldIgnoreErrorsInternal(certificate);
+}
+
+bool SignedExchangeCertificateChain::IgnoreErrorsSPKIList::
+ ShouldIgnoreErrorsInternal(
+ scoped_refptr<net::X509Certificate> certificate) {
+ if (hash_set_.empty())
+ return false;
+
+ base::StringPiece spki;
+ if (!net::asn1::ExtractSPKIFromDERCert(
+ net::x509_util::CryptoBufferAsStringPiece(certificate->cert_buffer()),
+ &spki)) {
+ return false;
+ }
+ net::SHA256HashValue hash;
+ crypto::SHA256HashString(spki, &hash, sizeof(net::SHA256HashValue));
+ return hash_set_.find(hash) != hash_set_.end();
+}
+
} // namespace content
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 26f9a12caf5..520f6149539 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
@@ -13,6 +13,11 @@
#include "base/strings/string_piece_forward.h"
#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/common/content_export.h"
+#include "services/network/ignore_errors_cert_verifier.h"
+
+namespace base {
+class CommandLine;
+} // namespace base
namespace net {
class X509Certificate;
@@ -27,6 +32,38 @@ class SignedExchangeDevToolsProxy;
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cert-chain-format
class CONTENT_EXPORT SignedExchangeCertificateChain {
public:
+ // An utility class which holds a set of certificates whose errors should be
+ // ignored. It parses a comma-delimited list of base64-encoded SHA-256 SPKI
+ // fingerprints, and can query if a certificate is included in the set.
+ // CONTENT_EXPORT since it is used from the unit test.
+ class CONTENT_EXPORT IgnoreErrorsSPKIList {
+ public:
+ static bool ShouldIgnoreErrors(
+ scoped_refptr<net::X509Certificate> certificate);
+
+ explicit IgnoreErrorsSPKIList(const base::CommandLine& command_line);
+ ~IgnoreErrorsSPKIList();
+
+ // Used for tests to override the instance. Returns the old instance, which
+ // should be restored when the test's done.
+ static std::unique_ptr<IgnoreErrorsSPKIList> SetInstanceForTesting(
+ std::unique_ptr<IgnoreErrorsSPKIList> p);
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(SignedExchangeCertificateChainTest,
+ IgnoreErrorsSPKIList);
+
+ static std::unique_ptr<IgnoreErrorsSPKIList>& GetInstance();
+
+ explicit IgnoreErrorsSPKIList(const std::string& spki_list);
+ void Parse(const std::string& spki_list);
+ bool ShouldIgnoreErrorsInternal(
+ scoped_refptr<net::X509Certificate> certificate);
+
+ network::IgnoreErrorsCertVerifier::SPKIHashSet hash_set_;
+ DISALLOW_COPY_AND_ASSIGN(IgnoreErrorsSPKIList);
+ };
+
static std::unique_ptr<SignedExchangeCertificateChain> Parse(
base::span<const uint8_t> cert_response_body,
SignedExchangeDevToolsProxy* devtools_proxy);
@@ -42,6 +79,11 @@ class CONTENT_EXPORT SignedExchangeCertificateChain {
const std::string& ocsp() const { return ocsp_; }
const std::string& sct() const { return sct_; }
+ // Returns true if SPKI hash of |cert_| is included in the
+ // --ignore-certificate-errors-spki-list command line flag, and
+ // ContentBrowserClient::CanIgnoreCertificateErrorIfNeeded() returns true.
+ bool ShouldIgnoreErrors() const;
+
private:
scoped_refptr<net::X509Certificate> cert_;
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 7e5a3df4c26..0d93a8ebc39 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
@@ -11,6 +11,7 @@
#include "base/strings/string_piece.h"
#include "components/cbor/values.h"
#include "components/cbor/writer.h"
+#include "content/browser/web_package/signed_exchange_test_utils.h"
#include "content/public/common/content_paths.h"
#include "net/cert/x509_util.h"
#include "net/test/cert_test_util.h"
@@ -25,6 +26,16 @@ cbor::Value CBORByteString(base::StringPiece str) {
return cbor::Value(str, cbor::Value::Type::BYTE_STRING);
}
+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");
+
+ return net::CreateCertificateChainFromFile(
+ dir_path, cert_file, net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
+}
+
} // namespace
TEST(SignedExchangeCertificateParseTest, Empty) {
@@ -199,4 +210,28 @@ TEST(SignedExchangeCertificateParseTest, ParseGoldenFile) {
ASSERT_TRUE(parsed);
}
+TEST(SignedExchangeCertificateChainTest, IgnoreErrorsSPKIList) {
+ SignedExchangeCertificateChain::IgnoreErrorsSPKIList ignore_nothing("");
+ SignedExchangeCertificateChain::IgnoreErrorsSPKIList ignore_ecdsap256(
+ kPEMECDSAP256SPKIHash);
+ SignedExchangeCertificateChain::IgnoreErrorsSPKIList ignore_ecdsap384(
+ kPEMECDSAP384SPKIHash);
+ SignedExchangeCertificateChain::IgnoreErrorsSPKIList ignore_both(
+ std::string(kPEMECDSAP256SPKIHash) + "," + kPEMECDSAP384SPKIHash);
+
+ scoped_refptr<net::X509Certificate> cert_ecdsap256 =
+ LoadCertificate("prime256v1-sha256.public.pem");
+ scoped_refptr<net::X509Certificate> cert_ecdsap384 =
+ LoadCertificate("secp384r1-sha256.public.pem");
+
+ EXPECT_FALSE(ignore_nothing.ShouldIgnoreErrorsInternal(cert_ecdsap256));
+ EXPECT_FALSE(ignore_nothing.ShouldIgnoreErrorsInternal(cert_ecdsap384));
+ EXPECT_TRUE(ignore_ecdsap256.ShouldIgnoreErrorsInternal(cert_ecdsap256));
+ EXPECT_FALSE(ignore_ecdsap256.ShouldIgnoreErrorsInternal(cert_ecdsap384));
+ EXPECT_FALSE(ignore_ecdsap384.ShouldIgnoreErrorsInternal(cert_ecdsap256));
+ EXPECT_TRUE(ignore_ecdsap384.ShouldIgnoreErrorsInternal(cert_ecdsap384));
+ EXPECT_TRUE(ignore_both.ShouldIgnoreErrorsInternal(cert_ecdsap256));
+ EXPECT_TRUE(ignore_both.ShouldIgnoreErrorsInternal(cert_ecdsap384));
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_envelope.cc b/chromium/content/browser/web_package/signed_exchange_envelope.cc
index e5033462d25..82000263d68 100644
--- a/chromium/content/browser/web_package/signed_exchange_envelope.cc
+++ b/chromium/content/browser/web_package/signed_exchange_envelope.cc
@@ -105,7 +105,7 @@ bool IsCacheableBySharedCache(const SignedExchangeEnvelope::HeaderMap& headers,
net::HttpUtil::NameValuePairsIterator::Values::NOT_REQUIRED,
net::HttpUtil::NameValuePairsIterator::Quotes::STRICT_QUOTES);
while (it.GetNext()) {
- auto name = it.name();
+ base::StringPiece name = it.name_piece();
if (name == "no-store" || name == "private") {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy,
@@ -361,11 +361,20 @@ SignedExchangeEnvelope::BuildHttpResponseHeaders() const {
}
header_str.append("\r\n");
return base::MakeRefCounted<net::HttpResponseHeaders>(
- net::HttpUtil::AssembleRawHeaders(header_str.c_str(), header_str.size()));
+ net::HttpUtil::AssembleRawHeaders(header_str));
}
void SignedExchangeEnvelope::set_cbor_header(base::span<const uint8_t> data) {
cbor_header_ = std::vector<uint8_t>(data.begin(), data.end());
}
+net::SHA256HashValue SignedExchangeEnvelope::ComputeHeaderIntegrity() const {
+ net::SHA256HashValue hash;
+ crypto::SHA256HashString(
+ base::StringPiece(reinterpret_cast<const char*>(cbor_header().data()),
+ cbor_header().size()),
+ &hash, sizeof(net::SHA256HashValue));
+ return hash;
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_envelope.h b/chromium/content/browser/web_package/signed_exchange_envelope.h
index 731684c334e..e23b09a571c 100644
--- a/chromium/content/browser/web_package/signed_exchange_envelope.h
+++ b/chromium/content/browser/web_package/signed_exchange_envelope.h
@@ -15,6 +15,7 @@
#include "base/strings/string_util.h"
#include "content/browser/web_package/signed_exchange_signature_header_field.h"
#include "content/common/content_export.h"
+#include "crypto/sha2.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "url/gurl.h"
@@ -77,6 +78,9 @@ class CONTENT_EXPORT SignedExchangeEnvelope {
signature_ = sig;
}
+ // Returns the header integrity value of the loaded signed exchange.
+ net::SHA256HashValue ComputeHeaderIntegrity() const;
+
private:
std::vector<uint8_t> cbor_header_;
diff --git a/chromium/content/browser/web_package/signed_exchange_handler.cc b/chromium/content/browser/web_package/signed_exchange_handler.cc
index af01d132ea6..22fad8e614b 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler.cc
+++ b/chromium/content/browser/web_package/signed_exchange_handler.cc
@@ -34,6 +34,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/common/url_loader_throttle.h"
+#include "crypto/sha2.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "mojo/public/cpp/system/string_data_pipe_producer.h"
#include "net/base/io_buffer.h"
@@ -502,7 +503,7 @@ void SignedExchangeHandler::OnCertReceived(
DCHECK(version_.has_value());
const SignedExchangeSignatureVerifier::Result verify_result =
SignedExchangeSignatureVerifier::Verify(
- *version_, *envelope_, unverified_cert_chain_->cert(),
+ *version_, *envelope_, unverified_cert_chain_.get(),
GetVerificationTime(), devtools_proxy_.get());
UMA_HISTOGRAM_ENUMERATION(kHistogramSignatureVerificationResult,
verify_result);
@@ -552,7 +553,8 @@ SignedExchangeLoadResult SignedExchangeHandler::CheckCertRequirements(
net::x509_util::CryptoBufferAsStringPiece(
verified_cert->cert_buffer())) &&
!base::FeatureList::IsEnabled(
- features::kAllowSignedHTTPExchangeCertsWithoutExtension)) {
+ features::kAllowSignedHTTPExchangeCertsWithoutExtension) &&
+ !unverified_cert_chain_->ShouldIgnoreErrors()) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(),
"Certificate must have CanSignHttpExchangesDraft extension. To ignore "
@@ -575,7 +577,8 @@ SignedExchangeLoadResult SignedExchangeHandler::CheckCertRequirements(
// 2019-05-01 00:00:00 UTC.
const base::Time kRequirementStartDateForIssuance =
base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1556668800);
- if (verified_cert->valid_start() >= kRequirementStartDateForIssuance) {
+ if (verified_cert->valid_start() >= kRequirementStartDateForIssuance &&
+ !unverified_cert_chain_->ShouldIgnoreErrors()) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(),
"Signed Exchange's certificate issued after 2019-05-01 must not have "
@@ -587,7 +590,8 @@ SignedExchangeLoadResult SignedExchangeHandler::CheckCertRequirements(
// 2019-08-01 00:00:00 UTC.
const base::Time kRequirementStartDateForVerification =
base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1564617600);
- if (GetVerificationTime() >= kRequirementStartDateForVerification) {
+ if (GetVerificationTime() >= kRequirementStartDateForVerification &&
+ !unverified_cert_chain_->ShouldIgnoreErrors()) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(),
"After 2019-08-01, Signed Exchange's certificate must not have a "
@@ -704,6 +708,7 @@ void SignedExchangeHandler::OnVerifyCert(
response_head.load_timing.send_start = now;
response_head.load_timing.send_end = now;
response_head.load_timing.receive_headers_end = now;
+ response_head.content_length = response_head.headers->GetContentLength();
auto body_stream = CreateResponseBodyStream();
if (!body_stream) {
@@ -778,4 +783,11 @@ SignedExchangeHandler::CreateResponseBodyStream() {
std::move(source_));
}
+base::Optional<net::SHA256HashValue>
+SignedExchangeHandler::ComputeHeaderIntegrity() const {
+ if (!envelope_)
+ return base::nullopt;
+ return envelope_->ComputeHeaderIntegrity();
+}
+
} // 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 ffef9dab7f7..351ebd80229 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler.h
+++ b/chromium/content/browser/web_package/signed_exchange_handler.h
@@ -26,6 +26,7 @@
namespace net {
class CertVerifyResult;
class DrainableIOBuffer;
+struct SHA256HashValue;
class SourceStream;
struct OCSPVerifyResult;
} // namespace net
@@ -96,10 +97,15 @@ class CONTENT_EXPORT SignedExchangeHandler {
std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
SignedExchangeReporter* reporter,
base::RepeatingCallback<int(void)> frame_tree_node_id_getter);
- ~SignedExchangeHandler();
+ virtual ~SignedExchangeHandler();
int64_t GetExchangeHeaderLength() const { return exchange_header_length_; }
+ // Returns the header integrity value of the loaded signed exchange if
+ // available. This is available after |headers_callback| is called.
+ // Otherwise returns nullopt.
+ virtual base::Optional<net::SHA256HashValue> ComputeHeaderIntegrity() const;
+
protected:
SignedExchangeHandler();
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 037cdfbc7f2..b1bf2628c84 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc
@@ -17,6 +17,8 @@
#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
#include "content/browser/web_package/signed_exchange_request_matcher.h"
#include "content/browser/web_package/signed_exchange_signature_verifier.h"
+#include "content/browser/web_package/signed_exchange_test_utils.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_paths.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -32,10 +34,12 @@
#include "net/test/test_data_directory.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/network_context.h"
+#include "services/network/public/cpp/network_switches.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
+using testing::DoAll;
using testing::ElementsAre;
using testing::Property;
using testing::Return;
@@ -63,6 +67,10 @@ constexpr char kDummySCTBytes[] = {
constexpr base::StringPiece kDummySCTList(kDummySCTBytes,
sizeof(kDummySCTBytes));
+class TestBrowserClient : public ContentBrowserClient {
+ bool CanIgnoreCertificateErrorIfNeeded() override { return true; }
+};
+
std::string GetTestFileContents(base::StringPiece name) {
base::FilePath path;
base::PathService::Get(content::DIR_TEST_DATA, &path);
@@ -144,8 +152,6 @@ class MockCTVerifier : public net::CTVerifier {
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 {
@@ -176,6 +182,7 @@ class SignedExchangeHandlerTest
}
void SetUp() override {
+ original_client_ = SetBrowserClientForTesting(&browser_client_);
SignedExchangeHandler::SetVerificationTimeForTesting(
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(kSignatureHeaderDate));
@@ -197,10 +204,15 @@ class SignedExchangeHandlerTest
}
void TearDown() override {
+ if (original_ignore_errors_spki_list_) {
+ SignedExchangeCertificateChain::IgnoreErrorsSPKIList::
+ SetInstanceForTesting(std::move(original_ignore_errors_spki_list_));
+ }
SignedExchangeHandler::SetNetworkContextForTesting(nullptr);
network::NetworkContext::SetCertVerifierForTesting(nullptr);
SignedExchangeHandler::SetVerificationTimeForTesting(
base::Optional<base::Time>());
+ SetBrowserClientForTesting(original_client_);
}
void SetCertVerifier(std::unique_ptr<net::CertVerifier> cert_verifier) {
@@ -208,6 +220,18 @@ class SignedExchangeHandlerTest
network::NetworkContext::SetCertVerifierForTesting(cert_verifier_.get());
}
+ void SetIgnoreCertificateErrorsSPKIList(const std::string value) {
+ DCHECK(!original_ignore_errors_spki_list_);
+ base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
+ command_line.AppendSwitchASCII(
+ network::switches::kIgnoreCertificateErrorsSPKIList, value);
+ original_ignore_errors_spki_list_ = SignedExchangeCertificateChain::
+ IgnoreErrorsSPKIList::SetInstanceForTesting(
+ std::make_unique<
+ SignedExchangeCertificateChain::IgnoreErrorsSPKIList>(
+ command_line));
+ }
+
// Creates a net::CertVerifyResult with some useful default values.
net::CertVerifyResult CreateCertVerifyResult() {
net::CertVerifyResult result;
@@ -377,10 +401,14 @@ class SignedExchangeHandlerTest
base::test::ScopedFeatureList feature_list_;
content::TestBrowserThreadBundle browser_thread_bundle_;
+ TestBrowserClient browser_client_;
+ ContentBrowserClient* original_client_;
std::unique_ptr<net::TestURLRequestContext> url_request_context_;
std::unique_ptr<network::NetworkContext> network_context_;
network::mojom::NetworkContextPtr network_context_ptr_;
const url::Origin request_initiator_;
+ std::unique_ptr<SignedExchangeCertificateChain::IgnoreErrorsSPKIList>
+ original_ignore_errors_spki_list_;
std::unique_ptr<net::MockSourceStream> source_stream_;
std::unique_ptr<MockSignedExchangeCertFetcherFactory> cert_fetcher_factory_;
@@ -607,6 +635,34 @@ TEST_P(SignedExchangeHandlerTest,
ReadStream(source_, nullptr);
}
+TEST_P(SignedExchangeHandlerTest,
+ CertValidMoreThan90DaysShouldBeAllowedByIgnoreErrorsSPKIListFlag) {
+ SetIgnoreCertificateErrorsSPKIList(kPEMECDSAP256SPKIHash);
+
+ SignedExchangeHandler::SetVerificationTimeForTesting(
+ base::Time::UnixEpoch() +
+ base::TimeDelta::FromSeconds(kCertValidityPeriodEnforcementDate));
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("test.example.org.public.pem.cbor"));
+ SetupMockCertVerifier("prime256v1-sha256.public.pem",
+ CreateCertVerifyResult());
+ SetSourceStreamContents("test.example.org_test.sxg");
+
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result());
+ 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, CertWithoutExtensionAllowedByFeatureFlag) {
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndEnableFeature(
@@ -633,6 +689,31 @@ TEST_P(SignedExchangeHandlerTest, CertWithoutExtensionAllowedByFeatureFlag) {
EXPECT_EQ(static_cast<int>(expected_payload.size()), rv);
}
+TEST_P(SignedExchangeHandlerTest,
+ CertWithoutExtensionAllowedByIgnoreErrorsSPKIListFlag) {
+ SetIgnoreCertificateErrorsSPKIList(kPEMECDSAP256SPKIHash);
+
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("test.example.org-noext.public.pem.cbor"));
+ SetupMockCertVerifier("prime256v1-sha256-noext.public.pem",
+ CreateCertVerifyResult());
+ SetSourceStreamContents("test.example.org_noext_test.sxg");
+
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result());
+ 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
diff --git a/chromium/content/browser/web_package/signed_exchange_loader.cc b/chromium/content/browser/web_package/signed_exchange_loader.cc
index efc013cc88a..dd58fdb71be 100644
--- a/chromium/content/browser/web_package/signed_exchange_loader.cc
+++ b/chromium/content/browser/web_package/signed_exchange_loader.cc
@@ -29,6 +29,7 @@
#include "net/cert/cert_status_flags.h"
#include "net/http/http_util.h"
#include "net/url_request/redirect_util.h"
+#include "services/network/public/cpp/constants.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
@@ -44,27 +45,6 @@ constexpr char kPrefetchLoadResultHistogram[] =
constexpr char kContentTypeOptionsHeaderName[] = "x-content-type-options";
constexpr char kNoSniffHeaderValue[] = "nosniff";
-net::RedirectInfo CreateRedirectInfo(
- const GURL& new_url,
- const network::ResourceRequest& outer_request,
- const network::ResourceResponseHead& outer_response,
- bool is_fallback_redirect) {
- // https://wicg.github.io/webpackage/loading.html#mp-http-fetch
- // Step 3. Set actualResponse's status to 303. [spec text]
- return net::RedirectInfo::ComputeRedirectInfo(
- "GET", outer_request.url, outer_request.site_for_cookies,
- outer_request.top_frame_origin,
- outer_request.update_first_party_url_on_redirect
- ? net::URLRequest::FirstPartyURLPolicy::
- UPDATE_FIRST_PARTY_URL_ON_REDIRECT
- : net::URLRequest::FirstPartyURLPolicy::NEVER_CHANGE_FIRST_PARTY_URL,
- outer_request.referrer_policy, outer_request.referrer.spec(), 303,
- new_url,
- net::RedirectUtil::GetReferrerPolicyHeader(outer_response.headers.get()),
- false /* insecure_scheme_was_upgraded */, true /* copy_fragment */,
- is_fallback_redirect);
-}
-
bool HasNoSniffHeader(const network::ResourceResponseHead& response) {
std::string content_type_options;
response.headers->EnumerateHeader(nullptr, kContentTypeOptionsHeaderName,
@@ -72,65 +52,10 @@ bool HasNoSniffHeader(const network::ResourceResponseHead& response) {
return base::LowerCaseEqualsASCII(content_type_options, kNoSniffHeaderValue);
}
-// The buffer size of DataPipe which is used to send the body to the renderer.
-// Use the same size as regular resource loading.
-constexpr static int kDefaultBufferSize = 512 * 1024;
-
SignedExchangeHandlerFactory* g_signed_exchange_factory_for_testing_ = nullptr;
} // namespace
-class SignedExchangeLoader::OuterResponseInfo {
- public:
- explicit OuterResponseInfo(const network::ResourceResponseHead& response)
- : request_start_(response.request_start),
- response_start_(response.response_start),
- request_time_(response.request_time),
- response_time_(response.response_time),
- load_timing_(response.load_timing) {
- if (base::FeatureList::IsEnabled(
- features::kSignedExchangeSubresourcePrefetch) &&
- response.headers) {
- response.headers->GetNormalizedHeader("link", &link_header_);
- }
- }
-
- network::ResourceResponseHead CreateRedirectResponseHead() const {
- network::ResourceResponseHead response_head;
- response_head.encoded_data_length = 0;
- std::string buf;
- if (link_header_.empty()) {
- buf = base::StringPrintf("HTTP/1.1 %d %s\r\n", 303, "See Other");
- } else {
- DCHECK(base::FeatureList::IsEnabled(
- features::kSignedExchangeSubresourcePrefetch));
- buf = base::StringPrintf(
- "HTTP/1.1 %d %s\r\n"
- "link: %s\r\n",
- 303, "See Other", link_header_.c_str());
- }
- response_head.headers = new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(buf.c_str(), buf.size()));
- response_head.encoded_data_length = 0;
- response_head.request_start = request_start_;
- response_head.response_start = response_start_;
- response_head.request_time = request_time_;
- response_head.response_time = response_time_;
- response_head.load_timing = load_timing_;
- return response_head;
- }
-
- private:
- const base::TimeTicks request_start_;
- const base::TimeTicks response_start_;
- const base::Time request_time_;
- const base::Time response_time_;
- const net::LoadTimingInfo load_timing_;
- std::string link_header_;
-
- DISALLOW_COPY_AND_ASSIGN(OuterResponseInfo);
-};
-
SignedExchangeLoader::SignedExchangeLoader(
const network::ResourceRequest& outer_request,
const network::ResourceResponseHead& outer_response,
@@ -146,7 +71,6 @@ SignedExchangeLoader::SignedExchangeLoader(
scoped_refptr<SignedExchangePrefetchMetricRecorder> metric_recorder,
const std::string& accept_langs)
: outer_request_(outer_request),
- outer_response_info_(std::make_unique<OuterResponseInfo>(outer_response)),
outer_response_(outer_response),
forwarding_client_(std::move(forwarding_client)),
url_loader_client_binding_(this),
@@ -217,8 +141,7 @@ void SignedExchangeLoader::OnUploadProgress(
NOTREACHED();
}
-void SignedExchangeLoader::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
+void SignedExchangeLoader::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
// Curerntly CachedMetadata for Signed Exchange is not supported.
NOTREACHED();
}
@@ -295,6 +218,13 @@ void SignedExchangeLoader::ConnectToClient(
client.PassInterface());
}
+base::Optional<net::SHA256HashValue>
+SignedExchangeLoader::ComputeHeaderIntegrity() const {
+ if (!signed_exchange_handler_)
+ return base::nullopt;
+ return signed_exchange_handler_->ComputeHeaderIntegrity();
+}
+
void SignedExchangeLoader::OnHTTPExchangeFound(
SignedExchangeLoadResult result,
net::Error error,
@@ -316,22 +246,24 @@ void SignedExchangeLoader::OnHTTPExchangeFound(
// Make a fallback redirect to |request_url|.
DCHECK(!fallback_url_);
fallback_url_ = request_url;
- DCHECK(outer_response_info_);
forwarding_client_->OnReceiveRedirect(
- CreateRedirectInfo(request_url, outer_request_, outer_response_,
- true /* is_fallback_redirect */),
- std::move(outer_response_info_)->CreateRedirectResponseHead());
+ signed_exchange_utils::CreateRedirectInfo(
+ request_url, outer_request_, outer_response_,
+ true /* is_fallback_redirect */),
+ signed_exchange_utils::CreateRedirectResponseHead(
+ outer_response_, true /* is_fallback_redirect */));
forwarding_client_.reset();
return;
}
DCHECK_EQ(result, SignedExchangeLoadResult::kSuccess);
inner_request_url_ = request_url;
- DCHECK(outer_response_info_);
forwarding_client_->OnReceiveRedirect(
- CreateRedirectInfo(request_url, outer_request_, outer_response_,
- false /* is_fallback_redirect */),
- std::move(outer_response_info_)->CreateRedirectResponseHead());
+ signed_exchange_utils::CreateRedirectInfo(
+ request_url, outer_request_, outer_response_,
+ false /* is_fallback_redirect */),
+ signed_exchange_utils::CreateRedirectResponseHead(
+ outer_response_, false /* is_fallback_redirect */));
forwarding_client_.reset();
const base::Optional<net::SSLInfo>& ssl_info = resource_response.ssl_info;
@@ -357,12 +289,22 @@ void SignedExchangeLoader::OnHTTPExchangeFound(
// Currently we always assume that we have body.
// TODO(https://crbug.com/80374): Add error handling and bail out
// earlier if there's an error.
-
- mojo::DataPipe data_pipe(kDefaultBufferSize);
- pending_body_consumer_ = std::move(data_pipe.consumer_handle);
-
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(MojoCreateDataPipeOptions);
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+ options.element_num_bytes = 1;
+ options.capacity_num_bytes = network::kDataPipeDefaultAllocationSize;
+ if (mojo::CreateDataPipe(&options, &producer_handle, &consumer_handle) !=
+ MOJO_RESULT_OK) {
+ forwarding_client_->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_INSUFFICIENT_RESOURCES));
+ return;
+ }
+ pending_body_consumer_ = std::move(consumer_handle);
body_data_pipe_adapter_ = std::make_unique<SourceStreamToDataPipe>(
- std::move(payload_stream), std::move(data_pipe.producer_handle),
+ std::move(payload_stream), std::move(producer_handle),
base::BindOnce(&SignedExchangeLoader::FinishReadingBody,
base::Unretained(this)));
diff --git a/chromium/content/browser/web_package/signed_exchange_loader.h b/chromium/content/browser/web_package/signed_exchange_loader.h
index 244802ba801..c14193b33c3 100644
--- a/chromium/content/browser/web_package/signed_exchange_loader.h
+++ b/chromium/content/browser/web_package/signed_exchange_loader.h
@@ -22,6 +22,7 @@
#include "url/origin.h"
namespace net {
+struct SHA256HashValue;
class SourceStream;
} // namespace net
@@ -81,7 +82,7 @@ class CONTENT_EXPORT SignedExchangeLoader final
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
@@ -105,13 +106,16 @@ class CONTENT_EXPORT SignedExchangeLoader final
return inner_request_url_;
}
+ // Returns the header integrity value of the loaded signed exchange if
+ // available. This is available after OnReceiveRedirect() of
+ // |forwarding_client| is called. Otherwise returns nullopt.
+ base::Optional<net::SHA256HashValue> ComputeHeaderIntegrity() const;
+
// Set nullptr to reset the mocking.
static void SetSignedExchangeHandlerFactoryForTest(
SignedExchangeHandlerFactory* factory);
private:
- class OuterResponseInfo;
-
// Called from |signed_exchange_handler_| when it finds an origin-signed HTTP
// exchange.
void OnHTTPExchangeFound(
@@ -128,9 +132,6 @@ class CONTENT_EXPORT SignedExchangeLoader final
const network::ResourceRequest outer_request_;
- // This info is used to create a dummy redirect response.
- std::unique_ptr<const OuterResponseInfo> outer_response_info_;
-
// The outer response of signed HTTP exchange which was received from network.
const network::ResourceResponseHead outer_response_;
diff --git a/chromium/content/browser/web_package/signed_exchange_loader_unittest.cc b/chromium/content/browser/web_package/signed_exchange_loader_unittest.cc
index 499dc0b8d30..0774e4737d7 100644
--- a/chromium/content/browser/web_package/signed_exchange_loader_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_loader_unittest.cc
@@ -62,7 +62,7 @@ class SignedExchangeLoaderTest : public testing::TestWithParam<bool> {
const network::ResourceResponseHead&));
MOCK_METHOD3(OnUploadProgress,
void(int64_t, int64_t, base::OnceCallback<void()> callback));
- MOCK_METHOD1(OnReceiveCachedMetadata, void(const std::vector<uint8_t>&));
+ MOCK_METHOD1(OnReceiveCachedMetadata, void(mojo_base::BigBuffer));
MOCK_METHOD1(OnTransferSizeUpdated, void(int32_t));
MOCK_METHOD1(OnStartLoadingResponseBody,
void(mojo::ScopedDataPipeConsumerHandle));
@@ -163,12 +163,13 @@ TEST_P(SignedExchangeLoaderTest, Simple) {
network::ResourceResponseHead response;
std::string headers("HTTP/1.1 200 OK\nnContent-type: foo/bar\n\n");
- response.headers = new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size()));
+ response.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(headers));
MockSignedExchangeHandlerFactory factory({MockSignedExchangeHandlerParams(
resource_request.url, SignedExchangeLoadResult::kSuccess, net::OK,
- GURL("https://publisher.example.com/"), "text/html", {})});
+ GURL("https://publisher.example.com/"), "text/html", {},
+ net::SHA256HashValue({{0x00}}))});
SignedExchangeLoader::SetSignedExchangeHandlerFactoryForTest(&factory);
std::unique_ptr<SignedExchangeLoader> signed_exchange_loader =
diff --git a/chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc
index af5c54d272e..8a0a2b0676b 100644
--- a/chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc
+++ b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc
@@ -77,6 +77,13 @@ SignedExchangePrefetchHandler::FollowRedirect(
return pending_request;
}
+base::Optional<net::SHA256HashValue>
+SignedExchangePrefetchHandler::ComputeHeaderIntegrity() const {
+ if (!signed_exchange_loader_)
+ return base::nullopt;
+ return signed_exchange_loader_->ComputeHeaderIntegrity();
+}
+
void SignedExchangePrefetchHandler::OnReceiveResponse(
const network::ResourceResponseHead& head) {
NOTREACHED();
@@ -96,7 +103,7 @@ void SignedExchangePrefetchHandler::OnUploadProgress(
}
void SignedExchangePrefetchHandler::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
+ mojo_base::BigBuffer data) {
NOTREACHED();
}
diff --git a/chromium/content/browser/web_package/signed_exchange_prefetch_handler.h b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.h
index ddacc3dc469..2943a6062cf 100644
--- a/chromium/content/browser/web_package/signed_exchange_prefetch_handler.h
+++ b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.h
@@ -15,6 +15,7 @@
#include "services/network/public/mojom/url_loader.mojom.h"
namespace net {
+struct SHA256HashValue;
class URLRequestContextGetter;
}
@@ -64,6 +65,12 @@ class SignedExchangePrefetchHandler final
network::mojom::URLLoaderClientRequest FollowRedirect(
network::mojom::URLLoaderRequest loader_request);
+ // Returns the header integrity value of the loaded signed exchange if
+ // available. This is available after OnReceiveRedirect() of
+ // |forwarding_client| is called and before FollowRedirect() of |this| is
+ // called. Otherwise returns nullopt.
+ base::Optional<net::SHA256HashValue> ComputeHeaderIntegrity() const;
+
private:
// network::mojom::URLLoaderClient overrides:
void OnReceiveResponse(const network::ResourceResponseHead& head) override;
@@ -72,7 +79,7 @@ class SignedExchangePrefetchHandler final
void OnUploadProgress(int64_t current_position,
int64_t total_size,
base::OnceCallback<void()> callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
diff --git a/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc b/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
index 45348f58e95..93331d09b64 100644
--- a/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
@@ -2,11 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <tuple>
+
#include "base/bind.h"
#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/synchronization/lock.h"
#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
@@ -199,25 +202,44 @@ class SignedExchangeRequestHandlerBrowserTestBase
DISALLOW_COPY_AND_ASSIGN(SignedExchangeRequestHandlerBrowserTestBase);
};
-enum class SignedExchangeRequestHandlerBrowserTestPrefetchParam {
- kPrefetchDisabled,
- kPrefetchEnabled
-};
-
class SignedExchangeRequestHandlerBrowserTest
- : public SignedExchangeRequestHandlerBrowserTestBase,
- public testing::WithParamInterface<
- SignedExchangeRequestHandlerBrowserTestPrefetchParam> {
+ : public testing::WithParamInterface<
+ std::tuple<bool /* prefetch_enabled */,
+ bool /* network_service_enabled */,
+ bool /* sxg_subresource_prefetch_enabled */>>,
+ public SignedExchangeRequestHandlerBrowserTestBase {
public:
SignedExchangeRequestHandlerBrowserTest() = default;
+ ~SignedExchangeRequestHandlerBrowserTest() = default;
- protected:
- bool PrefetchIsEnabled() {
- return GetParam() == SignedExchangeRequestHandlerBrowserTestPrefetchParam::
- kPrefetchEnabled;
+ void SetUp() override {
+ bool network_service_enabled;
+ bool sxg_subresource_prefetch_enabled;
+ std::tie(prefetch_enabled_, network_service_enabled,
+ sxg_subresource_prefetch_enabled) = GetParam();
+ std::vector<base::Feature> enable_features;
+ std::vector<base::Feature> disabled_features;
+ if (network_service_enabled) {
+ enable_features.push_back(network::features::kNetworkService);
+ } else {
+ disabled_features.push_back(network::features::kNetworkService);
+ }
+ if (sxg_subresource_prefetch_enabled) {
+ enable_features.push_back(features::kSignedExchangeSubresourcePrefetch);
+ } else {
+ disabled_features.push_back(features::kSignedExchangeSubresourcePrefetch);
+ }
+ feature_list_.InitWithFeatures(enable_features, disabled_features);
+ SignedExchangeRequestHandlerBrowserTestBase::SetUp();
}
+ protected:
+ bool PrefetchIsEnabled() const { return prefetch_enabled_; }
+
private:
+ bool prefetch_enabled_;
+ base::test::ScopedFeatureList feature_list_;
+
DISALLOW_COPY_AND_ASSIGN(SignedExchangeRequestHandlerBrowserTest);
};
@@ -445,7 +467,13 @@ IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest,
PrefetchIsEnabled() ? 2 : 1);
}
-IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest, BadMICE) {
+#if defined(OS_ANDROID)
+// https://crbug.com/966820. Fails pretty often on Android.
+#define MAYBE_BadMICE DISABLED_BadMICE
+#else
+#define MAYBE_BadMICE BadMICE
+#endif
+IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest, MAYBE_BadMICE) {
InstallMockCertChainInterceptor();
InstallMockCert();
@@ -529,13 +557,11 @@ IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest, CertNotFound) {
PrefetchIsEnabled() ? 2 : 1);
}
-INSTANTIATE_TEST_SUITE_P(
- SignedExchangeRequestHandlerBrowserTest,
- SignedExchangeRequestHandlerBrowserTest,
- testing::Values(
- SignedExchangeRequestHandlerBrowserTestPrefetchParam::kPrefetchDisabled,
- SignedExchangeRequestHandlerBrowserTestPrefetchParam::
- kPrefetchEnabled));
+INSTANTIATE_TEST_SUITE_P(,
+ SignedExchangeRequestHandlerBrowserTest,
+ ::testing::Combine(::testing::Bool(),
+ ::testing::Bool(),
+ ::testing::Bool()));
class SignedExchangeRequestHandlerDownloadBrowserTest
: public SignedExchangeRequestHandlerBrowserTestBase {
@@ -888,13 +914,17 @@ class SignedExchangeAcceptHeaderBrowserTest
base::Optional<std::string> GetInterceptedAcceptHeader(
const GURL& url) const {
+ base::AutoLock lock(url_accept_header_map_lock_);
const auto it = url_accept_header_map_.find(url);
if (it == url_accept_header_map_.end())
return base::nullopt;
return it->second;
}
- void ClearInterceptedAcceptHeaders() { url_accept_header_map_.clear(); }
+ void ClearInterceptedAcceptHeaders() {
+ base::AutoLock lock(url_accept_header_map_lock_);
+ url_accept_header_map_.clear();
+ }
net::EmbeddedTestServer https_server_;
@@ -944,6 +974,8 @@ class SignedExchangeAcceptHeaderBrowserTest
const auto it = request.headers.find(std::string(network::kAcceptHeader));
if (it == request.headers.end())
return;
+ // Note this method is called on the EmbeddedTestServer's background thread.
+ base::AutoLock lock(url_accept_header_map_lock_);
url_accept_header_map_[request.base_url.Resolve(request.relative_url)] =
it->second;
}
@@ -951,6 +983,10 @@ class SignedExchangeAcceptHeaderBrowserTest
base::test::ScopedFeatureList feature_list_;
base::test::ScopedFeatureList feature_list_for_accept_header_;
+ // url_accept_header_map_ is accessed both on the main thread and on the
+ // EmbeddedTestServer's background thread via MonitorRequest(), so it must be
+ // locked.
+ mutable base::Lock url_accept_header_map_lock_;
std::map<GURL, std::string> url_accept_header_map_;
};
diff --git a/chromium/content/browser/web_package/signed_exchange_request_matcher.cc b/chromium/content/browser/web_package/signed_exchange_request_matcher.cc
index d1b493f45e3..350f6792609 100644
--- a/chromium/content/browser/web_package/signed_exchange_request_matcher.cc
+++ b/chromium/content/browser/web_package/signed_exchange_request_matcher.cc
@@ -68,7 +68,7 @@ class ContentNegotiationAlgorithm {
item.value = name_value_pairs.name();
item.weight = 1.0;
while (name_value_pairs.GetNext()) {
- if (base::LowerCaseEqualsASCII(name_value_pairs.name(), "q")) {
+ if (base::LowerCaseEqualsASCII(name_value_pairs.name_piece(), "q")) {
if (auto value = GetQValue(name_value_pairs.value()))
item.weight = *value;
} else {
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 cf554f58811..bb2fb72213c 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
+++ b/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
@@ -8,27 +8,23 @@
#include <vector>
#include "base/big_endian.h"
-#include "base/command_line.h"
#include "base/containers/span.h"
#include "base/format_macros.h"
#include "base/metrics/histogram_macros.h"
-#include "base/no_destructor.h"
#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
+#include "content/browser/web_package/signed_exchange_certificate_chain.h"
#include "content/browser/web_package/signed_exchange_consts.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 "content/public/browser/content_browser_client.h"
-#include "crypto/sha2.h"
#include "crypto/signature_verifier.h"
#include "net/cert/asn1_util.h"
#include "net/cert/x509_util.h"
-#include "services/network/public/cpp/network_switches.h"
#include "third_party/boringssl/src/include/openssl/bytestring.h"
#include "third_party/boringssl/src/include/openssl/ec.h"
#include "third_party/boringssl/src/include/openssl/ec_key.h"
@@ -245,28 +241,18 @@ SignedExchangeSignatureVerifier::Result VerifyTimestamps(
return SignedExchangeSignatureVerifier::Result::kSuccess;
}
-// Returns true if SPKI hash of |certificate| is included in the
-// --ignore-certificate-errors-spki-list command line flag, and
-// ContentBrowserClient::CanIgnoreCertificateErrorIfNeeded() returns true.
-bool ShouldIgnoreTimestampError(
- scoped_refptr<net::X509Certificate> certificate) {
- static base::NoDestructor<
- SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList>
- instance(*base::CommandLine::ForCurrentProcess());
- return instance->ShouldIgnoreError(certificate);
-}
-
} // namespace
SignedExchangeSignatureVerifier::Result SignedExchangeSignatureVerifier::Verify(
SignedExchangeVersion version,
const SignedExchangeEnvelope& envelope,
- scoped_refptr<net::X509Certificate> certificate,
+ const SignedExchangeCertificateChain* cert_chain,
const base::Time& verification_time,
SignedExchangeDevToolsProxy* devtools_proxy) {
SCOPED_UMA_HISTOGRAM_TIMER("SignedExchange.Time.SignatureVerify");
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeSignatureVerifier::Verify");
+ scoped_refptr<net::X509Certificate> certificate = cert_chain->cert();
DCHECK(certificate);
const auto validity_period_result = VerifyValidityPeriod(envelope);
if (validity_period_result != Result::kSuccess) {
@@ -281,7 +267,7 @@ SignedExchangeSignatureVerifier::Result SignedExchangeSignatureVerifier::Verify(
}
const auto timestamp_result = VerifyTimestamps(envelope, verification_time);
if (timestamp_result != Result::kSuccess &&
- !ShouldIgnoreTimestampError(certificate)) {
+ !cert_chain->ShouldIgnoreErrors()) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy,
base::StringPrintf(
@@ -322,43 +308,4 @@ SignedExchangeSignatureVerifier::Result SignedExchangeSignatureVerifier::Verify(
return Result::kSuccess;
}
-SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList::IgnoreErrorsSPKIList(
- const std::string& spki_list) {
- Parse(spki_list);
-}
-
-SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList::IgnoreErrorsSPKIList(
- const base::CommandLine& command_line) {
- if (!GetContentClient()->browser()->CanIgnoreCertificateErrorIfNeeded())
- return;
- Parse(command_line.GetSwitchValueASCII(
- network::switches::kIgnoreCertificateErrorsSPKIList));
-}
-
-void SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList::Parse(
- const std::string& spki_list) {
- hash_set_ =
- network::IgnoreErrorsCertVerifier::MakeWhitelist(base::SplitString(
- spki_list, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL));
-}
-
-SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList::~IgnoreErrorsSPKIList() =
- default;
-
-bool SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList::ShouldIgnoreError(
- scoped_refptr<net::X509Certificate> certificate) {
- if (hash_set_.empty())
- return false;
-
- base::StringPiece spki;
- if (!net::asn1::ExtractSPKIFromDERCert(
- net::x509_util::CryptoBufferAsStringPiece(certificate->cert_buffer()),
- &spki)) {
- return false;
- }
- net::SHA256HashValue hash;
- crypto::SHA256HashString(spki, &hash, sizeof(net::SHA256HashValue));
- return hash_set_.find(hash) != hash_set_.end();
-}
-
} // namespace content
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 15b574d73ea..e9f08eac25b 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_verifier.h
+++ b/chromium/content/browser/web_package/signed_exchange_signature_verifier.h
@@ -10,15 +10,14 @@
#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/common/content_export.h"
#include "net/cert/x509_certificate.h"
-#include "services/network/ignore_errors_cert_verifier.h"
namespace base {
-class CommandLine;
class Time;
} // namespace base
namespace content {
+class SignedExchangeCertificateChain;
class SignedExchangeEnvelope;
class SignedExchangeDevToolsProxy;
@@ -51,30 +50,9 @@ class CONTENT_EXPORT SignedExchangeSignatureVerifier final {
kMaxValue = kErrExpired
};
- // An utility class which holds a set of certificates which errors should be
- // ignored. It parses a comma-delimited list of base64-encoded SHA-256 SPKI
- // fingerprints, and can query if a certificate is included in the set.
- // CONTENT_EXPORT since it is used from the unit test.
- class CONTENT_EXPORT IgnoreErrorsSPKIList {
- public:
- explicit IgnoreErrorsSPKIList(const base::CommandLine& command_line);
- ~IgnoreErrorsSPKIList();
- bool ShouldIgnoreError(scoped_refptr<net::X509Certificate> certificate);
-
- private:
- FRIEND_TEST_ALL_PREFIXES(SignedExchangeSignatureVerifierTest,
- IgnoreErrorsSPKIList);
-
- explicit IgnoreErrorsSPKIList(const std::string& spki_list);
- void Parse(const std::string& spki_list);
-
- network::IgnoreErrorsCertVerifier::SPKIHashSet hash_set_;
- DISALLOW_COPY_AND_ASSIGN(IgnoreErrorsSPKIList);
- };
-
static Result Verify(SignedExchangeVersion version,
const SignedExchangeEnvelope& envelope,
- scoped_refptr<net::X509Certificate> certificate,
+ const SignedExchangeCertificateChain* cert_chain,
const base::Time& verification_time,
SignedExchangeDevToolsProxy* devtools_proxy);
};
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 bf700ca58b0..95e95e68ca4 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
@@ -4,10 +4,16 @@
#include "content/browser/web_package/signed_exchange_signature_verifier.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
#include "base/test/metrics/histogram_tester.h"
+#include "content/browser/web_package/signed_exchange_certificate_chain.h"
#include "content/browser/web_package/signed_exchange_envelope.h"
#include "content/browser/web_package/signed_exchange_signature_header_field.h"
+#include "content/public/common/content_paths.h"
#include "net/cert/x509_certificate.h"
+#include "net/test/cert_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -18,7 +24,7 @@ const uint64_t kSignatureHeaderExpires = 1517895941;
// See content/test/data/sxg/README on how to generate these data.
// clang-format off
-constexpr char kSignatureHeaderECDSAP256[] = R"(label; sig=*MEUCIQCG/Oyo2geBPXXVRy6aN44z9Zn/B/6y/2MBwJfgltYjzAIgXIL1cdNfyHb8pC9efCsSqhVDCuMAS2XwYMLpvfJ0lCo=*; validity-url="https://test.example.org/resource.validity.msg"; integrity="digest/mi-sha256-03"; cert-url="https://example.com/cert.msg"; cert-sha256=*KX+BYLSMgDOON8Ju65RoId39Qvajxa12HO+WnD4HpS0=*; date=1517892341; expires=1517895941)";
+constexpr char kSignatureHeaderECDSAP256[] = R"(label;cert-sha256=*4GTISmmaq+jCoSZ/qhWEoWh6+iqo1hVCKdN5eHQkZh4=*;cert-url="https://example.com/cert.msg";date=1517892341;expires=1517895941;integrity="digest/mi-sha256-03";sig=*MEUCIQCx3N8udHGUCu8NcUsTEbxAplnqERapkpXdkH0XhY0qKAIgPoRHJ71BnrFZ0CdRiMi6ULotqnyxFqH10YInyzHznVY=*;validity-url="https://test.example.org/resource.validity.msg")";
constexpr uint8_t kCborHeadersECDSAP256[] = {
0xa4, 0x46, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x58, 0x39, 0x6d, 0x69,
0x2d, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x2d, 0x30, 0x33, 0x3d, 0x77,
@@ -34,7 +40,7 @@ constexpr uint8_t kCborHeadersECDSAP256[] = {
0x69, 0x6e, 0x67, 0x4c, 0x6d, 0x69, 0x2d, 0x73, 0x68, 0x61, 0x32, 0x35,
0x36, 0x2d, 0x30, 0x33
};
-constexpr char kSignatureHeaderECDSAP384[] = R"(label; sig=*MGUCMEeJujTLUifd561fwNZEzDptyEkXIKzkMOzbQFwlUpU3SWjY//58aRr6w6+V1jFa9wIxAPVlX3ia5a0wRYLfAXHO0Jm9bRKPoPUk7o9H/95eroC7BUL7ow+4H1W+20MuO1wbkw==*; validity-url="https://test.example.org/resource.validity.msg"; integrity="digest/mi-sha256-03"; cert-url="https://example.com/cert.msg"; cert-sha256=*8X8y8nj8vDJHSSa0cxn+TCu+8zGpIJfbdzAnd5cW+jA=*; date=1517892341; expires=1517895941)";
+constexpr char kSignatureHeaderECDSAP384[] = R"(label;cert-sha256=*nHSZO9uYwVQ0touPzq+OfsaGRhUwkW4ZIZbQQMDXEjY=*;cert-url="https://example.com/cert.msg";date=1517892341;expires=1517895941;integrity="digest/mi-sha256-03";sig=*MGUCMQD1QotpssEQf54/3bIi/YE3TNuA9hzMFlK4C+jNPmKYkf7haC/+F1qWZ51ZtUa5FswCMCVpGGlO/ImAFhNtAdIdDEP+fFbSgD6Qg0CiHzrmS30NCFGfy4yFY8+ybzBAEvOZmw==*;validity-url="https://test.example.org/resource.validity.msg")";
// clang-format on
// |expires| (1518497142) is more than 7 days (604800 seconds) after |date|
@@ -54,47 +60,15 @@ constexpr char kSignatureHeaderInvalidExpires[] =
"date=1517892341; expires=1518497142";
// clang-format on
-constexpr char kCertPEMECDSAP256[] = R"(
------BEGIN CERTIFICATE-----
-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-----)";
+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");
-constexpr char kCertPEMECDSAP384[] = R"(
------BEGIN CERTIFICATE-----
-MIICYDCCAUgCAQEwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxEzARBgNV
-BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoM
-B1Rlc3QgQ0ExFTATBgNVBAMMDFRlc3QgUm9vdCBDQTAeFw0xODA0MDkwMTUyMzVa
-Fw0xOTA0MDQwMTUyMzVaMDcxGTAXBgNVBAMMEHRlc3QuZXhhbXBsZS5vcmcxDTAL
-BgNVBAoMBFRlc3QxCzAJBgNVBAYTAlVTMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE
-YK0FPc6B2UkDO3GHS95PLss9e82f8RdQDIZE9UPUSOJ1UISOT19j/SJq3gyoY+pK
-J818LhVe+ywgdH+tKosO6v1l2o/EffIRDjCfN/aSUuQjkkSwgyL62/9687+486z6
-MA0GCSqGSIb3DQEBCwUAA4IBAQB61Q+/68hsD5OapG+2CDsJI+oR91H+Jv+tRMby
-of47O0hJGISuAB9xcFhIcMKwBReODpBmzwSO713NNU/oaG/XysHH1TNZZodTtWD9
-Z1g5AJamfwvFS+ObqzOtyFUdFS4NBAE4lXi5XnHa2hU2Bkm+abVYLqyAGw1kh2ES
-DGC2vA1lb2Uy9bgLCYYkZoESjb/JYRQjCmqlwYKOozU7ZbIe3zJPjRWYP1Tuany5
-+rYllWk/DJlMVjs/fbf0jj32vrevCgul43iWMgprOw1ncuK8l5nND/o5aN2mwMDw
-Xhe5DP7VATeQq3yGV3ps+rCTHDP6qSHDEWP7DqHQdSsxtI0E
------END CERTIFICATE-----)";
-
-constexpr char kPEMECDSAP256SPKIHash[] =
- "iwtEGagHhL9HbHI38aoFstFPEyB+lzZO5H2ZZAJlYOo=";
-constexpr char kPEMECDSAP384SPKIHash[] =
- "aGcf7fF/2+mXuHjYen7FZ8HZPR0B6sK6zIsyrCoB6Y8=";
+ return net::CreateCertificateChainFromFile(
+ dir_path, cert_file, net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
+}
} // namespace
@@ -111,11 +85,13 @@ class SignedExchangeSignatureVerifierTest
void TestVerifierGivenValidInput(
const SignedExchangeEnvelope& envelope,
scoped_refptr<net::X509Certificate> certificate) {
+ SignedExchangeCertificateChain cert_chain(
+ certificate, std::string() /* ocsp */, std::string() /* sct */);
{
base::HistogramTester histogram_tester;
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kSuccess,
SignedExchangeSignatureVerifier::Verify(
- GetParam(), envelope, certificate, VerificationTime(),
+ GetParam(), envelope, &cert_chain, VerificationTime(),
nullptr /* devtools_proxy */));
histogram_tester.ExpectUniqueSample(
"SignedExchange.TimeUntilExpiration",
@@ -129,7 +105,7 @@ class SignedExchangeSignatureVerifierTest
base::HistogramTester histogram_tester;
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrFutureDate,
SignedExchangeSignatureVerifier::Verify(
- GetParam(), envelope, certificate,
+ GetParam(), envelope, &cert_chain,
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(kSignatureHeaderDate - 1),
nullptr /* devtools_proxy */
@@ -146,7 +122,7 @@ class SignedExchangeSignatureVerifierTest
base::HistogramTester histogram_tester;
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kSuccess,
SignedExchangeSignatureVerifier::Verify(
- GetParam(), envelope, certificate,
+ GetParam(), envelope, &cert_chain,
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(kSignatureHeaderExpires),
nullptr /* devtools_proxy */
@@ -162,7 +138,7 @@ class SignedExchangeSignatureVerifierTest
base::HistogramTester histogram_tester;
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrExpired,
SignedExchangeSignatureVerifier::Verify(
- GetParam(), envelope, certificate,
+ GetParam(), envelope, &cert_chain,
base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(
kSignatureHeaderExpires + 1),
nullptr /* devtools_proxy */
@@ -186,7 +162,7 @@ class SignedExchangeSignatureVerifierTest
EXPECT_EQ(
SignedExchangeSignatureVerifier::Result::kErrValidityPeriodTooLong,
SignedExchangeSignatureVerifier::Verify(
- GetParam(), invalid_expires_envelope, certificate,
+ GetParam(), invalid_expires_envelope, &cert_chain,
VerificationTime(), nullptr /* devtools_proxy */
));
@@ -196,7 +172,7 @@ class SignedExchangeSignatureVerifierTest
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::
kErrSignatureVerificationFailed,
SignedExchangeSignatureVerifier::Verify(
- GetParam(), corrupted_envelope, certificate,
+ GetParam(), corrupted_envelope, &cert_chain,
VerificationTime(), nullptr /* devtools_proxy */
));
@@ -207,7 +183,7 @@ class SignedExchangeSignatureVerifierTest
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::
kErrSignatureVerificationFailed,
SignedExchangeSignatureVerifier::Verify(
- GetParam(), badsig_envelope, certificate, VerificationTime(),
+ GetParam(), badsig_envelope, &cert_chain, VerificationTime(),
nullptr /* devtools_proxy */
));
@@ -219,7 +195,7 @@ class SignedExchangeSignatureVerifierTest
EXPECT_EQ(
SignedExchangeSignatureVerifier::Result::kErrCertificateSHA256Mismatch,
SignedExchangeSignatureVerifier::Verify(
- GetParam(), badsigsha256_envelope, certificate, VerificationTime(),
+ GetParam(), badsigsha256_envelope, &cert_chain, VerificationTime(),
nullptr /* devtools_proxy */
));
}
@@ -231,11 +207,8 @@ TEST_P(SignedExchangeSignatureVerifierTest, VerifyECDSAP256) {
ASSERT_TRUE(signature.has_value());
ASSERT_EQ(1u, signature->size());
- net::CertificateList certlist =
- net::X509Certificate::CreateCertificateListFromBytes(
- kCertPEMECDSAP256, base::size(kCertPEMECDSAP256),
- net::X509Certificate::FORMAT_AUTO);
- ASSERT_EQ(1u, certlist.size());
+ scoped_refptr<net::X509Certificate> cert =
+ LoadCertificate("prime256v1-sha256.public.pem");
SignedExchangeEnvelope envelope;
envelope.set_request_url(signed_exchange_utils::URLWithRawString(
@@ -249,7 +222,7 @@ TEST_P(SignedExchangeSignatureVerifierTest, VerifyECDSAP256) {
envelope.SetSignatureForTesting((*signature)[0]);
- TestVerifierGivenValidInput(envelope, certlist[0]);
+ TestVerifierGivenValidInput(envelope, cert);
}
TEST_P(SignedExchangeSignatureVerifierTest, VerifyECDSAP384) {
@@ -258,11 +231,10 @@ TEST_P(SignedExchangeSignatureVerifierTest, VerifyECDSAP384) {
ASSERT_TRUE(signature.has_value());
ASSERT_EQ(1u, signature->size());
- net::CertificateList certlist =
- net::X509Certificate::CreateCertificateListFromBytes(
- kCertPEMECDSAP384, base::size(kCertPEMECDSAP384),
- net::X509Certificate::FORMAT_AUTO);
- ASSERT_EQ(1u, certlist.size());
+ scoped_refptr<net::X509Certificate> cert =
+ LoadCertificate("secp384r1-sha256.public.pem");
+ SignedExchangeCertificateChain cert_chain(cert, std::string() /* ocsp */,
+ std::string() /* sct */);
SignedExchangeEnvelope envelope;
envelope.set_request_url(signed_exchange_utils::URLWithRawString(
@@ -277,38 +249,10 @@ TEST_P(SignedExchangeSignatureVerifierTest, VerifyECDSAP384) {
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrUnsupportedCertType,
SignedExchangeSignatureVerifier::Verify(
- GetParam(), envelope, certlist[0], VerificationTime(),
+ GetParam(), envelope, &cert_chain, VerificationTime(),
nullptr /* devtools_proxy */));
}
-TEST_P(SignedExchangeSignatureVerifierTest, IgnoreErrorsSPKIList) {
- SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList ignore_nothing("");
- SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList ignore_ecdsap256(
- kPEMECDSAP256SPKIHash);
- SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList ignore_ecdsap384(
- kPEMECDSAP384SPKIHash);
- SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList ignore_both(
- std::string(kPEMECDSAP256SPKIHash) + "," + kPEMECDSAP384SPKIHash);
-
- scoped_refptr<net::X509Certificate> cert_ecdsap256 =
- net::X509Certificate::CreateCertificateListFromBytes(
- kCertPEMECDSAP256, base::size(kCertPEMECDSAP256),
- net::X509Certificate::FORMAT_AUTO)[0];
- scoped_refptr<net::X509Certificate> cert_ecdsap384 =
- net::X509Certificate::CreateCertificateListFromBytes(
- kCertPEMECDSAP384, base::size(kCertPEMECDSAP384),
- net::X509Certificate::FORMAT_AUTO)[0];
-
- EXPECT_FALSE(ignore_nothing.ShouldIgnoreError(cert_ecdsap256));
- EXPECT_FALSE(ignore_nothing.ShouldIgnoreError(cert_ecdsap384));
- EXPECT_TRUE(ignore_ecdsap256.ShouldIgnoreError(cert_ecdsap256));
- EXPECT_FALSE(ignore_ecdsap256.ShouldIgnoreError(cert_ecdsap384));
- EXPECT_FALSE(ignore_ecdsap384.ShouldIgnoreError(cert_ecdsap256));
- EXPECT_TRUE(ignore_ecdsap384.ShouldIgnoreError(cert_ecdsap384));
- EXPECT_TRUE(ignore_both.ShouldIgnoreError(cert_ecdsap256));
- EXPECT_TRUE(ignore_both.ShouldIgnoreError(cert_ecdsap384));
-}
-
INSTANTIATE_TEST_SUITE_P(SignedExchangeSignatureVerifierTests,
SignedExchangeSignatureVerifierTest,
::testing::Values(SignedExchangeVersion::kB3));
diff --git a/chromium/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc b/chromium/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
new file mode 100644
index 00000000000..f8b60715bcf
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
@@ -0,0 +1,1724 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/stl_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/task_runner.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/test_timeouts.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/loader/prefetch_browsertest_base.h"
+#include "content/browser/loader/prefetched_signed_exchange_cache.h"
+#include "content/browser/web_package/mock_signed_exchange_handler.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_paths.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 "net/base/features.h"
+#include "net/dns/mock_host_resolver.h"
+#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/public/cpp/features.h"
+#include "storage/browser/blob/blob_storage_context.h"
+
+namespace content {
+
+namespace {
+
+std::string GetHeaderIntegrityString(const net::SHA256HashValue& hash) {
+ std::string header_integrity_string = net::HashValue(hash).ToString();
+ // Change "sha256/" to "sha256-".
+ header_integrity_string[6] = '-';
+ return header_integrity_string;
+}
+
+} // namespace
+
+struct SignedExchangeSubresourcePrefetchBrowserTestParam {
+ SignedExchangeSubresourcePrefetchBrowserTestParam(
+ bool network_service_enabled)
+ : network_service_enabled(network_service_enabled) {}
+ const bool network_service_enabled;
+};
+
+class SignedExchangeSubresourcePrefetchBrowserTest
+ : public PrefetchBrowserTestBase,
+ public testing::WithParamInterface<
+ SignedExchangeSubresourcePrefetchBrowserTestParam> {
+ public:
+ SignedExchangeSubresourcePrefetchBrowserTest() = default;
+ ~SignedExchangeSubresourcePrefetchBrowserTest() = default;
+
+ void SetUp() override {
+ std::vector<base::Feature> enable_features;
+ std::vector<base::Feature> disabled_features;
+ enable_features.push_back(features::kSignedHTTPExchange);
+ enable_features.push_back(features::kSignedExchangeSubresourcePrefetch);
+ if (GetParam().network_service_enabled) {
+ enable_features.push_back(network::features::kNetworkService);
+ } else {
+ disabled_features.push_back(network::features::kNetworkService);
+ }
+ feature_list_.InitWithFeatures(enable_features, disabled_features);
+ PrefetchBrowserTestBase::SetUp();
+ }
+
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ PrefetchBrowserTestBase::SetUpOnMainThread();
+ }
+
+ protected:
+ static constexpr size_t kTestBlobStorageIPCThresholdBytes = 20;
+ static constexpr size_t kTestBlobStorageMaxSharedMemoryBytes = 50;
+ static constexpr size_t kTestBlobStorageMaxBlobMemorySize = 400;
+ static constexpr uint64_t kTestBlobStorageMaxDiskSpace = 500;
+ static constexpr uint64_t kTestBlobStorageMinFileSizeBytes = 10;
+ static constexpr uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
+
+ PrefetchedSignedExchangeCache::EntryMap GetCachedExchanges() {
+ RenderViewHost* rvh = shell()->web_contents()->GetRenderViewHost();
+ RenderFrameHostImpl* rfh =
+ static_cast<RenderFrameHostImpl*>(rvh->GetMainFrame());
+ scoped_refptr<PrefetchedSignedExchangeCache> cache =
+ rfh->EnsurePrefetchedSignedExchangeCache();
+ PrefetchedSignedExchangeCache::EntryMap results;
+ base::RunLoop run_loop;
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(
+ [](scoped_refptr<PrefetchedSignedExchangeCache> cache,
+ PrefetchedSignedExchangeCache::EntryMap* results) {
+ for (const auto& exchanges_it : cache->exchanges_) {
+ (*results)[exchanges_it.first] = exchanges_it.second->Clone();
+ }
+ },
+ cache, &results),
+ run_loop.QuitClosure());
+ run_loop.Run();
+ return results;
+ }
+
+ void SetBlobLimits() {
+ scoped_refptr<ChromeBlobStorageContext> blob_context =
+ ChromeBlobStorageContext::GetFor(
+ shell()->web_contents()->GetBrowserContext());
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(
+ &SignedExchangeSubresourcePrefetchBrowserTest::SetBlobLimitsOnIO,
+ blob_context));
+ }
+
+ // Test that CORB logic works well with prefetched signed exchange
+ // subresources. This test loads a main SXG which signed by
+ // "publisher.example.com", and loads a SXG subresource using a <script> tag.
+ //
+ // When |cross_origin| is set, the SXG subresource is signed by
+ // "crossorigin.example.com", otherwise sined by "publisher.example.com".
+ // |content| is the inner body content of the SXG subresource.
+ // |mime_type| is the MIME tyepe of the inner response of the SXG subresource.
+ // When |has_nosniff| is set, the inner response header of the SXG subresource
+ // has "x-content-type-options: nosniff" header.
+ // |expected_title| is the expected title after loading the SXG page. If the
+ // content load should not be blocked, this should be the title which is set
+ // by executing |content|, otherwise this should be "original title".
+ // |expected_action| is the expected CrossOriginReadBlocking::Action which is
+ // recorded in the histogram.
+ void RunCrossOriginReadBlockingTest(
+ bool cross_origin,
+ const std::string& content,
+ const std::string& mime_type,
+ bool has_nosniff,
+ const std::string& expected_title,
+ network::CrossOriginReadBlocking::Action expected_action) {
+ int script_sxg_fetch_count = 0;
+ int script_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.sxg";
+ const char* target_path = "/target.html";
+ const char* script_sxg_path = "/script_js.sxg";
+ const char* script_path = "/script.js";
+
+ base::RunLoop script_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script_sxg_path,
+ &script_sxg_fetch_count,
+ &script_sxg_prefetch_waiter);
+ base::RunLoop script_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script_path,
+ &script_fetch_count, &script_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
+ const GURL target_url =
+ embedded_test_server()->GetURL("publisher.example.com", target_path);
+ const GURL script_sxg_url = embedded_test_server()->GetURL(script_sxg_path);
+ const GURL script_url = embedded_test_server()->GetURL(
+ cross_origin ? "crossorigin.example.com" : "publisher.example.com",
+ script_path);
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ const net::SHA256HashValue script_header_integrity = {{0x02}};
+ const std::string script_header_integrity_string =
+ GetHeaderIntegrityString(script_header_integrity);
+
+ const std::string outer_link_header = base::StringPrintf(
+ "<%s>;"
+ "rel=\"alternate\";"
+ "type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\"",
+ script_sxg_url.spec().c_str(), script_url.spec().c_str());
+ const std::string inner_link_headers = base::StringPrintf(
+ "Link: "
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"preload\";as=\"script\"",
+ script_url.spec().c_str(), script_header_integrity_string.c_str(),
+ script_url.spec().c_str());
+
+ RegisterResponse(
+ prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
+ RegisterResponse(
+ script_path,
+ ResponseEntry("document.title=\"from server\";", "text/javascript"));
+ RegisterResponse(
+ target_sxg_path,
+ ResponseEntry(base::StringPrintf(
+ "<head><script src=\"%s\"></script><title>original "
+ "title</title>"
+ "</head>",
+ script_url.spec().c_str()),
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"},
+ {"link", outer_link_header}}));
+ RegisterResponse(script_sxg_path,
+ ResponseEntry(content, "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ std::vector<std::string> script_inner_response_headers;
+ if (has_nosniff) {
+ script_inner_response_headers.emplace_back(
+ "x-content-type-options: nosniff");
+ }
+ MockSignedExchangeHandlerFactory factory(
+ {MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ target_url, "text/html", {inner_link_headers},
+ target_header_integrity),
+ MockSignedExchangeHandlerParams(
+ script_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ script_url, mime_type, script_inner_response_headers,
+ script_header_integrity)});
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ script_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, script_sxg_fetch_count);
+ EXPECT_EQ(0, script_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+ WaitUntilLoaded(script_sxg_url);
+
+ EXPECT_EQ(2u, GetCachedExchanges().size());
+
+ {
+ base::HistogramTester histograms;
+ NavigateToURLAndWaitTitle(target_sxg_url, expected_title);
+ histograms.ExpectBucketCount(
+ "SiteIsolation.XSD.Browser.Action",
+ network::CrossOriginReadBlocking::Action::kResponseStarted, 1);
+ histograms.ExpectBucketCount("SiteIsolation.XSD.Browser.Action",
+ expected_action, 1);
+ }
+
+ EXPECT_EQ(1, script_sxg_fetch_count);
+ EXPECT_EQ(0, script_fetch_count);
+ }
+
+ private:
+ static void SetBlobLimitsOnIO(
+ scoped_refptr<ChromeBlobStorageContext> context) {
+ storage::BlobStorageLimits limits;
+ limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes;
+ limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes;
+ limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize;
+ limits.desired_max_disk_space = kTestBlobStorageMaxDiskSpace;
+ limits.effective_max_disk_space = kTestBlobStorageMaxDiskSpace;
+ limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes;
+ limits.max_file_size = kTestBlobStorageMaxFileSizeBytes;
+ context->context()->set_limits_for_testing(limits);
+ }
+ base::test::ScopedFeatureList feature_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(SignedExchangeSubresourcePrefetchBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ PrefetchedSignedExchangeCache) {
+ int target_sxg_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.sxg";
+ const char* target_path = "/target.html";
+
+ base::RunLoop target_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), target_sxg_path,
+ &target_sxg_fetch_count, &target_sxg_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_EQ(0, prefetch_url_loader_called_);
+
+ const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
+ const GURL target_url = embedded_test_server()->GetURL(target_path);
+
+ RegisterResponse(
+ prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
+ RegisterResponse(
+ target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML content
+ // as "application/signed-exchange;v=b3".
+ ResponseEntry("<head><title>Prefetch Target (SXG)</title></head>",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ MockSignedExchangeHandlerFactory factory({MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK, target_url,
+ "text/html", {}, target_header_integrity)});
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ target_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, target_sxg_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+
+ EXPECT_EQ(1, prefetch_url_loader_called_);
+
+ const auto cached_exchanges = GetCachedExchanges();
+ EXPECT_EQ(1u, cached_exchanges.size());
+ const auto it = cached_exchanges.find(target_sxg_url);
+ ASSERT_TRUE(it != cached_exchanges.end());
+ EXPECT_EQ(target_sxg_url, it->second->outer_url());
+ EXPECT_EQ(target_url, it->second->inner_url());
+ EXPECT_EQ(target_header_integrity, *it->second->header_integrity());
+
+ // Shutdown the server.
+ EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+
+ // Subsequent navigation to the target URL wouldn't hit the network for
+ // the target URL. The target content should still be read correctly.
+ // The content is loaded from PrefetchedSignedExchangeCache.
+ NavigateToURLAndWaitTitle(target_sxg_url, "Prefetch Target (SXG)");
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ PrefetchedSignedExchangeCache_CrossOrigin) {
+ int target_sxg_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.sxg";
+ const char* target_path = "/target.html";
+
+ base::RunLoop target_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), target_sxg_path,
+ &target_sxg_fetch_count, &target_sxg_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_EQ(0, prefetch_url_loader_called_);
+
+ const GURL target_sxg_url =
+ embedded_test_server()->GetURL("sxg.example.com", target_sxg_path);
+ const GURL target_url =
+ embedded_test_server()->GetURL("publisher.example.com", target_path);
+
+ RegisterResponse(prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>",
+ target_sxg_url.spec().c_str())));
+ RegisterResponse(
+ target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML content
+ // as "application/signed-exchange;v=b3".
+ ResponseEntry("<head><title>Prefetch Target (SXG)</title></head>",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ MockSignedExchangeHandlerFactory factory({MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK, target_url,
+ "text/html", {}, target_header_integrity)});
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ target_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, target_sxg_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+
+ EXPECT_EQ(1, prefetch_url_loader_called_);
+
+ const auto cached_exchanges = GetCachedExchanges();
+ EXPECT_EQ(1u, cached_exchanges.size());
+ const auto it = cached_exchanges.find(target_sxg_url);
+ ASSERT_TRUE(it != cached_exchanges.end());
+ EXPECT_EQ(target_sxg_url, it->second->outer_url());
+ EXPECT_EQ(target_url, it->second->inner_url());
+ EXPECT_EQ(target_header_integrity, *it->second->header_integrity());
+
+ // Shutdown the server.
+ EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+
+ // Subsequent navigation to the target URL wouldn't hit the network for
+ // the target URL. The target content should still be read correctly.
+ // The content is loaded from PrefetchedSignedExchangeCache.
+ NavigateToURLAndWaitTitle(target_sxg_url, "Prefetch Target (SXG)");
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ PrefetchedSignedExchangeCache_SameUrl) {
+ int target_sxg_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.html";
+ const char* target_path = "/target.html";
+
+ base::RunLoop target_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), target_sxg_path,
+ &target_sxg_fetch_count, &target_sxg_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_EQ(0, prefetch_url_loader_called_);
+
+ const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
+ const GURL target_url = embedded_test_server()->GetURL(target_path);
+
+ RegisterResponse(
+ prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
+ RegisterResponse(
+ target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML content
+ // as "application/signed-exchange;v=b3".
+ ResponseEntry("<head><title>Prefetch Target (SXG)</title></head>",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ MockSignedExchangeHandlerFactory factory({MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK, target_url,
+ "text/html", {}, target_header_integrity)});
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ target_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, target_sxg_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+
+ EXPECT_EQ(1, prefetch_url_loader_called_);
+
+ const auto cached_exchanges = GetCachedExchanges();
+ EXPECT_EQ(1u, cached_exchanges.size());
+ const auto it = cached_exchanges.find(target_sxg_url);
+ ASSERT_TRUE(it != cached_exchanges.end());
+ EXPECT_EQ(target_sxg_url, it->second->outer_url());
+ EXPECT_EQ(target_url, it->second->inner_url());
+ EXPECT_EQ(target_header_integrity, *it->second->header_integrity());
+
+ // Shutdown the server.
+ EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+
+ // Subsequent navigation to the target URL wouldn't hit the network for
+ // the target URL. The target content should still be read correctly.
+ // The content is loaded from PrefetchedSignedExchangeCache.
+ NavigateToURLAndWaitTitle(target_sxg_url, "Prefetch Target (SXG)");
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ PrefetchedSignedExchangeCache_BlobStorageLimit) {
+ SetBlobLimits();
+ int target_sxg_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.sxg";
+ const char* target_path = "/target.html";
+
+ base::RunLoop target_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), target_sxg_path,
+ &target_sxg_fetch_count, &target_sxg_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_EQ(0, prefetch_url_loader_called_);
+
+ const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
+ const GURL target_url = embedded_test_server()->GetURL(target_path);
+ std::string content = "<head><title>Prefetch Target (SXG)</title></head>";
+ // Make the content larger than the disk space.
+ content.resize(kTestBlobStorageMaxDiskSpace + 1, ' ');
+ RegisterResponse(
+ prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
+ RegisterResponse(target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry(content, "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ MockSignedExchangeHandlerFactory factory({MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK, target_url,
+ "text/html", {}, target_header_integrity)});
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ target_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, target_sxg_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+
+ EXPECT_EQ(1, prefetch_url_loader_called_);
+
+ const auto cached_exchanges = GetCachedExchanges();
+ // The content of prefetched SXG is larger than the Blob storage limit.
+ // So the SXG should not be stored to the cache.
+ EXPECT_EQ(0u, cached_exchanges.size());
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ PrefetchAlternativeSubresourceSXG) {
+ int script_sxg_fetch_count = 0;
+ int script_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.sxg";
+ const char* target_path = "/target.html";
+ const char* script_sxg_path = "/script_js.sxg";
+ const char* script_path = "/script.js";
+
+ base::RunLoop script_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script_sxg_path,
+ &script_sxg_fetch_count, &script_sxg_prefetch_waiter);
+ base::RunLoop script_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script_path,
+ &script_fetch_count, &script_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_EQ(0, prefetch_url_loader_called_);
+
+ const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
+ const GURL target_url = embedded_test_server()->GetURL(target_path);
+ const GURL script_sxg_url = embedded_test_server()->GetURL(script_sxg_path);
+ const GURL script_url = embedded_test_server()->GetURL(script_path);
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ const net::SHA256HashValue script_header_integrity = {{0x02}};
+ const std::string script_header_integrity_string =
+ GetHeaderIntegrityString(script_header_integrity);
+
+ const std::string outer_link_header = base::StringPrintf(
+ "<%s>;"
+ "rel=\"alternate\";"
+ "type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\"",
+ script_sxg_url.spec().c_str(), script_url.spec().c_str());
+ const std::string inner_link_headers = base::StringPrintf(
+ "Link: "
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"preload\";as=\"script\"",
+ script_url.spec().c_str(), script_header_integrity_string.c_str(),
+ script_url.spec().c_str());
+
+ RegisterResponse(
+ prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
+ RegisterResponse(script_path, ResponseEntry("document.title=\"from server\";",
+ "text/javascript"));
+ RegisterResponse(target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("<head><title>Prefetch Target (SXG)</title>"
+ "<script src=\"./script.js\"></script></head>",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"},
+ {"link", outer_link_header}}));
+ RegisterResponse(script_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a JS
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("document.title=\"done\";",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ MockSignedExchangeHandlerFactory factory(
+ {MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ target_url, "text/html", {inner_link_headers},
+ target_header_integrity),
+ MockSignedExchangeHandlerParams(
+ script_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ script_url, "text/javascript", {}, script_header_integrity)});
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ script_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, script_sxg_fetch_count);
+ EXPECT_EQ(0, script_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+ WaitUntilLoaded(script_sxg_url);
+
+ const auto cached_exchanges = GetCachedExchanges();
+ EXPECT_EQ(2u, cached_exchanges.size());
+
+ const auto target_it = cached_exchanges.find(target_sxg_url);
+ ASSERT_TRUE(target_it != cached_exchanges.end());
+ EXPECT_EQ(target_sxg_url, target_it->second->outer_url());
+ EXPECT_EQ(target_url, target_it->second->inner_url());
+ EXPECT_EQ(target_header_integrity, *target_it->second->header_integrity());
+
+ const auto script_it = cached_exchanges.find(script_sxg_url);
+ ASSERT_TRUE(script_it != cached_exchanges.end());
+ EXPECT_EQ(script_sxg_url, script_it->second->outer_url());
+ EXPECT_EQ(script_url, script_it->second->inner_url());
+ EXPECT_EQ(script_header_integrity, *script_it->second->header_integrity());
+
+ // Subsequent navigation to the target URL wouldn't hit the network for
+ // the target URL. The target content should still be read correctly.
+ // The content is loaded from PrefetchedSignedExchangeCache. And the script
+ // is also loaded from PrefetchedSignedExchangeCache.
+ NavigateToURLAndWaitTitle(target_sxg_url, "done");
+
+ EXPECT_EQ(1, script_sxg_fetch_count);
+ EXPECT_EQ(0, script_fetch_count);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ PrefetchAlternativeSubresourceSXG_ImageSrcsetAndSizes) {
+ int image1_sxg_fetch_count = 0;
+ int image1_fetch_count = 0;
+ int image2_sxg_fetch_count = 0;
+ int image2_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.sxg";
+ const char* target_path = "/target.html";
+ const char* image1_sxg_path = "/image1_png.sxg";
+ const char* image1_path = "/image1.png";
+ const char* image2_sxg_path = "/image2_png.sxg";
+ const char* image2_path = "/image2.png";
+
+ base::RunLoop image1_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), image1_sxg_path,
+ &image1_sxg_fetch_count, &image1_sxg_prefetch_waiter);
+ base::RunLoop image1_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), image1_path,
+ &image1_fetch_count, &image1_prefetch_waiter);
+ base::RunLoop image2_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), image2_sxg_path,
+ &image2_sxg_fetch_count, &image2_sxg_prefetch_waiter);
+ base::RunLoop image2_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), image2_path,
+ &image2_fetch_count, &image2_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
+ const GURL target_url = embedded_test_server()->GetURL(target_path);
+ const GURL image1_sxg_url = embedded_test_server()->GetURL(image1_sxg_path);
+ const GURL image1_url = embedded_test_server()->GetURL(image1_path);
+ const GURL image2_sxg_url = embedded_test_server()->GetURL(image2_sxg_path);
+ const GURL image2_url = embedded_test_server()->GetURL(image2_path);
+
+ std::string image_contents;
+ {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ base::FilePath path;
+ ASSERT_TRUE(base::PathService::Get(content::DIR_TEST_DATA, &path));
+ path = path.AppendASCII("loader/empty16x16.png");
+ ASSERT_TRUE(base::PathExists(path));
+ ASSERT_TRUE(base::ReadFileToString(path, &image_contents));
+ }
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ const net::SHA256HashValue image1_header_integrity = {{0x02}};
+ const net::SHA256HashValue image2_header_integrity = {{0x03}};
+ const std::string image1_header_integrity_string =
+ GetHeaderIntegrityString(image1_header_integrity);
+ const std::string image2_header_integrity_string =
+ GetHeaderIntegrityString(image2_header_integrity);
+
+ const std::string outer_link_header = base::StringPrintf(
+ "<%s>;"
+ "rel=\"alternate\";"
+ "type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\","
+ "<%s>;"
+ "rel=\"alternate\";"
+ "type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\"",
+ image1_sxg_url.spec().c_str(), image1_url.spec().c_str(),
+ image2_sxg_url.spec().c_str(), image2_url.spec().c_str());
+ const std::string inner_link_headers = base::StringPrintf(
+ "Link: "
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"preload\";as=\"image\";"
+ // imagesrcset says the size of image1 is 320, and the size of image2 is
+ // 160.
+ "imagesrcset=\"%s 320w, %s 160w\";"
+ // imagesizes says the size of the image is 320. So image1 is selected.
+ "imagesizes=\"320px\"",
+ image1_url.spec().c_str(), image1_header_integrity_string.c_str(),
+ image2_url.spec().c_str(), image2_header_integrity_string.c_str(),
+ image2_url.spec().c_str(), image1_url.spec().c_str(),
+ image2_url.spec().c_str());
+
+ RegisterResponse(
+ prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
+ RegisterResponse(image1_path, ResponseEntry(image_contents, "image/png"));
+ RegisterResponse(image2_path, ResponseEntry(image_contents, "image/png"));
+ RegisterResponse(
+ target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry(base::StringPrintf(
+ "<head>"
+ "<title>Prefetch Target (SXG)</title>"
+ "</head>"
+ "<img src=\"%s\" onload=\"document.title='done'\">",
+ image1_url.spec().c_str()),
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"},
+ {"link", outer_link_header}}));
+ RegisterResponse(
+ image1_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a JS
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry(image_contents, "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ MockSignedExchangeHandlerFactory factory(
+ {MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ target_url, "text/html", {inner_link_headers},
+ target_header_integrity),
+ MockSignedExchangeHandlerParams(
+ image1_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ image1_url, "image/png", {}, image1_header_integrity),
+ MockSignedExchangeHandlerParams(
+ image2_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ image2_url, "image/png", {}, image2_header_integrity)});
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ image1_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, image1_sxg_fetch_count);
+ EXPECT_EQ(0, image1_fetch_count);
+ EXPECT_EQ(0, image2_sxg_fetch_count);
+ EXPECT_EQ(0, image2_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+ WaitUntilLoaded(image1_sxg_url);
+
+ const auto cached_exchanges = GetCachedExchanges();
+ EXPECT_EQ(2u, cached_exchanges.size());
+
+ const auto target_it = cached_exchanges.find(target_sxg_url);
+ ASSERT_TRUE(target_it != cached_exchanges.end());
+ EXPECT_EQ(target_sxg_url, target_it->second->outer_url());
+ EXPECT_EQ(target_url, target_it->second->inner_url());
+ EXPECT_EQ(target_header_integrity, *target_it->second->header_integrity());
+
+ const auto image1_it = cached_exchanges.find(image1_sxg_url);
+ ASSERT_TRUE(image1_it != cached_exchanges.end());
+ EXPECT_EQ(image1_sxg_url, image1_it->second->outer_url());
+ EXPECT_EQ(image1_url, image1_it->second->inner_url());
+ EXPECT_EQ(image1_header_integrity, *image1_it->second->header_integrity());
+
+ NavigateToURLAndWaitTitle(target_sxg_url, "done");
+
+ EXPECT_EQ(1, image1_sxg_fetch_count);
+ EXPECT_EQ(0, image1_fetch_count);
+ EXPECT_EQ(0, image2_sxg_fetch_count);
+ EXPECT_EQ(0, image2_fetch_count);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ PrefetchAlternativeSubresourceSXG_CrossOrigin) {
+ int script_sxg_fetch_count = 0;
+ int script_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.sxg";
+ const char* target_path = "/target.html";
+ const char* script_sxg_path = "/script_js.sxg";
+ const char* script_path = "/script.js";
+
+ base::RunLoop script_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script_sxg_path,
+ &script_sxg_fetch_count, &script_sxg_prefetch_waiter);
+ base::RunLoop script_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script_path,
+ &script_fetch_count, &script_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_EQ(0, prefetch_url_loader_called_);
+
+ const GURL target_sxg_url =
+ embedded_test_server()->GetURL("sxg.example.com", target_sxg_path);
+ const GURL target_url =
+ embedded_test_server()->GetURL("publisher.example.com", target_path);
+ const GURL script_sxg_url =
+ embedded_test_server()->GetURL("sxg.example.com", script_sxg_path);
+ const GURL script_url =
+ embedded_test_server()->GetURL("publisher.example.com", script_path);
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ const net::SHA256HashValue script_header_integrity = {{0x02}};
+ const std::string script_header_integrity_string =
+ GetHeaderIntegrityString(script_header_integrity);
+
+ const std::string outer_link_header = base::StringPrintf(
+ "<%s>;"
+ "rel=\"alternate\";"
+ "type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\"",
+ script_sxg_url.spec().c_str(), script_url.spec().c_str());
+ const std::string inner_link_headers = base::StringPrintf(
+ "Link: "
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"preload\";as=\"script\"",
+ script_url.spec().c_str(), script_header_integrity_string.c_str(),
+ script_url.spec().c_str());
+
+ RegisterResponse(prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>",
+ target_sxg_url.spec().c_str())));
+ RegisterResponse(script_path, ResponseEntry("document.title=\"from server\";",
+ "text/javascript"));
+ RegisterResponse(target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("<head><title>Prefetch Target (SXG)</title>"
+ "<script src=\"./script.js\"></script></head>",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"},
+ {"link", outer_link_header}}));
+ RegisterResponse(script_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a JS
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("document.title=\"done\";",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ MockSignedExchangeHandlerFactory factory(
+ {MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ target_url, "text/html", {inner_link_headers},
+ target_header_integrity),
+ MockSignedExchangeHandlerParams(
+ script_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ script_url, "text/javascript", {}, script_header_integrity)});
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ script_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, script_sxg_fetch_count);
+ EXPECT_EQ(0, script_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+ WaitUntilLoaded(script_sxg_url);
+
+ const auto cached_exchanges = GetCachedExchanges();
+ EXPECT_EQ(2u, cached_exchanges.size());
+
+ const auto target_it = cached_exchanges.find(target_sxg_url);
+ ASSERT_TRUE(target_it != cached_exchanges.end());
+ EXPECT_EQ(target_sxg_url, target_it->second->outer_url());
+ EXPECT_EQ(target_url, target_it->second->inner_url());
+ EXPECT_EQ(target_header_integrity, *target_it->second->header_integrity());
+
+ const auto script_it = cached_exchanges.find(script_sxg_url);
+ ASSERT_TRUE(script_it != cached_exchanges.end());
+ EXPECT_EQ(script_sxg_url, script_it->second->outer_url());
+ EXPECT_EQ(script_url, script_it->second->inner_url());
+ EXPECT_EQ(script_header_integrity, *script_it->second->header_integrity());
+
+ // Subsequent navigation to the target URL wouldn't hit the network for
+ // the target URL. The target content should still be read correctly.
+ // The content is loaded from PrefetchedSignedExchangeCache. And the script
+ // is also loaded from PrefetchedSignedExchangeCache.
+ NavigateToURLAndWaitTitle(target_sxg_url, "done");
+
+ EXPECT_EQ(1, script_sxg_fetch_count);
+ EXPECT_EQ(0, script_fetch_count);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ PrefetchAlternativeSubresourceSXG_DifferentOrigin) {
+ int script_sxg_fetch_count = 0;
+ int script_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.sxg";
+ const char* target_path = "/target.html";
+ const char* script_sxg_path = "/script_js.sxg";
+ const char* script_path = "/script.js";
+
+ base::RunLoop script_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script_sxg_path,
+ &script_sxg_fetch_count, &script_sxg_prefetch_waiter);
+ base::RunLoop script_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script_path,
+ &script_fetch_count, &script_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_EQ(0, prefetch_url_loader_called_);
+
+ const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
+ const GURL target_url = embedded_test_server()->GetURL(target_path);
+ // script_js.sxg is served from different origin.
+ const GURL script_sxg_url =
+ embedded_test_server()->GetURL("example.com", script_sxg_path);
+ const GURL script_url = embedded_test_server()->GetURL(script_path);
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ const net::SHA256HashValue script_header_integrity = {{0x02}};
+ const std::string script_header_integrity_string =
+ GetHeaderIntegrityString(script_header_integrity);
+
+ const std::string outer_link_header = base::StringPrintf(
+ "<%s>;"
+ "rel=\"alternate\";"
+ "type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\"",
+ script_sxg_url.spec().c_str(), script_url.spec().c_str());
+ const std::string inner_link_headers = base::StringPrintf(
+ "Link: "
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"preload\";as=\"script\"",
+ script_url.spec().c_str(), script_header_integrity_string.c_str(),
+ script_url.spec().c_str());
+
+ RegisterResponse(
+ prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
+ RegisterResponse(script_path, ResponseEntry("document.title=\"from server\";",
+ "text/javascript"));
+ RegisterResponse(target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("<head><title>Prefetch Target (SXG)</title>"
+ "<script src=\"./script.js\"></script></head>",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"},
+ {"link", outer_link_header}}));
+ RegisterResponse(script_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a JS
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("document.title=\"done\";",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ MockSignedExchangeHandlerFactory factory(
+ {MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ target_url, "text/html", {inner_link_headers},
+ target_header_integrity),
+ MockSignedExchangeHandlerParams(
+ script_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ script_url, "text/javascript", {}, script_header_integrity)});
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ script_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, script_sxg_fetch_count);
+ EXPECT_EQ(0, script_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+ WaitUntilLoaded(script_sxg_url);
+
+ const auto cached_exchanges = GetCachedExchanges();
+ EXPECT_EQ(2u, cached_exchanges.size());
+
+ const auto target_it = cached_exchanges.find(target_sxg_url);
+ ASSERT_TRUE(target_it != cached_exchanges.end());
+ EXPECT_EQ(target_sxg_url, target_it->second->outer_url());
+ EXPECT_EQ(target_url, target_it->second->inner_url());
+ EXPECT_EQ(target_header_integrity, *target_it->second->header_integrity());
+
+ const auto script_it = cached_exchanges.find(script_sxg_url);
+ ASSERT_TRUE(script_it != cached_exchanges.end());
+ EXPECT_EQ(script_sxg_url, script_it->second->outer_url());
+ EXPECT_EQ(script_url, script_it->second->inner_url());
+ EXPECT_EQ(script_header_integrity, *script_it->second->header_integrity());
+
+ // script_js.sxg was served from different origin from target.sxg. So
+ // script.js is loaded from the server.
+ NavigateToURLAndWaitTitle(target_sxg_url, "from server");
+
+ EXPECT_EQ(1, script_sxg_fetch_count);
+ EXPECT_EQ(1, script_fetch_count);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ PrefetchAlternativeSubresourceSXG_MultipleResources) {
+ int script1_sxg_fetch_count = 0;
+ int script1_fetch_count = 0;
+ int script2_sxg_fetch_count = 0;
+ int script2_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.sxg";
+ const char* target_path = "/target.html";
+ const char* script1_sxg_path = "/script1_js.sxg";
+ const char* script1_path = "/script1.js";
+ const char* script2_sxg_path = "/script2_js.sxg";
+ const char* script2_path = "/script2.js";
+
+ base::RunLoop script1_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script1_sxg_path,
+ &script1_sxg_fetch_count,
+ &script1_sxg_prefetch_waiter);
+ base::RunLoop script1_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script1_path,
+ &script1_fetch_count, &script1_prefetch_waiter);
+ base::RunLoop script2_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script2_sxg_path,
+ &script2_sxg_fetch_count,
+ &script2_sxg_prefetch_waiter);
+ base::RunLoop script2_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script2_path,
+ &script2_fetch_count, &script2_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_EQ(0, prefetch_url_loader_called_);
+
+ const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
+ const GURL target_url = embedded_test_server()->GetURL(target_path);
+ const GURL script1_sxg_url = embedded_test_server()->GetURL(script1_sxg_path);
+ const GURL script1_url = embedded_test_server()->GetURL(script1_path);
+ const GURL script2_sxg_url = embedded_test_server()->GetURL(script2_sxg_path);
+ const GURL script2_url = embedded_test_server()->GetURL(script2_path);
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ const net::SHA256HashValue script1_header_integrity = {{0x02}};
+ const std::string script1_header_integrity_string =
+ GetHeaderIntegrityString(script1_header_integrity);
+ const net::SHA256HashValue script2_header_integrity = {{0x03}};
+ const std::string script2_header_integrity_string =
+ GetHeaderIntegrityString(script2_header_integrity);
+
+ const std::string outer_link_header = base::StringPrintf(
+ "<%s>;rel=\"alternate\";type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\","
+ "<%s>;rel=\"alternate\";type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\"",
+ script1_sxg_url.spec().c_str(), script1_url.spec().c_str(),
+ script2_sxg_url.spec().c_str(), script2_url.spec().c_str());
+ const std::string inner_link_headers = base::StringPrintf(
+ "Link: "
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"preload\";as=\"script\","
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"preload\";as=\"script\"",
+ script1_url.spec().c_str(), script1_header_integrity_string.c_str(),
+ script1_url.spec().c_str(), script2_url.spec().c_str(),
+ script2_header_integrity_string.c_str(), script2_url.spec().c_str());
+
+ RegisterResponse(
+ prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
+ RegisterResponse(script1_path, ResponseEntry("var test_title=\"from\";",
+ "text/javascript"));
+ RegisterResponse(script2_path,
+ ResponseEntry("document.title=test_title+\"server\";",
+ "text/javascript"));
+ RegisterResponse(
+ target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("<head><title>Prefetch Target (SXG)</title>"
+ "<script src=\"./script1.js\"></script>"
+ "<script src=\"./script2.js\"></script></head>",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"},
+ {"link", outer_link_header}}));
+ RegisterResponse(script1_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a JS
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("var test_title=\"done\";",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ RegisterResponse(script2_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a JS
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("document.title=test_title;",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ MockSignedExchangeHandlerFactory factory({
+ MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ target_url, "text/html", {inner_link_headers},
+ target_header_integrity),
+ MockSignedExchangeHandlerParams(
+ script1_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ script1_url, "text/javascript", {}, script1_header_integrity),
+ MockSignedExchangeHandlerParams(
+ script2_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ script2_url, "text/javascript", {}, script2_header_integrity),
+ });
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ script1_sxg_prefetch_waiter.Run();
+ script2_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, script1_sxg_fetch_count);
+ EXPECT_EQ(0, script1_fetch_count);
+ EXPECT_EQ(1, script2_sxg_fetch_count);
+ EXPECT_EQ(0, script2_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+ WaitUntilLoaded(script1_sxg_url);
+ WaitUntilLoaded(script2_sxg_url);
+
+ const auto cached_exchanges = GetCachedExchanges();
+ EXPECT_EQ(3u, cached_exchanges.size());
+
+ const auto target_it = cached_exchanges.find(target_sxg_url);
+ ASSERT_TRUE(target_it != cached_exchanges.end());
+ EXPECT_EQ(target_sxg_url, target_it->second->outer_url());
+ EXPECT_EQ(target_url, target_it->second->inner_url());
+ EXPECT_EQ(target_header_integrity, *target_it->second->header_integrity());
+
+ const auto script1_it = cached_exchanges.find(script1_sxg_url);
+ ASSERT_TRUE(script1_it != cached_exchanges.end());
+ EXPECT_EQ(script1_sxg_url, script1_it->second->outer_url());
+ EXPECT_EQ(script1_url, script1_it->second->inner_url());
+ EXPECT_EQ(script1_header_integrity, *script1_it->second->header_integrity());
+
+ const auto script2_it = cached_exchanges.find(script2_sxg_url);
+ ASSERT_TRUE(script2_it != cached_exchanges.end());
+ EXPECT_EQ(script2_sxg_url, script2_it->second->outer_url());
+ EXPECT_EQ(script2_url, script2_it->second->inner_url());
+ EXPECT_EQ(script2_header_integrity, *script2_it->second->header_integrity());
+
+ // Subsequent navigation to the target URL wouldn't hit the network for
+ // the target URL. The target content should still be read correctly.
+ // The content is loaded from PrefetchedSignedExchangeCache. And the scripts
+ // are also loaded from PrefetchedSignedExchangeCache.
+ NavigateToURLAndWaitTitle(target_sxg_url, "done");
+
+ EXPECT_EQ(1, script1_sxg_fetch_count);
+ EXPECT_EQ(0, script1_fetch_count);
+ EXPECT_EQ(1, script2_sxg_fetch_count);
+ EXPECT_EQ(0, script2_fetch_count);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ PrefetchAlternativeSubresourceSXG_SameUrl) {
+ int script_sxg_fetch_count = 0;
+ int script_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.html";
+ const char* target_path = "/target.html";
+ const char* script_sxg_path = "/script.js";
+ const char* script_path = "/script.js";
+
+ base::RunLoop script_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script_sxg_path,
+ &script_sxg_fetch_count, &script_sxg_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_EQ(0, prefetch_url_loader_called_);
+
+ const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
+ const GURL target_url = embedded_test_server()->GetURL(target_path);
+ const GURL script_sxg_url = embedded_test_server()->GetURL(script_sxg_path);
+ const GURL script_url = embedded_test_server()->GetURL(script_path);
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ const net::SHA256HashValue script_header_integrity = {{0x02}};
+ const std::string script_header_integrity_string =
+ GetHeaderIntegrityString(script_header_integrity);
+
+ const std::string outer_link_header = base::StringPrintf(
+ "<%s>;"
+ "rel=\"alternate\";"
+ "type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\"",
+ script_sxg_url.spec().c_str(), script_url.spec().c_str());
+ const std::string inner_link_headers = base::StringPrintf(
+ "Link: "
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"preload\";as=\"script\"",
+ script_url.spec().c_str(), script_header_integrity_string.c_str(),
+ script_url.spec().c_str());
+
+ RegisterResponse(
+ prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
+ RegisterResponse(script_path, ResponseEntry("document.title=\"from server\";",
+ "text/javascript"));
+ RegisterResponse(target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("<head><title>Prefetch Target (SXG)</title>"
+ "<script src=\"./script.js\"></script></head>",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"},
+ {"link", outer_link_header}}));
+ RegisterResponse(script_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a JS
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("document.title=\"done\";",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ MockSignedExchangeHandlerFactory factory(
+ {MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ target_url, "text/html", {inner_link_headers},
+ target_header_integrity),
+ MockSignedExchangeHandlerParams(
+ script_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ script_url, "text/javascript", {}, script_header_integrity)});
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ script_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, script_sxg_fetch_count);
+ EXPECT_EQ(0, script_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+ WaitUntilLoaded(script_sxg_url);
+
+ const auto cached_exchanges = GetCachedExchanges();
+ EXPECT_EQ(2u, cached_exchanges.size());
+
+ const auto target_it = cached_exchanges.find(target_sxg_url);
+ ASSERT_TRUE(target_it != cached_exchanges.end());
+ EXPECT_EQ(target_sxg_url, target_it->second->outer_url());
+ EXPECT_EQ(target_url, target_it->second->inner_url());
+ EXPECT_EQ(target_header_integrity, *target_it->second->header_integrity());
+
+ const auto script_it = cached_exchanges.find(script_sxg_url);
+ ASSERT_TRUE(script_it != cached_exchanges.end());
+ EXPECT_EQ(script_sxg_url, script_it->second->outer_url());
+ EXPECT_EQ(script_url, script_it->second->inner_url());
+ EXPECT_EQ(script_header_integrity, *script_it->second->header_integrity());
+
+ // Subsequent navigation to the target URL wouldn't hit the network for
+ // the target URL. The target content should still be read correctly.
+ // The content is loaded from PrefetchedSignedExchangeCache. And the script
+ // is also loaded from PrefetchedSignedExchangeCache.
+ NavigateToURLAndWaitTitle(target_sxg_url, "done");
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ PrefetchAlternativeSubresourceSXG_IntegrityMismatch) {
+ int script_sxg_fetch_count = 0;
+ int script_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.sxg";
+ const char* target_path = "/target.html";
+ const char* script_path = "/script.js";
+ const char* script_sxg_path = "/script_js.sxg";
+
+ base::RunLoop script_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script_sxg_path,
+ &script_sxg_fetch_count, &script_sxg_prefetch_waiter);
+ base::RunLoop script_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script_path,
+ &script_fetch_count, &script_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_EQ(0, prefetch_url_loader_called_);
+
+ const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
+ const GURL target_url = embedded_test_server()->GetURL(target_path);
+ const GURL script_sxg_url = embedded_test_server()->GetURL(script_sxg_path);
+ const GURL script_url = embedded_test_server()->GetURL(script_path);
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ const net::SHA256HashValue script_header_integrity = {{0x02}};
+ const net::SHA256HashValue wrong_script_header_integrity = {{0x03}};
+ // Use the wrong header integrity value for "allowed-alt-sxg" link header to
+ // trigger the integrity mismatch fallback logic.
+ const std::string script_header_integrity_string =
+ GetHeaderIntegrityString(wrong_script_header_integrity);
+
+ const std::string outer_link_header = base::StringPrintf(
+ "<%s>;"
+ "rel=\"alternate\";"
+ "type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\"",
+ script_sxg_url.spec().c_str(), script_url.spec().c_str());
+ const std::string inner_link_headers = base::StringPrintf(
+ "Link: "
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"preload\";as=\"script\"",
+ script_url.spec().c_str(), script_header_integrity_string.c_str(),
+ script_url.spec().c_str());
+
+ RegisterResponse(
+ prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
+ RegisterResponse(script_path, ResponseEntry("document.title=\"from server\";",
+ "text/javascript"));
+ RegisterResponse(target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("<head><title>Prefetch Target (SXG)</title>"
+ "<script src=\"./script.js\"></script></head>",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"},
+ {"link", outer_link_header}}));
+ RegisterResponse(script_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a JS
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("document.title=\"done\";",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ MockSignedExchangeHandlerFactory factory(
+ {MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ target_url, "text/html", {inner_link_headers},
+ target_header_integrity),
+ MockSignedExchangeHandlerParams(
+ script_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ script_url, "text/javascript", {}, script_header_integrity)});
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ script_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, script_sxg_fetch_count);
+ EXPECT_EQ(0, script_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+ WaitUntilLoaded(script_sxg_url);
+
+ // The value of "header-integrity" in "allowed-alt-sxg" link header of the
+ // inner response doesn't match the actual header integrity of script_js.sxg.
+ // So the script request must go to the server.
+ NavigateToURLAndWaitTitle(target_sxg_url, "from server");
+
+ EXPECT_EQ(1, script_fetch_count);
+}
+
+IN_PROC_BROWSER_TEST_P(
+ SignedExchangeSubresourcePrefetchBrowserTest,
+ PrefetchAlternativeSubresourceSXG_MultipleResources_IntegrityMismatch) {
+ int script1_sxg_fetch_count = 0;
+ int script1_fetch_count = 0;
+ int script2_sxg_fetch_count = 0;
+ int script2_fetch_count = 0;
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.sxg";
+ const char* target_path = "/target.html";
+ const char* script1_sxg_path = "/script1_js.sxg";
+ const char* script1_path = "/script1.js";
+ const char* script2_sxg_path = "/script2_js.sxg";
+ const char* script2_path = "/script2.js";
+
+ base::RunLoop script1_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script1_sxg_path,
+ &script1_sxg_fetch_count,
+ &script1_sxg_prefetch_waiter);
+ base::RunLoop script1_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script1_path,
+ &script1_fetch_count, &script1_prefetch_waiter);
+ base::RunLoop script2_sxg_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script2_sxg_path,
+ &script2_sxg_fetch_count,
+ &script2_sxg_prefetch_waiter);
+ base::RunLoop script2_prefetch_waiter;
+ RegisterRequestMonitor(embedded_test_server(), script2_path,
+ &script2_fetch_count, &script2_prefetch_waiter);
+ RegisterRequestHandler(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_EQ(0, prefetch_url_loader_called_);
+
+ const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
+ const GURL target_url = embedded_test_server()->GetURL(target_path);
+ const GURL script1_sxg_url = embedded_test_server()->GetURL(script1_sxg_path);
+ const GURL script1_url = embedded_test_server()->GetURL(script1_path);
+ const GURL script2_sxg_url = embedded_test_server()->GetURL(script2_sxg_path);
+ const GURL script2_url = embedded_test_server()->GetURL(script2_path);
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+ const net::SHA256HashValue script1_header_integrity = {{0x02}};
+ const std::string script1_header_integrity_string =
+ GetHeaderIntegrityString(script1_header_integrity);
+ const net::SHA256HashValue script2_header_integrity = {{0x03}};
+ const net::SHA256HashValue wrong_script2_header_integrity = {{0x04}};
+ // Use the wrong header integrity value for "allowed-alt-sxg" link header to
+ // trigger the integrity mismatch fallback logic.
+ const std::string script2_header_integrity_string =
+ GetHeaderIntegrityString(wrong_script2_header_integrity);
+
+ const std::string outer_link_header = base::StringPrintf(
+ "<%s>;rel=\"alternate\";type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\","
+ "<%s>;rel=\"alternate\";type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\"",
+ script1_sxg_url.spec().c_str(), script1_url.spec().c_str(),
+ script2_sxg_url.spec().c_str(), script2_url.spec().c_str());
+ const std::string inner_link_headers = base::StringPrintf(
+ "Link: "
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"preload\";as=\"script\","
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"preload\";as=\"script\"",
+ script1_url.spec().c_str(), script1_header_integrity_string.c_str(),
+ script1_url.spec().c_str(), script2_url.spec().c_str(),
+ script2_header_integrity_string.c_str(), script2_url.spec().c_str());
+
+ RegisterResponse(
+ prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
+ RegisterResponse(script1_path, ResponseEntry("var test_title=\"from\";",
+ "text/javascript"));
+ RegisterResponse(script2_path,
+ ResponseEntry("document.title=test_title+\" server\";",
+ "text/javascript"));
+ RegisterResponse(
+ target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("<head><title>Prefetch Target (SXG)</title>"
+ "<script src=\"./script1.js\"></script>"
+ "<script src=\"./script2.js\"></script></head>",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"},
+ {"link", outer_link_header}}));
+ RegisterResponse(script1_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a JS
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("var test_title=\"done\";",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ RegisterResponse(script2_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a JS
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry("document.title=test_title;",
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ MockSignedExchangeHandlerFactory factory({
+ MockSignedExchangeHandlerParams(
+ target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ target_url, "text/html", {inner_link_headers},
+ target_header_integrity),
+ MockSignedExchangeHandlerParams(
+ script1_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ script1_url, "text/javascript", {}, script1_header_integrity),
+ MockSignedExchangeHandlerParams(
+ script2_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK,
+ script2_url, "text/javascript", {}, script2_header_integrity),
+ });
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+ script1_sxg_prefetch_waiter.Run();
+ script2_sxg_prefetch_waiter.Run();
+ EXPECT_EQ(1, script1_sxg_fetch_count);
+ EXPECT_EQ(0, script1_fetch_count);
+ EXPECT_EQ(1, script2_sxg_fetch_count);
+ EXPECT_EQ(0, script2_fetch_count);
+
+ WaitUntilLoaded(target_sxg_url);
+ WaitUntilLoaded(script1_sxg_url);
+ WaitUntilLoaded(script2_sxg_url);
+
+ const auto cached_exchanges = GetCachedExchanges();
+ EXPECT_EQ(3u, cached_exchanges.size());
+
+ // The value of "header-integrity" in "allowed-alt-sxg" link header of the
+ // inner response doesn't match the actual header integrity of script2_js.sxg.
+ // So the all script requests must go to the server.
+ NavigateToURLAndWaitTitle(target_sxg_url, "from server");
+
+ EXPECT_EQ(1, script1_sxg_fetch_count);
+ EXPECT_EQ(1, script1_fetch_count);
+ EXPECT_EQ(1, script2_sxg_fetch_count);
+ EXPECT_EQ(1, script2_fetch_count);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest, CORS) {
+ std::unique_ptr<net::EmbeddedTestServer> data_server =
+ std::make_unique<net::EmbeddedTestServer>(
+ net::EmbeddedTestServer::TYPE_HTTPS);
+
+ const char* prefetch_path = "/prefetch.html";
+ const char* target_sxg_path = "/target.sxg";
+ const char* target_path = "/target.html";
+
+ RegisterRequestHandler(embedded_test_server());
+ RegisterRequestHandler(data_server.get());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ ASSERT_TRUE(data_server->Start());
+
+ std::string test_server_origin = embedded_test_server()->base_url().spec();
+ // Remove the last "/""
+ test_server_origin.pop_back();
+
+ struct {
+ // Set in the main SXG's inner response header.
+ // Example:
+ // Link: <http://***/**.data>;rel="preload";as="fetch";crossorigin
+ // ^^^^^^^^^^^
+ const char* const crossorigin_preload_header;
+ // Set in the data SXG's inner response header.
+ // Example:
+ // Access-Control-Allow-Origin: *
+ // ^
+ const char* const access_control_allow_origin_header;
+ // Set "Access-Control-Allow-Credentials: true" link header in the data
+ // SXG's inner response header.
+ const bool has_access_control_allow_credentials_true_header;
+ // The credentials attribute of Fetch API's request while fetching the data.
+ const char* const request_credentials;
+ // If the data is served from the SXG the result must be "sxg". If the data
+ // is served from the server without SXG, the result must be "server". If
+ // failed to fetch the data, the result must be "failed".
+ const char* const expected_result;
+ } kTestCases[] = {
+ // - If crossorigin is not set in the preload header, cross origin fetch
+ // goes to the server. It is because the mode of the preload request
+ // ("no-cors") and the mode of the fetch request ("cors") doesn't match.
+ {nullptr, nullptr, false, "omit", "server"},
+ {nullptr, nullptr, false, "include", "server"},
+ {nullptr, nullptr, false, "same-origin", "server"},
+
+ // - When "crossorigin" is set in the preload header, the mode of the
+ // preload request is "cors", and the credentials mode is "same-origin".
+ // - When the credentials mode of the fetch request doesn't match, the
+ // fetch request goes to the server.
+ {"crossorigin", nullptr, false, "omit", "server"},
+ {"crossorigin", nullptr, false, "include", "server"},
+ // - When the credentials mode of the fetch request match with the
+ // credentials mode of the preload request, the prefetched signed
+ // exchange is used.
+ // - When the inner response doesn't have ACAO header, fails to load.
+ {"crossorigin", nullptr, false, "same-origin", "failed"},
+ // - When the inner response has "ACAO: *" header, succeeds to load.
+ {"crossorigin", "*", false, "same-origin", "sxg"},
+ // - When the inner response has "ACAO: <origin>" header, succeeds to
+ // load.
+ {"crossorigin", test_server_origin.c_str(), false, "same-origin", "sxg"},
+
+ // - crossorigin="anonymous" must be treated as same as just having
+ // "crossorigin".
+ {"crossorigin=\"anonymous\"", nullptr, false, "omit", "server"},
+ {"crossorigin=\"anonymous\"", nullptr, false, "include", "server"},
+ {"crossorigin=\"anonymous\"", nullptr, false, "same-origin", "failed"},
+ {"crossorigin=\"anonymous\"", "*", false, "same-origin", "sxg"},
+ {"crossorigin=\"anonymous\"", test_server_origin.c_str(), false,
+ "same-origin", "sxg"},
+
+ // - When crossorigin="use-credentials" is set in the preload header, the
+ // mode of the preload request is "cors", and the credentials mode is
+ // "include".
+ // - When the credentials mode of the fetch request doesn't match, the
+ // fetch request goes to the server.
+ {"crossorigin=\"use-credentials\"", nullptr, false, "omit", "server"},
+ {"crossorigin=\"use-credentials\"", nullptr, false, "same-origin",
+ "server"},
+ // - When the credentials mode of the fetch request match with the
+ // credentials mode of the preload request, the prefetched signed
+ // exchange is used.
+ // - When the inner response doesn't have ACAO header, fails to load.
+ {"crossorigin=\"use-credentials\"", nullptr, false, "include", "failed"},
+ // - Even if the inner response has "ACAO: *" header, fails to load
+ // the "include" credentials mode request.
+ {"crossorigin=\"use-credentials\"", "*", false, "include", "failed"},
+ // - Even if the inner response has "ACAO: *" header and "ACAC: true"
+ // header, fails to load the "include" credentials mode request.
+ {"crossorigin=\"use-credentials\"", "*", true, "include", "failed"},
+ // - Even if the inner response has "ACAO: <origin>" header, fails to
+ // load the "include" credentials mode request.
+ {"crossorigin=\"use-credentials\"", test_server_origin.c_str(), false,
+ "include", "failed"},
+ // - If the inner response has "ACAO: <origin>" header, and
+ // "ACAC: true" header, succeeds to load.
+ {"crossorigin=\"use-credentials\"", test_server_origin.c_str(), true,
+ "include", "sxg"},
+ };
+
+ const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path);
+ const GURL target_url = embedded_test_server()->GetURL(target_path);
+
+ const net::SHA256HashValue target_header_integrity = {{0x01}};
+
+ std::string target_sxg_outer_link_header;
+ std::string target_sxg_inner_link_header("Link: ");
+ std::string requests_list_string;
+
+ std::vector<MockSignedExchangeHandlerParams> mock_params;
+ for (size_t i = 0; i < base::size(kTestCases); ++i) {
+ if (i) {
+ target_sxg_outer_link_header += ",";
+ target_sxg_inner_link_header += ",";
+ requests_list_string += ",";
+ }
+ const std::string data_sxg_path = base::StringPrintf("/%zu_data.sxg", i);
+ const std::string data_path = base::StringPrintf("/%zu.data", i);
+ const GURL data_sxg_url = embedded_test_server()->GetURL(data_sxg_path);
+ const GURL data_url = data_server->GetURL(data_path);
+ requests_list_string += base::StringPrintf(
+ "new Request('%s', {credentials: '%s'})", data_url.spec().c_str(),
+ kTestCases[i].request_credentials);
+ const net::SHA256HashValue data_header_integrity = {{0x02 + i}};
+ const std::string data_header_integrity_string =
+ GetHeaderIntegrityString(data_header_integrity);
+
+ target_sxg_outer_link_header += base::StringPrintf(
+ "<%s>;rel=\"alternate\";type=\"application/signed-exchange;v=b3\";"
+ "anchor=\"%s\"",
+ data_sxg_url.spec().c_str(), data_url.spec().c_str());
+
+ target_sxg_inner_link_header += base::StringPrintf(
+ "<%s>;rel=\"allowed-alt-sxg\";header-integrity=\"%s\","
+ "<%s>;rel=\"preload\";as=\"fetch\"",
+ data_url.spec().c_str(), data_header_integrity_string.c_str(),
+ data_url.spec().c_str());
+ if (kTestCases[i].crossorigin_preload_header) {
+ target_sxg_inner_link_header +=
+ base::StringPrintf(";%s", kTestCases[i].crossorigin_preload_header);
+ }
+ RegisterResponse(data_sxg_path,
+ ResponseEntry("sxg", "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"}}));
+ RegisterResponse(
+ data_path,
+ ResponseEntry(
+ "server", "text/plain",
+ {{"Access-Control-Allow-Origin", test_server_origin.c_str()},
+ {"Access-Control-Allow-Credentials", "true"}}));
+ std::vector<std::string> data_sxg_inner_headers;
+ if (kTestCases[i].access_control_allow_origin_header) {
+ data_sxg_inner_headers.emplace_back(
+ base::StringPrintf("Access-Control-Allow-Origin: %s",
+ kTestCases[i].access_control_allow_origin_header));
+ }
+ if (kTestCases[i].has_access_control_allow_credentials_true_header) {
+ data_sxg_inner_headers.emplace_back(
+ "Access-Control-Allow-Credentials: true");
+ }
+ mock_params.emplace_back(
+ data_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK, data_url,
+ "text/plain", std::move(data_sxg_inner_headers), data_header_integrity);
+ }
+
+ std::vector<std::string> target_sxg_inner_headers = {
+ std::move(target_sxg_inner_link_header)};
+ mock_params.emplace_back(target_sxg_url, SignedExchangeLoadResult::kSuccess,
+ net::OK, target_url, "text/html",
+ std::move(target_sxg_inner_headers),
+ target_header_integrity);
+ MockSignedExchangeHandlerFactory factory(std::move(mock_params));
+
+ RegisterResponse(
+ prefetch_path,
+ ResponseEntry(base::StringPrintf(
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg_path)));
+ RegisterResponse(
+ target_sxg_path,
+ // We mock the SignedExchangeHandler, so just return a HTML
+ // content as "application/signed-exchange;v=b3".
+ ResponseEntry(base::StringPrintf(R"(
+<head><title>Prefetch Target (SXG)</title><script>
+let results = [];
+(async function(requests) {
+ for (let i = 0; i < requests.length; ++i) {
+ try {
+ const res = await fetch(requests[i]);
+ results.push(await res.text());
+ } catch (err) {
+ results.push('failed');
+ }
+ }
+ document.title = 'done';
+})([%s]);
+</script></head>)",
+ requests_list_string.c_str()),
+ "application/signed-exchange;v=b3",
+ {{"x-content-type-options", "nosniff"},
+ {"link", target_sxg_outer_link_header}}));
+
+ ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path));
+
+ // Wait until all (main- and sub-resource) SXGs are prefetched.
+ while (GetCachedExchanges().size() < base::size(kTestCases) + 1) {
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
+ run_loop.Run();
+ }
+
+ NavigateToURLAndWaitTitle(target_sxg_url, "done");
+
+ for (size_t i = 0; i < base::size(kTestCases); ++i) {
+ SCOPED_TRACE(base::StringPrintf("TestCase %zu", i));
+ EXPECT_EQ(
+ EvalJs(shell(), base::StringPrintf("results[%zu]", i)).ExtractString(),
+ kTestCases[i].expected_result);
+ }
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ CrossOriginReadBlocking_AllowedAfterSniffing) {
+ RunCrossOriginReadBlockingTest(
+ true /* cross_origin */, "document.title=\"done\"", "text/javascript",
+ false /* has_nosniff */, "done",
+ network::CrossOriginReadBlocking::Action::kAllowedAfterSniffing);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ CrossOriginReadBlocking_BlockedAfterSniffing) {
+ RunCrossOriginReadBlockingTest(
+ true /* cross_origin */, "<!DOCTYPE html>hello;", "text/html",
+ false /* has_nosniff */, "original title",
+ network::CrossOriginReadBlocking::Action::kBlockedAfterSniffing);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ CrossOriginReadBlocking_AllowedWithoutSniffing) {
+ RunCrossOriginReadBlockingTest(
+ false /* cross_origin */, "document.title=\"done\"", "text/javascript",
+ true /* has_nosniff */, "done",
+ network::CrossOriginReadBlocking::Action::kAllowedWithoutSniffing);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+ CrossOriginReadBlocking_BlockedWithoutSniffing) {
+ RunCrossOriginReadBlockingTest(
+ true /* cross_origin */, "<!DOCTYPE html>hello;", "text/html",
+ true /* has_nosniff */, "original title",
+ network::CrossOriginReadBlocking::Action::kBlockedWithoutSniffing);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ SignedExchangeSubresourcePrefetchBrowserTest,
+ SignedExchangeSubresourcePrefetchBrowserTest,
+ testing::Values(SignedExchangeSubresourcePrefetchBrowserTestParam(false),
+ SignedExchangeSubresourcePrefetchBrowserTestParam(true)));
+} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_test_utils.h b/chromium/content/browser/web_package/signed_exchange_test_utils.h
new file mode 100644
index 00000000000..76d44f0f30b
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_test_utils.h
@@ -0,0 +1,17 @@
+// Copyright 2019 The Chromium Authors. All rights 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_TEST_UTILS_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_TEST_UTILS_H_
+
+namespace content {
+
+constexpr char kPEMECDSAP256SPKIHash[] =
+ "/e65FnHy30VS3LY9z8f0bNU1v6IQbg7g/mhGEQ11Im0=";
+constexpr char kPEMECDSAP384SPKIHash[] =
+ "V8vLfOEWuDlMqzl7Ki6PmnvSepqzjY1qU0gl+DrEh9A=";
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_TEST_UTILS_H_
diff --git a/chromium/content/browser/web_package/signed_exchange_utils.cc b/chromium/content/browser/web_package/signed_exchange_utils.cc
index 50da2ec0368..a7248ef6748 100644
--- a/chromium/content/browser/web_package/signed_exchange_utils.cc
+++ b/chromium/content/browser/web_package/signed_exchange_utils.cc
@@ -94,7 +94,7 @@ base::Optional<SignedExchangeVersion> GetSignedExchangeVersion(
net::HttpUtil::NameValuePairsIterator parser(
content_type.begin() + semicolon + 1, content_type.end(), ';');
while (parser.GetNext()) {
- const base::StringPiece name(parser.name_begin(), parser.name_end());
+ const base::StringPiece name = parser.name_piece();
params[base::ToLowerASCII(name)] = parser.value();
}
if (!parser.valid())
@@ -194,5 +194,60 @@ SignedExchangeLoadResult GetLoadResultFromSignatureVerifierResult(
return SignedExchangeLoadResult::kSignatureVerificationError;
}
+net::RedirectInfo CreateRedirectInfo(
+ const GURL& new_url,
+ const network::ResourceRequest& outer_request,
+ const network::ResourceResponseHead& outer_response,
+ bool is_fallback_redirect) {
+ // https://wicg.github.io/webpackage/loading.html#mp-http-fetch
+ // Step 3. Set actualResponse's status to 303. [spec text]
+ return net::RedirectInfo::ComputeRedirectInfo(
+ "GET", outer_request.url, outer_request.site_for_cookies,
+ outer_request.top_frame_origin,
+ outer_request.update_first_party_url_on_redirect
+ ? net::URLRequest::FirstPartyURLPolicy::
+ UPDATE_FIRST_PARTY_URL_ON_REDIRECT
+ : net::URLRequest::FirstPartyURLPolicy::NEVER_CHANGE_FIRST_PARTY_URL,
+ outer_request.referrer_policy, outer_request.referrer.spec(), 303,
+ new_url,
+ net::RedirectUtil::GetReferrerPolicyHeader(outer_response.headers.get()),
+ false /* insecure_scheme_was_upgraded */, true /* copy_fragment */,
+ is_fallback_redirect);
+}
+
+network::ResourceResponseHead CreateRedirectResponseHead(
+ const network::ResourceResponseHead& outer_response,
+ bool is_fallback_redirect) {
+ network::ResourceResponseHead response_head;
+ response_head.encoded_data_length = 0;
+ std::string buf;
+ std::string link_header;
+ if (!is_fallback_redirect &&
+ base::FeatureList::IsEnabled(
+ features::kSignedExchangeSubresourcePrefetch) &&
+ outer_response.headers) {
+ outer_response.headers->GetNormalizedHeader("link", &link_header);
+ }
+ if (link_header.empty()) {
+ buf = base::StringPrintf("HTTP/1.1 %d %s\r\n", 303, "See Other");
+ } else {
+ DCHECK(base::FeatureList::IsEnabled(
+ features::kSignedExchangeSubresourcePrefetch));
+ buf = base::StringPrintf(
+ "HTTP/1.1 %d %s\r\n"
+ "link: %s\r\n",
+ 303, "See Other", link_header.c_str());
+ }
+ response_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(buf));
+ response_head.encoded_data_length = 0;
+ response_head.request_start = outer_response.request_start;
+ response_head.response_start = outer_response.response_start;
+ response_head.request_time = outer_response.request_time;
+ response_head.response_time = outer_response.response_time;
+ response_head.load_timing = outer_response.load_timing;
+ return response_head;
+}
+
} // namespace signed_exchange_utils
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_utils.h b/chromium/content/browser/web_package/signed_exchange_utils.h
index 44ec88f599d..1500b0f4e56 100644
--- a/chromium/content/browser/web_package/signed_exchange_utils.h
+++ b/chromium/content/browser/web_package/signed_exchange_utils.h
@@ -12,9 +12,12 @@
#include "content/browser/web_package/signed_exchange_error.h"
#include "content/browser/web_package/signed_exchange_signature_verifier.h"
#include "content/common/content_export.h"
+#include "net/url_request/redirect_util.h"
+#include "services/network/public/cpp/resource_response.h"
#include "url/gurl.h"
namespace network {
+struct ResourceRequest;
struct ResourceResponseHead;
} // namespace network
@@ -73,6 +76,19 @@ CONTENT_EXPORT base::Optional<SignedExchangeVersion> GetSignedExchangeVersion(
SignedExchangeLoadResult GetLoadResultFromSignatureVerifierResult(
SignedExchangeSignatureVerifier::Result verify_result);
+// Creates a RedirectInfo of synthesized redirect for signed exchange loading.
+net::RedirectInfo CreateRedirectInfo(
+ const GURL& new_url,
+ const network::ResourceRequest& outer_request,
+ const network::ResourceResponseHead& outer_response,
+ bool is_fallback_redirect);
+
+// Creates a ResourceResponseHead of synthesized redirect for signed exchange
+// loading.
+network::ResourceResponseHead CreateRedirectResponseHead(
+ const network::ResourceResponseHead& outer_response,
+ bool is_fallback_redirect);
+
} // namespace signed_exchange_utils
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_validity_pinger.cc b/chromium/content/browser/web_package/signed_exchange_validity_pinger.cc
index f6cfef6da94..6d7ab970f6b 100644
--- a/chromium/content/browser/web_package/signed_exchange_validity_pinger.cc
+++ b/chromium/content/browser/web_package/signed_exchange_validity_pinger.cc
@@ -131,7 +131,7 @@ void SignedExchangeValidityPinger::OnUploadProgress(
}
void SignedExchangeValidityPinger::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
+ mojo_base::BigBuffer data) {
NOTREACHED();
}
diff --git a/chromium/content/browser/web_package/signed_exchange_validity_pinger.h b/chromium/content/browser/web_package/signed_exchange_validity_pinger.h
index d17c1d09be0..18ff4465cc6 100644
--- a/chromium/content/browser/web_package/signed_exchange_validity_pinger.h
+++ b/chromium/content/browser/web_package/signed_exchange_validity_pinger.h
@@ -55,7 +55,7 @@ class CONTENT_EXPORT SignedExchangeValidityPinger
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
diff --git a/chromium/content/browser/webauth/DEPS b/chromium/content/browser/webauth/DEPS
index 8d0f2ca5aa4..3030fce1ef3 100644
--- a/chromium/content/browser/webauth/DEPS
+++ b/chromium/content/browser/webauth/DEPS
@@ -1,3 +1,9 @@
include_rules = [
- "+device",
+ "+device",
]
+
+specific_include_rules = {
+ "authenticator_impl_unittest\.cc": [
+ "+components/autofill/content/browser/webauthn/internal_authenticator_impl.h"
+ ]
+}
diff --git a/chromium/content/browser/webauth/authenticator_common.cc b/chromium/content/browser/webauth/authenticator_common.cc
index 47f990f9e12..bec47722223 100644
--- a/chromium/content/browser/webauth/authenticator_common.cc
+++ b/chromium/content/browser/webauth/authenticator_common.cc
@@ -11,6 +11,7 @@
#include "base/base64url.h"
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
@@ -19,6 +20,7 @@
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "content/browser/bad_message.h"
+#include "content/browser/webauth/authenticator_environment_impl.h"
#include "content/browser/webauth/authenticator_type_converters.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
@@ -29,6 +31,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/service_manager_connection.h"
#include "crypto/sha2.h"
@@ -129,9 +132,9 @@ bool OriginIsCryptoTokenExtension(const url::Origin& origin) {
bool HasValidEffectiveDomain(url::Origin caller_origin) {
// For calls originating in the CryptoToken U2F extension, allow CryptoToken
// to validate domain.
- if (OriginIsCryptoTokenExtension(caller_origin) &&
- base::FeatureList::IsEnabled(device::kWebAuthProxyCryptotoken))
+ if (OriginIsCryptoTokenExtension(caller_origin)) {
return true;
+ }
return !caller_origin.opaque() &&
!url::HostIsIPAddress(caller_origin.host()) &&
@@ -151,9 +154,9 @@ bool HasValidEffectiveDomain(url::Origin caller_origin) {
// https://html.spec.whatwg.org/multipage/origin.html#is-a-registrable-domain-suffix-of-or-is-equal-to.
bool IsRelyingPartyIdValid(const std::string& relying_party_id,
url::Origin caller_origin) {
- if (OriginIsCryptoTokenExtension(caller_origin) &&
- base::FeatureList::IsEnabled(device::kWebAuthProxyCryptotoken))
+ if (OriginIsCryptoTokenExtension(caller_origin)) {
return true;
+ }
if (relying_party_id.empty())
return false;
@@ -189,8 +192,7 @@ base::Optional<std::string> ProcessAppIdExtension(std::string appid,
const url::Origin& origin) {
// The CryptoToken U2F extension checks the appid before calling the WebAuthn
// API so there is no need to validate it here.
- if (OriginIsCryptoTokenExtension(origin) &&
- base::FeatureList::IsEnabled(device::kWebAuthProxyCryptotoken)) {
+ if (OriginIsCryptoTokenExtension(origin)) {
if (!GURL(appid).is_valid()) {
DCHECK(false) << "cryptotoken request did not set a valid App ID";
return base::nullopt;
@@ -285,16 +287,26 @@ device::CtapMakeCredentialRequest CreateCtapMakeCredentialRequest(
mojo::ConvertTo<device::PublicKeyCredentialUserEntity>(options->user),
device::PublicKeyCredentialParams(std::move(credential_params)));
- auto exclude_list =
+ make_credential_param.exclude_list =
mojo::ConvertTo<std::vector<device::PublicKeyCredentialDescriptor>>(
options->exclude_credentials);
- make_credential_param.SetExcludeList(std::move(exclude_list));
- make_credential_param.SetHmacSecret(options->hmac_create_secret);
- make_credential_param.set_is_incognito_mode(is_incognito);
+ make_credential_param.hmac_secret = options->hmac_create_secret;
+ make_credential_param.is_incognito_mode = is_incognito;
return make_credential_param;
}
+// 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::array<uint8_t, crypto::kSHA256Length> CreateApplicationParameter(
+ const std::string& relying_party_id) {
+ std::array<uint8_t, crypto::kSHA256Length> application_parameter;
+ crypto::SHA256HashString(relying_party_id, application_parameter.data(),
+ application_parameter.size());
+ return application_parameter;
+}
+
device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
const std::string& client_data_json,
const blink::mojom::PublicKeyCredentialRequestOptionsPtr& options,
@@ -303,39 +315,29 @@ device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
device::CtapGetAssertionRequest request_parameter(options->relying_party_id,
client_data_json);
- auto allowed_list =
+ request_parameter.allow_list =
mojo::ConvertTo<std::vector<device::PublicKeyCredentialDescriptor>>(
options->allow_credentials);
- request_parameter.SetAllowList(std::move(allowed_list));
- request_parameter.SetUserVerification(
+ request_parameter.user_verification =
mojo::ConvertTo<device::UserVerificationRequirement>(
- options->user_verification));
+ options->user_verification);
if (app_id) {
- request_parameter.SetAppId(std::move(*app_id));
+ request_parameter.alternative_application_parameter =
+ CreateApplicationParameter(*app_id);
+ request_parameter.app_id = std::move(*app_id);
}
if (!options->cable_authentication_data.empty()) {
- request_parameter.SetCableExtension(
+ request_parameter.cable_extension =
mojo::ConvertTo<std::vector<device::CableDiscoveryData>>(
- options->cable_authentication_data));
+ options->cable_authentication_data);
}
- request_parameter.set_is_incognito_mode(is_incognito);
+ request_parameter.is_incognito_mode = is_incognito;
return request_parameter;
}
-// 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::array<uint8_t, crypto::kSHA256Length> CreateApplicationParameter(
- const std::string& relying_party_id) {
- std::array<uint8_t, crypto::kSHA256Length> application_parameter;
- crypto::SHA256HashString(relying_party_id, application_parameter.data(),
- application_parameter.size());
- return application_parameter;
-}
-
// Parses the FIDO transport types extension from the DER-encoded, X.509
// certificate in |der_cert| and appends any unique transport types found to
// |out_transports|.
@@ -494,6 +496,10 @@ std::string Base64UrlEncode(const base::span<const uint8_t> input) {
}
base::flat_set<device::FidoTransportProtocol> GetTransportsEnabledByFlags() {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableWebAuthTestingAPI)) {
+ return device::GetAllTransportProtocols();
+ }
base::flat_set<device::FidoTransportProtocol> transports;
transports.insert(device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
transports.insert(device::FidoTransportProtocol::kInternal);
@@ -591,7 +597,7 @@ void AuthenticatorCommon::MakeCredential(
// requests if cryptotoken sends a new one such that requests from before
// a navigation event do not prevent new requests. See
// https://crbug.com/935480.
- Cancel();
+ CancelWithStatus(blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR);
} else {
std::move(callback).Run(
blink::mojom::AuthenticatorStatus::PENDING_REQUEST, nullptr);
@@ -639,8 +645,10 @@ void AuthenticatorCommon::MakeCredential(
return;
}
- if (options->authenticator_selection &&
- options->authenticator_selection->require_resident_key &&
+ const bool resident_key =
+ options->authenticator_selection &&
+ options->authenticator_selection->require_resident_key;
+ if (resident_key &&
(!base::FeatureList::IsEnabled(device::kWebAuthResidentKeys) ||
!request_delegate_->SupportsResidentKeys())) {
// Disallow the creation of resident credentials.
@@ -650,6 +658,43 @@ void AuthenticatorCommon::MakeCredential(
return;
}
+ auto authenticator_selection_criteria =
+ options->authenticator_selection
+ ? mojo::ConvertTo<device::AuthenticatorSelectionCriteria>(
+ options->authenticator_selection)
+ : device::AuthenticatorSelectionCriteria();
+
+ // Reject any non-sensical credProtect extension values.
+ if ( // Can't require the default policy (or no policy).
+ (options->enforce_protection_policy &&
+ (options->protection_policy ==
+ blink::mojom::ProtectionPolicy::UNSPECIFIED ||
+ options->protection_policy == blink::mojom::ProtectionPolicy::NONE)) ||
+ // For non-resident keys, NONE doesn't make sense. (UV_OR_CRED_ID_REQUIRED
+ // does because, with CTAP 2.0, just because a resident key isn't
+ // _required_ doesn't mean that one won't be created and an RP might want
+ // credProtect to take effect if that happens.)
+ (!resident_key &&
+ options->protection_policy == blink::mojom::ProtectionPolicy::NONE) ||
+ // UV_REQUIRED only makes sense if UV is required overall.
+ (options->protection_policy ==
+ blink::mojom::ProtectionPolicy::UV_REQUIRED &&
+ authenticator_selection_criteria.user_verification_requirement() !=
+ device::UserVerificationRequirement::kRequired)) {
+ InvokeCallbackAndCleanup(
+ std::move(callback),
+ blink::mojom::AuthenticatorStatus::PROTECTION_POLICY_INCONSISTENT);
+ return;
+ }
+
+ if (options->protection_policy ==
+ blink::mojom::ProtectionPolicy::UNSPECIFIED &&
+ resident_key) {
+ // If not specified, UV_OR_CRED_ID_REQUIRED is made the default.
+ options->protection_policy =
+ blink::mojom::ProtectionPolicy::UV_OR_CRED_ID_REQUIRED;
+ }
+
DCHECK(make_credential_response_callback_.is_null());
make_credential_response_callback_ = std::move(callback);
@@ -690,16 +735,10 @@ void AuthenticatorCommon::MakeCredential(
{device::FidoTransportProtocol::kUsbHumanInterfaceDevice})
: transports_;
- auto authenticator_selection_criteria =
- options->authenticator_selection
- ? mojo::ConvertTo<device::AuthenticatorSelectionCriteria>(
- options->authenticator_selection)
- : device::AuthenticatorSelectionCriteria();
-
auto ctap_request = CreateCtapMakeCredentialRequest(
client_data_json_, options, browser_context()->IsOffTheRecord());
// On dual protocol CTAP2/U2F devices, force credential creation over U2F.
- ctap_request.set_is_u2f_only(OriginIsCryptoTokenExtension(caller_origin_));
+ ctap_request.is_u2f_only = OriginIsCryptoTokenExtension(caller_origin_);
// Compute the effective attestation conveyance preference and set
// |attestation_requested_| for showing the attestation consent prompt later.
@@ -710,18 +749,36 @@ void AuthenticatorCommon::MakeCredential(
relying_party_id_)) {
attestation = ::device::AttestationConveyancePreference::DIRECT;
}
- ctap_request.set_attestation_preference(attestation);
+ ctap_request.attestation_preference = attestation;
attestation_requested_ =
attestation != ::device::AttestationConveyancePreference::NONE;
+ switch (options->protection_policy) {
+ case blink::mojom::ProtectionPolicy::UNSPECIFIED:
+ case blink::mojom::ProtectionPolicy::NONE:
+ break;
+ case blink::mojom::ProtectionPolicy::UV_OR_CRED_ID_REQUIRED:
+ ctap_request.cred_protect =
+ std::make_pair(device::CredProtect::kUVOrCredIDRequired,
+ options->enforce_protection_policy);
+ break;
+ case blink::mojom::ProtectionPolicy::UV_REQUIRED:
+ ctap_request.cred_protect = std::make_pair(
+ device::CredProtect::kUVRequired, options->enforce_protection_policy);
+ break;
+ }
+
request_ = std::make_unique<device::MakeCredentialRequestHandler>(
- connector_, transports, std::move(ctap_request),
+ connector_,
+ AuthenticatorEnvironmentImpl::GetInstance()->GetFactory(
+ render_frame_host_),
+ transports, std::move(ctap_request),
std::move(authenticator_selection_criteria),
base::BindOnce(&AuthenticatorCommon::OnRegisterResponse,
weak_factory_.GetWeakPtr()));
request_delegate_->RegisterActionCallbacks(
- base::BindOnce(&AuthenticatorCommon::Cancel,
+ base::BindOnce(&AuthenticatorCommon::OnCancelFromUI,
weak_factory_.GetWeakPtr()) /* cancel_callback */,
base::BindRepeating(
&device::FidoRequestHandlerBase::StartAuthenticatorRequest,
@@ -732,8 +789,7 @@ void AuthenticatorCommon::MakeCredential(
base::BindRepeating(
&device::FidoRequestHandlerBase::InitiatePairingWithDevice,
request_->GetWeakPtr()) /* ble_pairing_callback */);
- if (options->authenticator_selection &&
- options->authenticator_selection->require_resident_key) {
+ if (resident_key) {
request_delegate_->SetMightCreateResidentCredential(true);
}
request_->set_observer(request_delegate_.get());
@@ -754,7 +810,7 @@ void AuthenticatorCommon::GetAssertion(
// requests if cryptotoken sends a new one such that requests from before
// a navigation event do not prevent new requests. See
// https://crbug.com/935480.
- Cancel();
+ CancelWithStatus(blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR);
} else {
std::move(callback).Run(
blink::mojom::AuthenticatorStatus::PENDING_REQUEST, nullptr);
@@ -856,16 +912,20 @@ void AuthenticatorCommon::GetAssertion(
auto ctap_request = CreateCtapGetAssertionRequest(
client_data_json_, std::move(options), app_id_,
browser_context()->IsOffTheRecord());
+ ctap_request.is_u2f_only = OriginIsCryptoTokenExtension(caller_origin_);
auto opt_platform_authenticator_info =
CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists(
ctap_request);
request_ = std::make_unique<device::GetAssertionRequestHandler>(
- connector_, transports, std::move(ctap_request),
+ connector_,
+ AuthenticatorEnvironmentImpl::GetInstance()->GetFactory(
+ render_frame_host_),
+ transports, std::move(ctap_request),
base::BindOnce(&AuthenticatorCommon::OnSignResponse,
weak_factory_.GetWeakPtr()));
request_delegate_->RegisterActionCallbacks(
- base::BindOnce(&AuthenticatorCommon::Cancel,
+ base::BindOnce(&AuthenticatorCommon::OnCancelFromUI,
weak_factory_.GetWeakPtr()) /* cancel_callback */,
base::BindRepeating(
&device::FidoRequestHandlerBase::StartAuthenticatorRequest,
@@ -922,7 +982,9 @@ bool AuthenticatorCommon::IsUserVerifyingPlatformAuthenticatorAvailableImpl(
->IsWebAuthenticationTouchIdAuthenticatorSupported())
return false;
- return device::fido::mac::TouchIdAuthenticator::IsAvailable();
+ auto opt_config = request_delegate->GetTouchIdAuthenticatorConfig();
+ return opt_config &&
+ device::fido::mac::TouchIdAuthenticator::IsAvailable(*opt_config);
#elif defined(OS_WIN)
return base::FeatureList::IsEnabled(device::kWebAuthUseNativeWinApi) &&
device::WinWebAuthnApiAuthenticator::
@@ -932,6 +994,10 @@ bool AuthenticatorCommon::IsUserVerifyingPlatformAuthenticatorAvailableImpl(
#endif
}
+void AuthenticatorCommon::Cancel() {
+ CancelWithStatus(blink::mojom::AuthenticatorStatus::ABORT_ERROR);
+}
+
// Callback to handle the async registration response from a U2fDevice.
void AuthenticatorCommon::OnRegisterResponse(
device::FidoReturnCode status_code,
@@ -995,6 +1061,19 @@ void AuthenticatorCommon::OnRegisterResponse(
AuthenticatorRequestClientDelegate::InterestingFailureReason::
kAuthenticatorMissingUserVerification);
return;
+ case device::FidoReturnCode::kAuthenticatorMissingCredentialManagement:
+ NOTREACHED()
+ << "This should only be reachable from CredentialManagementHandler";
+ InvokeCallbackAndCleanup(
+ std::move(make_credential_response_callback_),
+ blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr,
+ Focus::kDoCheck);
+ return;
+ case device::FidoReturnCode::kStorageFull:
+ SignalFailureToRequestDelegate(
+ AuthenticatorRequestClientDelegate::InterestingFailureReason::
+ kStorageFull);
+ return;
case device::FidoReturnCode::kSuccess:
DCHECK(response_data.has_value());
@@ -1181,6 +1260,19 @@ void AuthenticatorCommon::OnSignResponse(
AuthenticatorRequestClientDelegate::InterestingFailureReason::
kAuthenticatorMissingUserVerification);
return;
+ case device::FidoReturnCode::kAuthenticatorMissingCredentialManagement:
+ NOTREACHED()
+ << "This should only be reachable from CredentialManagementHandler";
+ InvokeCallbackAndCleanup(
+ std::move(get_assertion_response_callback_),
+ blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR);
+ return;
+ case device::FidoReturnCode::kStorageFull:
+ NOTREACHED() << "Should not be possible for assertions.";
+ SignalFailureToRequestDelegate(
+ AuthenticatorRequestClientDelegate::InterestingFailureReason::
+ kStorageFull);
+ return;
case device::FidoReturnCode::kSuccess:
DCHECK(response_data.has_value());
@@ -1228,7 +1320,7 @@ void AuthenticatorCommon::SignalFailureToRequestDelegate(
break;
case AuthenticatorRequestClientDelegate::InterestingFailureReason::
kKeyNotRegistered:
- status = blink::mojom::AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED;
+ status = blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
break;
case AuthenticatorRequestClientDelegate::InterestingFailureReason::kTimeout:
status = blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
@@ -1253,6 +1345,10 @@ void AuthenticatorCommon::SignalFailureToRequestDelegate(
kAuthenticatorMissingUserVerification:
status = blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
break;
+ case AuthenticatorRequestClientDelegate::InterestingFailureReason::
+ kStorageFull:
+ status = blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
+ break;
}
error_awaiting_user_acknowledgement_ = status;
@@ -1264,22 +1360,9 @@ void AuthenticatorCommon::SignalFailureToRequestDelegate(
request_->CancelActiveAuthenticators();
return;
}
-
- FailWithErrorAndCleanup();
+ CancelWithStatus(error_awaiting_user_acknowledgement_);
} // namespace content
-void AuthenticatorCommon::FailWithErrorAndCleanup() {
- DCHECK(make_credential_response_callback_ ||
- get_assertion_response_callback_);
- if (make_credential_response_callback_) {
- InvokeCallbackAndCleanup(std::move(make_credential_response_callback_),
- error_awaiting_user_acknowledgement_);
- } else if (get_assertion_response_callback_) {
- InvokeCallbackAndCleanup(std::move(get_assertion_response_callback_),
- error_awaiting_user_acknowledgement_);
- }
-}
-
// TODO(crbug.com/814418): Add web tests to verify timeouts are
// indistinguishable from NOT_ALLOWED_ERROR cases.
void AuthenticatorCommon::OnTimeout() {
@@ -1294,12 +1377,22 @@ void AuthenticatorCommon::OnTimeout() {
AuthenticatorRequestClientDelegate::InterestingFailureReason::kTimeout);
}
-void AuthenticatorCommon::Cancel() {
+void AuthenticatorCommon::CancelWithStatus(
+ blink::mojom::AuthenticatorStatus status) {
// If response callback is invoked already, then ignore cancel request.
if (!make_credential_response_callback_ && !get_assertion_response_callback_)
return;
+ if (make_credential_response_callback_) {
+ InvokeCallbackAndCleanup(std::move(make_credential_response_callback_),
+ status);
+ } else if (get_assertion_response_callback_) {
+ InvokeCallbackAndCleanup(std::move(get_assertion_response_callback_),
+ status);
+ }
+}
- FailWithErrorAndCleanup();
+void AuthenticatorCommon::OnCancelFromUI() {
+ CancelWithStatus(error_awaiting_user_acknowledgement_);
}
void AuthenticatorCommon::InvokeCallbackAndCleanup(
@@ -1363,8 +1456,7 @@ CreateTouchIdAuthenticatorIfAvailable(
return nullptr;
}
return device::fido::mac::TouchIdAuthenticator::CreateIfAvailable(
- std::move(opt_authenticator_config->keychain_access_group),
- std::move(opt_authenticator_config->metadata_secret));
+ std::move(*opt_authenticator_config));
}
} // namespace
#endif
diff --git a/chromium/content/browser/webauth/authenticator_common.h b/chromium/content/browser/webauth/authenticator_common.h
index ac7534c8b9b..9bd5a10bd9a 100644
--- a/chromium/content/browser/webauth/authenticator_common.h
+++ b/chromium/content/browser/webauth/authenticator_common.h
@@ -33,7 +33,7 @@ class OneShotTimer;
namespace device {
struct PlatformAuthenticatorInfo;
-class CtapGetAssertionRequest;
+struct CtapGetAssertionRequest;
class FidoRequestHandlerBase;
enum class FidoReturnCode : uint8_t;
@@ -83,6 +83,7 @@ class CONTENT_EXPORT AuthenticatorCommon {
void IsUserVerifyingPlatformAuthenticatorAvailable(
blink::mojom::Authenticator::
IsUserVerifyingPlatformAuthenticatorAvailableCallback callback);
+ void Cancel();
// Synchronous implementation of
// IsUserVerifyingPlatformAuthenticatorAvailable.
@@ -149,12 +150,12 @@ class CONTENT_EXPORT AuthenticatorCommon {
response_data,
base::Optional<device::FidoTransportProtocol> transport_used);
- void FailWithErrorAndCleanup();
-
// Runs when timer expires and cancels all issued requests to a U2fDevice.
void OnTimeout();
+ // Cancels the currently pending request (if any) with the supplied status.
+ void CancelWithStatus(blink::mojom::AuthenticatorStatus status);
// Runs when the user cancels WebAuthN request via UI dialog.
- void Cancel();
+ void OnCancelFromUI();
// Called when a GetAssertion has completed, either because an allow_list was
// used and so an answer is returned directly, or because the user selected an
diff --git a/chromium/content/browser/webauth/authenticator_environment_impl.cc b/chromium/content/browser/webauth/authenticator_environment_impl.cc
new file mode 100644
index 00000000000..6bb72968722
--- /dev/null
+++ b/chromium/content/browser/webauth/authenticator_environment_impl.cc
@@ -0,0 +1,99 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/webauth/authenticator_environment_impl.h"
+
+#include <utility>
+
+#include "base/command_line.h"
+#include "base/stl_util.h"
+#include "content/browser/webauth/virtual_discovery.h"
+#include "content/browser/webauth/virtual_fido_discovery_factory.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/common/content_switches.h"
+#include "device/fido/fido_discovery_factory.h"
+
+namespace content {
+
+// static
+AuthenticatorEnvironment* AuthenticatorEnvironment::GetInstance() {
+ return AuthenticatorEnvironmentImpl::GetInstance();
+}
+
+// static
+AuthenticatorEnvironmentImpl* AuthenticatorEnvironmentImpl::GetInstance() {
+ static base::NoDestructor<AuthenticatorEnvironmentImpl> environment;
+ return environment.get();
+}
+
+AuthenticatorEnvironmentImpl::AuthenticatorEnvironmentImpl() {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableWebAuthTestingAPI)) {
+ discovery_factory_ = std::make_unique<VirtualFidoDiscoveryFactory>();
+ } else {
+ discovery_factory_ = std::make_unique<device::FidoDiscoveryFactory>();
+ }
+}
+
+AuthenticatorEnvironmentImpl::~AuthenticatorEnvironmentImpl() = default;
+
+device::FidoDiscoveryFactory* AuthenticatorEnvironmentImpl::GetFactory(
+ RenderFrameHost* host) {
+ auto* factory = GetVirtualFactoryFor(host);
+ if (factory)
+ return factory;
+ return discovery_factory_.get();
+}
+
+device::FidoDiscoveryFactory* AuthenticatorEnvironmentImpl::GetFactory() {
+ return discovery_factory_.get();
+}
+
+void AuthenticatorEnvironmentImpl::EnableVirtualAuthenticatorFor(
+ RenderFrameHost* host) {
+ // Do not create a new virtual authenticator if there is one already defined
+ // for the |host|.
+ if (base::ContainsKey(virtual_discovery_factories_, host))
+ return;
+ virtual_discovery_factories_[host] =
+ std::make_unique<VirtualFidoDiscoveryFactory>();
+}
+
+void AuthenticatorEnvironmentImpl::DisableVirtualAuthenticatorFor(
+ RenderFrameHost* host) {
+ if (base::ContainsKey(virtual_discovery_factories_, host))
+ virtual_discovery_factories_.erase(host);
+}
+
+void AuthenticatorEnvironmentImpl::AddVirtualAuthenticatorBinding(
+ RenderFrameHost* host,
+ blink::test::mojom::VirtualAuthenticatorManagerRequest request) {
+ auto* factory = GetVirtualFactoryFor(host);
+ DCHECK(factory);
+ factory->AddBinding(std::move(request));
+}
+
+void AuthenticatorEnvironmentImpl::ReplaceDefaultDiscoveryFactoryForTesting(
+ std::unique_ptr<device::FidoDiscoveryFactory> factory) {
+ discovery_factory_ = std::move(factory);
+}
+
+void AuthenticatorEnvironmentImpl::OnDiscoveryDestroyed(
+ VirtualFidoDiscovery* discovery) {
+ for (auto& it : virtual_discovery_factories_) {
+ it.second->OnDiscoveryDestroyed(discovery);
+ }
+}
+
+VirtualFidoDiscoveryFactory* AuthenticatorEnvironmentImpl::GetVirtualFactoryFor(
+ RenderFrameHost* host) {
+ do {
+ if (base::ContainsKey(virtual_discovery_factories_, host)) {
+ return virtual_discovery_factories_[host].get();
+ }
+ } while ((host = host->GetParent()));
+ return nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/webauth/authenticator_environment_impl.h b/chromium/content/browser/webauth/authenticator_environment_impl.h
new file mode 100644
index 00000000000..9615929b460
--- /dev/null
+++ b/chromium/content/browser/webauth/authenticator_environment_impl.h
@@ -0,0 +1,87 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_ENVIRONMENT_IMPL_H_
+#define CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_ENVIRONMENT_IMPL_H_
+
+#include <map>
+#include <memory>
+
+#include "base/macros.h"
+#include "base/no_destructor.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/authenticator_environment.h"
+#include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.h"
+
+namespace device {
+class FidoDiscoveryFactory;
+}
+
+namespace content {
+
+class RenderFrameHost;
+class VirtualFidoDiscovery;
+class VirtualFidoDiscoveryFactory;
+
+// Allows enabling and disabling per-frame virtual environments for the Web
+// Authentication API. Disabling the environment resets its state.
+//
+// This class is a singleton.
+class CONTENT_EXPORT AuthenticatorEnvironmentImpl
+ : public AuthenticatorEnvironment {
+ public:
+ static AuthenticatorEnvironmentImpl* GetInstance();
+
+ // Returns a FidoDiscoveryFactory for the given frame host.
+ device::FidoDiscoveryFactory* GetFactory(RenderFrameHost* host);
+
+ // Returns the default FidoDiscoveryFactory.
+ device::FidoDiscoveryFactory* GetFactory();
+
+ // Enables the scoped virtual authenticator environment for the frame host and
+ // its descendants.
+ // Does not have any effect if the |host| already has the virtual environment
+ // enabled.
+ void EnableVirtualAuthenticatorFor(RenderFrameHost* host);
+
+ // Disables the scoped virtual authenticator environment for this |host|,
+ // resetting the state. If the environment is set on one of the |host|'s
+ // parents instead, this won't have any effect.
+ void DisableVirtualAuthenticatorFor(RenderFrameHost* host);
+
+ // Binds the request to the virtual authenticator enabled for the frame host.
+ // The virtual authenticator must be enabled beforehand.
+ void AddVirtualAuthenticatorBinding(
+ RenderFrameHost* host,
+ blink::test::mojom::VirtualAuthenticatorManagerRequest request);
+
+ // Called by VirtualFidoDiscoveries when they are destructed.
+ void OnDiscoveryDestroyed(VirtualFidoDiscovery* discovery);
+
+ // AuthenticatorEnvironment:
+ void ReplaceDefaultDiscoveryFactoryForTesting(
+ std::unique_ptr<device::FidoDiscoveryFactory> factory) override;
+
+ protected:
+ AuthenticatorEnvironmentImpl();
+ ~AuthenticatorEnvironmentImpl() override;
+
+ private:
+ friend class base::NoDestructor<AuthenticatorEnvironmentImpl>;
+
+ // Returns the virtual fido discovery factory for the host if the virtual
+ // environment is enabled for it, otherwise returns nullptr.
+ VirtualFidoDiscoveryFactory* GetVirtualFactoryFor(RenderFrameHost* host);
+
+ std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory_;
+
+ std::map<RenderFrameHost*, std::unique_ptr<VirtualFidoDiscoveryFactory>>
+ virtual_discovery_factories_;
+
+ DISALLOW_COPY_AND_ASSIGN(AuthenticatorEnvironmentImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_ENVIRONMENT_IMPL_H_
diff --git a/chromium/content/browser/webauth/authenticator_impl.cc b/chromium/content/browser/webauth/authenticator_impl.cc
index 3b1488dd28d..fa58ff2857b 100644
--- a/chromium/content/browser/webauth/authenticator_impl.cc
+++ b/chromium/content/browser/webauth/authenticator_impl.cc
@@ -77,6 +77,10 @@ void AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailable(
std::move(callback));
}
+void AuthenticatorImpl::Cancel() {
+ authenticator_common_->Cancel();
+}
+
void AuthenticatorImpl::DidFinishNavigation(
NavigationHandle* navigation_handle) {
// If the RenderFrameHost itself is navigated then this function will cause
diff --git a/chromium/content/browser/webauth/authenticator_impl.h b/chromium/content/browser/webauth/authenticator_impl.h
index 8b004ed2c56..1f1a0afe243 100644
--- a/chromium/content/browser/webauth/authenticator_impl.h
+++ b/chromium/content/browser/webauth/authenticator_impl.h
@@ -24,7 +24,7 @@ class OneShotTimer;
namespace device {
struct PlatformAuthenticatorInfo;
-class CtapGetAssertionRequest;
+struct CtapGetAssertionRequest;
class FidoRequestHandlerBase;
enum class FidoReturnCode : uint8_t;
@@ -79,6 +79,7 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator,
GetAssertionCallback callback) override;
void IsUserVerifyingPlatformAuthenticatorAvailable(
IsUserVerifyingPlatformAuthenticatorAvailableCallback callback) override;
+ void Cancel() override;
// WebContentsObserver:
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
diff --git a/chromium/content/browser/webauth/authenticator_impl_unittest.cc b/chromium/content/browser/webauth/authenticator_impl_unittest.cc
index 02405c6c0e2..73e3f2b29ca 100644
--- a/chromium/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/chromium/content/browser/webauth/authenticator_impl_unittest.cc
@@ -27,9 +27,11 @@
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
+#include "components/autofill/content/browser/webauthn/internal_authenticator_impl.h"
#include "components/cbor/reader.h"
#include "components/cbor/values.h"
#include "content/browser/webauth/authenticator_common.h"
+#include "content/browser/webauth/authenticator_environment_impl.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"
@@ -45,10 +47,11 @@
#include "device/fido/features.h"
#include "device/fido/fido_authenticator.h"
#include "device/fido/fido_constants.h"
+#include "device/fido/fido_test_data.h"
#include "device/fido/hid/fake_hid_impl_for_testing.h"
#include "device/fido/mock_fido_device.h"
-#include "device/fido/scoped_virtual_fido_device.h"
#include "device/fido/test_callback_receiver.h"
+#include "device/fido/virtual_fido_device_factory.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -56,6 +59,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_MACOSX)
+#include "device/fido/mac/authenticator_config.h"
#include "device/fido/mac/scoped_touch_id_test_environment.h"
#endif
@@ -76,6 +80,7 @@ using blink::mojom::AuthenticatorTransport;
using blink::mojom::CableAuthentication;
using blink::mojom::CableAuthenticationPtr;
using blink::mojom::GetAssertionAuthenticatorResponsePtr;
+using blink::mojom::InternalAuthenticatorPtr;
using blink::mojom::MakeCredentialAuthenticatorResponsePtr;
using blink::mojom::PublicKeyCredentialCreationOptions;
using blink::mojom::PublicKeyCredentialCreationOptionsPtr;
@@ -340,9 +345,26 @@ std::vector<CableAuthenticationPtr> GetTestCableExtension() {
} // namespace
-class AuthenticatorImplTest : public content::RenderViewHostTestHarness {
+class AuthenticatorTestBase : public content::RenderViewHostTestHarness {
+ public:
+ AuthenticatorTestBase() { ResetVirtualDevice(); }
+ ~AuthenticatorTestBase() override {}
+
+ void ResetVirtualDevice() {
+ auto virtual_device_factory =
+ std::make_unique<device::test::VirtualFidoDeviceFactory>();
+ virtual_device_factory_ = virtual_device_factory.get();
+ AuthenticatorEnvironmentImpl::GetInstance()
+ ->ReplaceDefaultDiscoveryFactoryForTesting(
+ std::move(virtual_device_factory));
+ }
+
+ protected:
+ device::test::VirtualFidoDeviceFactory* virtual_device_factory_;
+};
+
+class AuthenticatorImplTest : public AuthenticatorTestBase {
public:
- AuthenticatorImplTest() {}
~AuthenticatorImplTest() override {}
protected:
@@ -501,7 +523,6 @@ TEST_F(AuthenticatorImplTest, MakeCredentialOriginAndRpIds) {
std::string(test_case.origin));
NavigateAndCommit(GURL(test_case.origin));
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
@@ -527,7 +548,6 @@ TEST_F(AuthenticatorImplTest, MakeCredentialOriginAndRpIds) {
// parameters contain a supported algorithm.
TEST_F(AuthenticatorImplTest, MakeCredentialNoSupportedAlgorithm) {
SimulateNavigation(GURL(kTestOrigin1));
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
@@ -550,7 +570,6 @@ TEST_F(AuthenticatorImplTest, MakeCredentialNoSupportedAlgorithm) {
// verification is required for U2F devices.
TEST_F(AuthenticatorImplTest, MakeCredentialUserVerification) {
SimulateNavigation(GURL(kTestOrigin1));
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
@@ -574,7 +593,6 @@ TEST_F(AuthenticatorImplTest, MakeCredentialUserVerification) {
// key is requested on create().
TEST_F(AuthenticatorImplTest, MakeCredentialResidentKey) {
SimulateNavigation(GURL(kTestOrigin1));
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
@@ -660,6 +678,11 @@ TEST_F(AuthenticatorImplTest, TestSerializedSignClientData) {
}
TEST_F(AuthenticatorImplTest, TestMakeCredentialTimeout) {
+ // The VirtualFidoAuthenticator simulates a tap immediately after it gets the
+ // request. Replace by the real discovery that will wait until timeout.
+ AuthenticatorEnvironmentImpl::GetInstance()
+ ->ReplaceDefaultDiscoveryFactoryForTesting(
+ std::make_unique<device::FidoDiscoveryFactory>());
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
@@ -719,13 +742,12 @@ constexpr OriginClaimedAuthorityPair kValidAppIdCases[] = {
// Verify behavior for various combinations of origins and RP IDs.
TEST_F(AuthenticatorImplTest, AppIdExtensionValues) {
TestServiceManagerContext smc;
- device::test::ScopedVirtualFidoDevice virtual_device;
for (const auto& test_case : kValidAppIdCases) {
SCOPED_TRACE(std::string(test_case.origin) + " " +
std::string(test_case.claimed_authority));
- EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
TryAuthenticationWithAppId(test_case.origin,
test_case.claimed_authority));
}
@@ -762,9 +784,8 @@ TEST_F(AuthenticatorImplTest, CryptotokenBypass) {
GetTestPublicKeyCredentialRequestOptions();
options->relying_party_id = std::string(kTestOrigin1);
- device::test::ScopedVirtualFidoDevice virtual_device;
// Inject a registration for the URL (which is a U2F AppID).
- ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->allow_credentials[0]->id, kTestOrigin1));
options->appid = kTestOrigin1;
@@ -780,6 +801,7 @@ TEST_F(AuthenticatorImplTest, CryptotokenBypass) {
}
{
+ ResetVirtualDevice();
OverrideLastCommittedOrigin(
main_rfh(), url::Origin::Create(GURL(kTestExtensionOrigin)));
// Next, verify that other extensions cannot bypass the origin checks.
@@ -787,9 +809,8 @@ TEST_F(AuthenticatorImplTest, CryptotokenBypass) {
GetTestPublicKeyCredentialRequestOptions();
options->relying_party_id = std::string(kTestOrigin1);
- device::test::ScopedVirtualFidoDevice virtual_device;
// Inject a registration for the URL (which is a U2F AppID).
- ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->allow_credentials[0]->id, kTestOrigin1));
options->appid = kTestOrigin1;
@@ -811,17 +832,16 @@ TEST_F(AuthenticatorImplTest, CryptoTokenU2fOnly) {
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST);
- // TODO(martinkr): ScopedVirtualFidoDevice does not offer devices that
+ // TODO(martinkr): VirtualFidoDeviceFactory does not offer devices that
// support both U2F and CTAP yet; we should test those.
for (const bool u2f_authenticator : {true, false}) {
SCOPED_TRACE(u2f_authenticator ? "U2F" : "CTAP");
OverrideLastCommittedOrigin(main_rfh(),
url::Origin::Create(GURL(kCryptotokenOrigin)));
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
- scoped_virtual_device.SetSupportedProtocol(
+ virtual_device_factory_->SetSupportedProtocol(
u2f_authenticator ? device::ProtocolVersion::kU2f
- : device::ProtocolVersion::kCtap);
+ : device::ProtocolVersion::kCtap2);
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
@@ -853,7 +873,7 @@ TEST_F(AuthenticatorImplTest, CryptotokenUsbOnly) {
for (const bool is_cryptotoken_request : {false, true}) {
// caBLE and platform discoveries cannot be instantiated through
- // ScopedVirtualFidoDevice, so we don't test them here.
+ // VirtualFidoDeviceFactory, so we don't test them here.
for (const device::FidoTransportProtocol transport :
{device::FidoTransportProtocol::kUsbHumanInterfaceDevice,
device::FidoTransportProtocol::kBluetoothLowEnergy,
@@ -867,10 +887,11 @@ TEST_F(AuthenticatorImplTest, CryptotokenUsbOnly) {
url::Origin::Create(GURL(is_cryptotoken_request ? kCryptotokenOrigin
: kTestOrigin1)));
- device::test::ScopedVirtualFidoDevice device;
- device.SetSupportedProtocol(device::ProtocolVersion::kU2f);
- device.SetTransport(transport);
- device.mutable_state()->transport = transport;
+ ResetVirtualDevice();
+ virtual_device_factory_->SetSupportedProtocol(
+ device::ProtocolVersion::kU2f);
+ virtual_device_factory_->SetTransport(transport);
+ virtual_device_factory_->mutable_state()->transport = transport;
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
@@ -900,17 +921,16 @@ TEST_F(AuthenticatorImplTest, AttestationPermitted) {
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST);
- // TODO(martinkr): ScopedVirtualFidoDevice does not offer devices that
+ // TODO(martinkr): VirtualFidoDeviceFactory does not offer devices that
// support both U2F and CTAP yet; we should test those.
for (const bool u2f_authenticator : {true, false}) {
SCOPED_TRACE(u2f_authenticator ? "U2F" : "CTAP");
OverrideLastCommittedOrigin(main_rfh(),
url::Origin::Create(GURL(kCryptotokenOrigin)));
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
- scoped_virtual_device.SetSupportedProtocol(
+ virtual_device_factory_->SetSupportedProtocol(
u2f_authenticator ? device::ProtocolVersion::kU2f
- : device::ProtocolVersion::kCtap);
+ : device::ProtocolVersion::kCtap2);
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
@@ -940,8 +960,7 @@ TEST_F(AuthenticatorImplTest, AppIdExtension) {
// requested.
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
- device::test::ScopedVirtualFidoDevice virtual_device;
- ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->allow_credentials[0]->id, kTestRelyingPartyId));
TestGetAssertionCallback callback_receiver;
@@ -956,10 +975,10 @@ TEST_F(AuthenticatorImplTest, AppIdExtension) {
{
// Second, test that the appid extension is echoed, but is false, when appid
// is requested but not used.
+ ResetVirtualDevice();
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
- device::test::ScopedVirtualFidoDevice virtual_device;
- ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->allow_credentials[0]->id, kTestRelyingPartyId));
// This AppID won't be used because the RP ID will be tried (successfully)
@@ -978,11 +997,40 @@ TEST_F(AuthenticatorImplTest, AppIdExtension) {
{
// Lastly, when used, the appid extension result should be "true".
+ ResetVirtualDevice();
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
- device::test::ScopedVirtualFidoDevice virtual_device;
// Inject a registration for the URL (which is a U2F AppID).
- ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
+ options->allow_credentials[0]->id, kTestOrigin1));
+
+ options->appid = kTestOrigin1;
+
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ ASSERT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
+
+ EXPECT_EQ(true, callback_receiver.value()->echo_appid_extension);
+ EXPECT_EQ(true, callback_receiver.value()->appid_extension);
+ }
+
+ {
+ // AppID should still work when the authenticator supports credProtect.
+ ResetVirtualDevice();
+ device::VirtualCtap2Device::Config config;
+ config.u2f_support = true;
+ config.pin_support = true;
+ config.resident_key_support = true;
+ config.cred_protect_support = true;
+
+ virtual_device_factory_->SetCtap2Config(config);
+
+ // Inject a registration for the URL (which is a U2F AppID).
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->allow_credentials[0]->id, kTestOrigin1));
options->appid = kTestOrigin1;
@@ -999,6 +1047,11 @@ TEST_F(AuthenticatorImplTest, AppIdExtension) {
}
TEST_F(AuthenticatorImplTest, TestGetAssertionTimeout) {
+ // The VirtualFidoAuthenticator simulates a tap immediately after it gets the
+ // request. Replace by the real discovery that will wait until timeout.
+ AuthenticatorEnvironmentImpl::GetInstance()
+ ->ReplaceDefaultDiscoveryFactoryForTesting(
+ std::make_unique<device::FidoDiscoveryFactory>());
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
@@ -1017,7 +1070,6 @@ TEST_F(AuthenticatorImplTest, TestGetAssertionTimeout) {
}
TEST_F(AuthenticatorImplTest, OversizedCredentialId) {
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
TestServiceManagerContext service_manager_context;
// 255 is the maximum size of a U2F credential ID. We also test one greater
@@ -1038,7 +1090,7 @@ TEST_F(AuthenticatorImplTest, OversizedCredentialId) {
const bool should_be_valid = size < 256;
if (should_be_valid) {
- ASSERT_TRUE(scoped_virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
credential->id, kTestRelyingPartyId));
}
@@ -1052,7 +1104,7 @@ TEST_F(AuthenticatorImplTest, OversizedCredentialId) {
if (should_be_valid) {
EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
} else {
- EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
callback_receiver.status());
}
}
@@ -1102,10 +1154,10 @@ TEST_F(AuthenticatorImplTest, NoSilentAuthenticationForCable) {
SimulateNavigation(GURL(kTestOrigin1));
for (bool is_cable_device : {false, true}) {
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ ResetVirtualDevice();
device::VirtualCtap2Device::Config config;
config.reject_silent_authentication_requests = true;
- scoped_virtual_device.SetCtap2Config(config);
+ virtual_device_factory_->SetCtap2Config(config);
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
@@ -1113,7 +1165,7 @@ TEST_F(AuthenticatorImplTest, NoSilentAuthenticationForCable) {
options->cable_authentication_data = GetTestCableExtension();
if (is_cable_device) {
- scoped_virtual_device.SetTransport(
+ virtual_device_factory_->SetTransport(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
for (auto& cred : options->allow_credentials) {
cred->transports.clear();
@@ -1121,7 +1173,7 @@ TEST_F(AuthenticatorImplTest, NoSilentAuthenticationForCable) {
}
}
- ASSERT_TRUE(scoped_virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->allow_credentials[0]->id, kTestRelyingPartyId));
TestGetAssertionCallback callback_receiver;
@@ -1137,7 +1189,7 @@ TEST_F(AuthenticatorImplTest, NoSilentAuthenticationForCable) {
// The virtual device will return an error because
// |reject_silent_authentication_requests| is true and then it'll
// immediately resolve the touch request.
- EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
callback_receiver.status());
}
}
@@ -1151,10 +1203,9 @@ TEST_F(AuthenticatorImplTest, TestGetAssertionU2fDeviceBackwardsCompatibility) {
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
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(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->allow_credentials[0]->id, kTestRelyingPartyId));
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
@@ -1174,7 +1225,6 @@ TEST_F(AuthenticatorImplTest, GetAssertionWithEmptyAllowCredentials) {
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
- device::test::ScopedVirtualFidoDevice virtual_device;
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
// Trigger timer.
@@ -1186,7 +1236,6 @@ TEST_F(AuthenticatorImplTest, GetAssertionWithEmptyAllowCredentials) {
}
TEST_F(AuthenticatorImplTest, MakeCredentialAlreadyRegistered) {
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
TestServiceManagerContext service_manager_context;
SimulateNavigation(GURL(kTestOrigin1));
@@ -1196,7 +1245,7 @@ TEST_F(AuthenticatorImplTest, MakeCredentialAlreadyRegistered) {
// Exclude the one already registered credential.
options->exclude_credentials = GetTestCredentials();
- ASSERT_TRUE(scoped_virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->exclude_credentials[0]->id, kTestRelyingPartyId));
TestMakeCredentialCallback callback_receiver;
@@ -1209,7 +1258,6 @@ TEST_F(AuthenticatorImplTest, MakeCredentialAlreadyRegistered) {
}
TEST_F(AuthenticatorImplTest, MakeCredentialPendingRequest) {
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
TestServiceManagerContext service_manager_context;
SimulateNavigation(GURL(kTestOrigin1));
@@ -1238,7 +1286,6 @@ TEST_F(AuthenticatorImplTest, MakeCredentialPendingRequest) {
}
TEST_F(AuthenticatorImplTest, GetAssertionPendingRequest) {
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
TestServiceManagerContext service_manager_context;
SimulateNavigation(GURL(kTestOrigin1));
@@ -1266,7 +1313,6 @@ TEST_F(AuthenticatorImplTest, GetAssertionPendingRequest) {
}
TEST_F(AuthenticatorImplTest, NavigationDuringOperation) {
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
TestServiceManagerContext service_manager_context;
SimulateNavigation(GURL(kTestOrigin1));
@@ -1283,7 +1329,7 @@ TEST_F(AuthenticatorImplTest, NavigationDuringOperation) {
// 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 =
+ virtual_device_factory_->mutable_state()->simulate_press_callback =
base::BindRepeating(
[](std::unique_ptr<AuthenticatorImpl>* ptr) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -1299,10 +1345,9 @@ TEST_F(AuthenticatorImplTest, NavigationDuringOperation) {
}
TEST_F(AuthenticatorImplTest, InvalidResponse) {
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
TestServiceManagerContext service_manager_context;
- scoped_virtual_device.mutable_state()->simulate_invalid_response = true;
+ virtual_device_factory_->mutable_state()->simulate_invalid_response = true;
SimulateNavigation(GURL(kTestOrigin1));
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
@@ -1347,14 +1392,13 @@ TEST_F(AuthenticatorImplTest, Ctap2AssertionWithUnknownCredential) {
<< "return_immediate_invalid_credential_error="
<< return_immediate_invalid_credential_error);
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
device::VirtualCtap2Device::Config config;
config.return_immediate_invalid_credential_error =
return_immediate_invalid_credential_error;
- scoped_virtual_device.SetCtap2Config(config);
+ virtual_device_factory_->SetCtap2Config(config);
bool pressed = false;
- scoped_virtual_device.mutable_state()->simulate_press_callback =
+ virtual_device_factory_->mutable_state()->simulate_press_callback =
base::BindRepeating([](bool* flag) { *flag = true; }, &pressed);
TestGetAssertionCallback callback_receiver;
@@ -1362,7 +1406,7 @@ TEST_F(AuthenticatorImplTest, Ctap2AssertionWithUnknownCredential) {
authenticator->GetAssertion(GetTestPublicKeyCredentialRequestOptions(),
callback_receiver.callback());
callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
callback_receiver.status());
// The user must have pressed the authenticator for the operation to
// resolve.
@@ -1373,13 +1417,12 @@ TEST_F(AuthenticatorImplTest, Ctap2AssertionWithUnknownCredential) {
TEST_F(AuthenticatorImplTest, GetAssertionResponseWithAttestedCredentialData) {
TestServiceManagerContext service_manager_context;
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
device::VirtualCtap2Device::Config config;
config.return_attested_cred_data_in_get_assertion_response = true;
- scoped_virtual_device.SetCtap2Config(config);
+ virtual_device_factory_->SetCtap2Config(config);
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
- ASSERT_TRUE(scoped_virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->allow_credentials[0]->id, kTestRelyingPartyId));
SimulateNavigation(GURL(kTestOrigin1));
@@ -1481,14 +1524,6 @@ class TestAuthenticatorContentBrowserClient : public ContentBrowserClient {
individual_attestation, attestation_consent, is_focused);
}
-#if defined(OS_MACOSX)
- bool IsWebAuthenticationTouchIdAuthenticatorSupported() override {
- return supports_touch_id;
- }
-
- bool supports_touch_id = true;
-#endif
-
// If set, this closure will be called when the subsequently constructed
// delegate is informed that the request has started.
base::OnceClosure action_callbacks_registered_callback;
@@ -1648,7 +1683,6 @@ class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
protected:
TestAuthenticatorContentBrowserClient test_client_;
- device::test::ScopedVirtualFidoDevice virtual_device_;
private:
static const char* AttestationConveyancePreferenceToString(
@@ -1828,10 +1862,10 @@ TEST_F(AuthenticatorContentBrowserClientTest, AttestationBehaviour) {
},
};
- virtual_device_.mutable_state()->attestation_cert_common_name =
+ virtual_device_factory_->mutable_state()->attestation_cert_common_name =
kStandardCommonName;
- virtual_device_.mutable_state()->individual_attestation_cert_common_name =
- kIndividualCommonName;
+ virtual_device_factory_->mutable_state()
+ ->individual_attestation_cert_common_name = kIndividualCommonName;
NavigateAndCommit(GURL("https://example.com"));
RunTestCases(kTests);
@@ -1885,9 +1919,10 @@ TEST_F(AuthenticatorContentBrowserClientTest,
},
};
- virtual_device_.mutable_state()->attestation_cert_common_name = kCommonName;
- virtual_device_.mutable_state()->individual_attestation_cert_common_name =
+ virtual_device_factory_->mutable_state()->attestation_cert_common_name =
kCommonName;
+ virtual_device_factory_->mutable_state()
+ ->individual_attestation_cert_common_name = kCommonName;
NavigateAndCommit(GURL("https://example.com"));
RunTestCases(kTests);
@@ -1898,11 +1933,13 @@ TEST_F(AuthenticatorContentBrowserClientTest,
// behavior of the Touch ID platform authenticator.
TEST_F(AuthenticatorContentBrowserClientTest,
PlatformAuthenticatorAttestation) {
- virtual_device_.SetSupportedProtocol(device::ProtocolVersion::kCtap);
- virtual_device_.mutable_state()->transport =
+ virtual_device_factory_->SetSupportedProtocol(
+ device::ProtocolVersion::kCtap2);
+ virtual_device_factory_->mutable_state()->transport =
device::FidoTransportProtocol::kInternal;
- virtual_device_.mutable_state()->self_attestation = true;
- virtual_device_.mutable_state()->non_zero_aaguid_with_self_attestation = true;
+ virtual_device_factory_->mutable_state()->self_attestation = true;
+ virtual_device_factory_->mutable_state()
+ ->non_zero_aaguid_with_self_attestation = true;
NavigateAndCommit(GURL("https://example.com"));
const std::vector<TestCase> kTests = {
@@ -1945,8 +1982,9 @@ TEST_F(AuthenticatorContentBrowserClientTest,
}
TEST_F(AuthenticatorContentBrowserClientTest, Ctap2SelfAttestation) {
- virtual_device_.SetSupportedProtocol(device::ProtocolVersion::kCtap);
- virtual_device_.mutable_state()->self_attestation = true;
+ virtual_device_factory_->SetSupportedProtocol(
+ device::ProtocolVersion::kCtap2);
+ virtual_device_factory_->mutable_state()->self_attestation = true;
NavigateAndCommit(GURL("https://example.com"));
const std::vector<TestCase> kTests = {
@@ -1987,9 +2025,11 @@ TEST_F(AuthenticatorContentBrowserClientTest, Ctap2SelfAttestation) {
TEST_F(AuthenticatorContentBrowserClientTest,
Ctap2SelfAttestationNonZeroAaguid) {
- virtual_device_.SetSupportedProtocol(device::ProtocolVersion::kCtap);
- virtual_device_.mutable_state()->self_attestation = true;
- virtual_device_.mutable_state()->non_zero_aaguid_with_self_attestation = true;
+ virtual_device_factory_->SetSupportedProtocol(
+ device::ProtocolVersion::kCtap2);
+ virtual_device_factory_->mutable_state()->self_attestation = true;
+ virtual_device_factory_->mutable_state()
+ ->non_zero_aaguid_with_self_attestation = true;
NavigateAndCommit(GURL("https://example.com"));
const std::vector<TestCase> kTests = {
@@ -2078,7 +2118,7 @@ TEST_F(AuthenticatorContentBrowserClientTest, Unfocused) {
credential->id.resize(16);
credential->transports = {AuthenticatorTransport::USB};
- ASSERT_TRUE(virtual_device_.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
credential->id, kTestRelyingPartyId));
options->allow_credentials.emplace_back(std::move(credential));
@@ -2123,42 +2163,6 @@ TEST_F(AuthenticatorContentBrowserClientTest,
}
}
-#if defined(OS_MACOSX)
-TEST_F(AuthenticatorContentBrowserClientTest,
- IsUVPAAFalseIfEmbedderDoesNotSupportTouchId) {
- if (__builtin_available(macOS 10.12.2, *)) {
- // Touch ID is hardware-supported, but not enabled by the embedder.
- device::fido::mac::ScopedTouchIdTestEnvironment touch_id_test_environment;
- touch_id_test_environment.SetTouchIdAvailable(true);
- test_client_.supports_touch_id = false;
-
- NavigateAndCommit(GURL(kTestOrigin1));
- AuthenticatorPtr authenticator = ConnectToAuthenticator();
-
- TestIsUvpaaCallback cb;
- authenticator->IsUserVerifyingPlatformAuthenticatorAvailable(cb.callback());
- cb.WaitForCallback();
- EXPECT_FALSE(cb.value());
- }
-}
-
-TEST_F(AuthenticatorContentBrowserClientTest, IsUVPAATrueIfTouchIdAvailable) {
- if (__builtin_available(macOS 10.12.2, *)) {
- device::fido::mac::ScopedTouchIdTestEnvironment touch_id_test_environment;
- touch_id_test_environment.SetTouchIdAvailable(true);
- test_client_.supports_touch_id = true;
-
- NavigateAndCommit(GURL(kTestOrigin1));
- AuthenticatorPtr authenticator = ConnectToAuthenticator();
-
- TestIsUvpaaCallback cb;
- authenticator->IsUserVerifyingPlatformAuthenticatorAvailable(cb.callback());
- cb.WaitForCallback();
- EXPECT_TRUE(cb.value());
- }
-}
-#endif // defined(OS_MACOSX)
-
#if defined(OS_WIN)
TEST_F(AuthenticatorContentBrowserClientTest, WinIsUVPAA) {
for (const bool enable_win_webauthn_api : {false, true}) {
@@ -2207,7 +2211,7 @@ TEST_F(AuthenticatorContentBrowserClientTest,
OverrideLastCommittedOrigin(main_rfh(),
url::Origin::Create(GURL(kCryptotokenOrigin)));
- virtual_device_.SetSupportedProtocol(device::ProtocolVersion::kU2f);
+ virtual_device_factory_->SetSupportedProtocol(device::ProtocolVersion::kU2f);
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
// Despite the direct attestation conveyance preference, the request delegate
@@ -2346,8 +2350,11 @@ TEST_F(AuthenticatorImplRequestDelegateTest,
EXPECT_CALL(*mock_adapter_, IsPresent())
.WillRepeatedly(::testing::Return(true));
- device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
- auto* fake_ble_discovery = discovery_factory.ForgeNextBleDiscovery();
+ auto discovery_factory =
+ std::make_unique<device::test::FakeFidoDiscoveryFactory>();
+ auto* fake_ble_discovery = discovery_factory->ForgeNextBleDiscovery();
+ AuthenticatorEnvironmentImpl::GetInstance()
+ ->ReplaceDefaultDiscoveryFactoryForTesting(std::move(discovery_factory));
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options =
@@ -2393,6 +2400,11 @@ TEST_F(AuthenticatorImplRequestDelegateTest,
}
TEST_F(AuthenticatorImplRequestDelegateTest, FailureReasonForTimeout) {
+ // The VirtualFidoAuthenticator simulates a tap immediately after it gets the
+ // request. Replace by the real discovery that will wait until timeout.
+ AuthenticatorEnvironmentImpl::GetInstance()
+ ->ReplaceDefaultDiscoveryFactoryForTesting(
+ std::make_unique<device::FidoDiscoveryFactory>());
SimulateNavigation(GURL(kTestOrigin1));
FailureReasonCallbackReceiver failure_reason_receiver;
@@ -2422,7 +2434,6 @@ TEST_F(AuthenticatorImplRequestDelegateTest, FailureReasonForTimeout) {
TEST_F(AuthenticatorImplRequestDelegateTest,
FailureReasonForDuplicateRegistration) {
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
SimulateNavigation(GURL(kTestOrigin1));
FailureReasonCallbackReceiver failure_reason_receiver;
@@ -2437,7 +2448,7 @@ TEST_F(AuthenticatorImplRequestDelegateTest,
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
options->exclude_credentials = GetTestCredentials();
- ASSERT_TRUE(scoped_virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->exclude_credentials[0]->id, kTestRelyingPartyId));
TestMakeCredentialCallback callback_receiver;
@@ -2456,7 +2467,6 @@ TEST_F(AuthenticatorImplRequestDelegateTest,
TEST_F(AuthenticatorImplRequestDelegateTest,
FailureReasonForMissingRegistration) {
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
SimulateNavigation(GURL(kTestOrigin1));
FailureReasonCallbackReceiver failure_reason_receiver;
@@ -2473,8 +2483,7 @@ TEST_F(AuthenticatorImplRequestDelegateTest,
callback_receiver.callback());
callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
- callback_receiver.status());
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
ASSERT_TRUE(failure_reason_receiver.was_called());
EXPECT_EQ(content::AuthenticatorRequestClientDelegate::
@@ -2487,11 +2496,10 @@ TEST_F(AuthenticatorImplTest, Transports) {
NavigateAndCommit(GURL(kTestOrigin1));
for (auto protocol :
- {device::ProtocolVersion::kU2f, device::ProtocolVersion::kCtap}) {
+ {device::ProtocolVersion::kU2f, device::ProtocolVersion::kCtap2}) {
SCOPED_TRACE(static_cast<int>(protocol));
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
- scoped_virtual_device.SetSupportedProtocol(protocol);
+ virtual_device_factory_->SetSupportedProtocol(protocol);
AuthenticatorPtr authenticator = ConnectToAuthenticator();
PublicKeyCredentialCreationOptionsPtr options =
@@ -2519,8 +2527,8 @@ TEST_F(AuthenticatorImplTest, ExtensionHMACSecret) {
for (const bool include_extension : {false, true}) {
SCOPED_TRACE(include_extension);
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
- scoped_virtual_device.SetSupportedProtocol(device::ProtocolVersion::kCtap);
+ virtual_device_factory_->SetSupportedProtocol(
+ device::ProtocolVersion::kCtap2);
AuthenticatorPtr authenticator = ConnectToAuthenticator();
PublicKeyCredentialCreationOptionsPtr options =
@@ -2576,16 +2584,16 @@ TEST_F(AuthenticatorImplTest, MakeCredentialWithLargeExcludeList) {
SCOPED_TRACE(::testing::Message()
<< "has_excluded_credential=" << has_excluded_credential);
- device::test::ScopedVirtualFidoDevice virtual_device;
+ ResetVirtualDevice();
device::VirtualCtap2Device::Config config;
config.reject_large_allow_and_exclude_lists = true;
- virtual_device.SetCtap2Config(config);
+ virtual_device_factory_->SetCtap2Config(config);
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
options->exclude_credentials = GetTestCredentials(/*num_credentials=*/10);
if (has_excluded_credential) {
- ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->exclude_credentials.back()->id, kTestRelyingPartyId));
}
TestMakeCredentialCallback callback_receiver;
@@ -2609,10 +2617,10 @@ TEST_F(AuthenticatorImplTest, GetAssertionWithLargeAllowList) {
SCOPED_TRACE(::testing::Message()
<< "has_allowed_credential=" << has_allowed_credential);
- device::test::ScopedVirtualFidoDevice virtual_device;
+ ResetVirtualDevice();
device::VirtualCtap2Device::Config config;
config.reject_large_allow_and_exclude_lists = true;
- virtual_device.SetCtap2Config(config);
+ virtual_device_factory_->SetCtap2Config(config);
AuthenticatorPtr authenticator = ConnectToAuthenticator();
@@ -2620,7 +2628,7 @@ TEST_F(AuthenticatorImplTest, GetAssertionWithLargeAllowList) {
GetTestPublicKeyCredentialRequestOptions();
options->allow_credentials = GetTestCredentials(/*num_credentials=*/10);
if (has_allowed_credential) {
- ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->allow_credentials.back()->id, kTestRelyingPartyId));
}
@@ -2630,9 +2638,8 @@ TEST_F(AuthenticatorImplTest, GetAssertionWithLargeAllowList) {
base::RunLoop().RunUntilIdle();
callback_receiver.WaitForCallback();
EXPECT_EQ(callback_receiver.status(),
- has_allowed_credential
- ? AuthenticatorStatus::SUCCESS
- : AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED);
+ has_allowed_credential ? AuthenticatorStatus::SUCCESS
+ : AuthenticatorStatus::NOT_ALLOWED_ERROR);
}
}
@@ -2695,8 +2702,6 @@ class UVAuthenticatorImplTest : public AuthenticatorImplTest {
return auth_data->obtained_user_verification();
}
- device::test::ScopedVirtualFidoDevice virtual_device_;
-
private:
DISALLOW_COPY_AND_ASSIGN(UVAuthenticatorImplTest);
};
@@ -2776,7 +2781,7 @@ class PINAuthenticatorImplTest : public UVAuthenticatorImplTest {
old_client_ = SetBrowserClientForTesting(&test_client_);
device::VirtualCtap2Device::Config config;
config.pin_support = true;
- virtual_device_.SetCtap2Config(config);
+ virtual_device_factory_->SetCtap2Config(config);
NavigateAndCommit(GURL(kTestOrigin1));
}
@@ -2802,29 +2807,29 @@ class PINAuthenticatorImplTest : public UVAuthenticatorImplTest {
case 0:
// No support.
config.pin_support = false;
- virtual_device_.mutable_state()->pin = "";
- virtual_device_.mutable_state()->retries = 0;
+ virtual_device_factory_->mutable_state()->pin = "";
+ virtual_device_factory_->mutable_state()->retries = 0;
break;
case 1:
// PIN supported, but no PIN set.
config.pin_support = true;
- virtual_device_.mutable_state()->pin = "";
- virtual_device_.mutable_state()->retries = 0;
+ virtual_device_factory_->mutable_state()->pin = "";
+ virtual_device_factory_->mutable_state()->retries = 0;
break;
case 2:
// PIN set.
config.pin_support = true;
- virtual_device_.mutable_state()->pin = kTestPIN;
- virtual_device_.mutable_state()->retries = 8;
+ virtual_device_factory_->mutable_state()->pin = kTestPIN;
+ virtual_device_factory_->mutable_state()->retries = 8;
break;
default:
NOTREACHED();
}
- virtual_device_.SetCtap2Config(config);
+ virtual_device_factory_->SetCtap2Config(config);
}
private:
@@ -2928,14 +2933,14 @@ TEST_F(PINAuthenticatorImplTest, MakeCredential) {
case kNoPIN:
EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
- EXPECT_EQ("", virtual_device_.mutable_state()->pin);
+ EXPECT_EQ("", virtual_device_factory_->mutable_state()->pin);
EXPECT_FALSE(HasUV(callback_receiver));
break;
case kSetPIN:
case kUsePIN:
EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
- EXPECT_EQ(kTestPIN, virtual_device_.mutable_state()->pin);
+ EXPECT_EQ(kTestPIN, virtual_device_factory_->mutable_state()->pin);
EXPECT_TRUE(HasUV(callback_receiver));
break;
@@ -2949,8 +2954,8 @@ TEST_F(PINAuthenticatorImplTest, MakeCredential) {
TEST_F(PINAuthenticatorImplTest, MakeCredentialSoftLock) {
TestServiceManagerContext smc;
- virtual_device_.mutable_state()->pin = kTestPIN;
- virtual_device_.mutable_state()->retries = 8;
+ virtual_device_factory_->mutable_state()->pin = kTestPIN;
+ virtual_device_factory_->mutable_state()->retries = 8;
test_client_.expected = {{8, "wrong"}, {7, "wrong"}, {6, "wrong"}};
AuthenticatorPtr authenticator = ConnectToAuthenticator();
@@ -2959,8 +2964,8 @@ TEST_F(PINAuthenticatorImplTest, MakeCredentialSoftLock) {
callback_receiver.callback());
callback_receiver.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
- EXPECT_EQ(5, virtual_device_.mutable_state()->retries);
- EXPECT_TRUE(virtual_device_.mutable_state()->soft_locked);
+ EXPECT_EQ(5, virtual_device_factory_->mutable_state()->retries);
+ EXPECT_TRUE(virtual_device_factory_->mutable_state()->soft_locked);
ASSERT_TRUE(test_client_.failure_reason.has_value());
EXPECT_EQ(InterestingFailureReason::kSoftPINBlock,
*test_client_.failure_reason);
@@ -2968,8 +2973,8 @@ TEST_F(PINAuthenticatorImplTest, MakeCredentialSoftLock) {
TEST_F(PINAuthenticatorImplTest, MakeCredentialHardLock) {
TestServiceManagerContext smc;
- virtual_device_.mutable_state()->pin = kTestPIN;
- virtual_device_.mutable_state()->retries = 1;
+ virtual_device_factory_->mutable_state()->pin = kTestPIN;
+ virtual_device_factory_->mutable_state()->retries = 1;
test_client_.expected = {{1, "wrong"}};
AuthenticatorPtr authenticator = ConnectToAuthenticator();
@@ -2978,7 +2983,7 @@ TEST_F(PINAuthenticatorImplTest, MakeCredentialHardLock) {
callback_receiver.callback());
callback_receiver.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
- EXPECT_EQ(0, virtual_device_.mutable_state()->retries);
+ EXPECT_EQ(0, virtual_device_factory_->mutable_state()->retries);
ASSERT_TRUE(test_client_.failure_reason.has_value());
EXPECT_EQ(InterestingFailureReason::kHardPINBlock,
*test_client_.failure_reason);
@@ -3011,7 +3016,7 @@ TEST_F(PINAuthenticatorImplTest, GetAssertion) {
// clang-format on
PublicKeyCredentialRequestOptionsPtr dummy_options = get_credential_options();
- ASSERT_TRUE(virtual_device_.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
dummy_options->allow_credentials[0]->id, kTestRelyingPartyId));
for (bool ui_support : {false, true}) {
@@ -3051,7 +3056,7 @@ TEST_F(PINAuthenticatorImplTest, GetAssertion) {
switch (expected[support_level][uv_level]) {
case kFailure:
- EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
callback_receiver.status());
break;
@@ -3062,7 +3067,7 @@ TEST_F(PINAuthenticatorImplTest, GetAssertion) {
case kUsePIN:
EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
- EXPECT_EQ(kTestPIN, virtual_device_.mutable_state()->pin);
+ EXPECT_EQ(kTestPIN, virtual_device_factory_->mutable_state()->pin);
EXPECT_TRUE(HasUV(callback_receiver));
break;
@@ -3076,11 +3081,11 @@ TEST_F(PINAuthenticatorImplTest, GetAssertion) {
TEST_F(PINAuthenticatorImplTest, GetAssertionSoftLock) {
TestServiceManagerContext smc;
- virtual_device_.mutable_state()->pin = kTestPIN;
- virtual_device_.mutable_state()->retries = 8;
+ virtual_device_factory_->mutable_state()->pin = kTestPIN;
+ virtual_device_factory_->mutable_state()->retries = 8;
PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
- ASSERT_TRUE(virtual_device_.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->allow_credentials[0]->id, kTestRelyingPartyId));
test_client_.expected = {{8, "wrong"}, {7, "wrong"}, {6, "wrong"}};
@@ -3089,8 +3094,8 @@ TEST_F(PINAuthenticatorImplTest, GetAssertionSoftLock) {
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
callback_receiver.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
- EXPECT_EQ(5, virtual_device_.mutable_state()->retries);
- EXPECT_TRUE(virtual_device_.mutable_state()->soft_locked);
+ EXPECT_EQ(5, virtual_device_factory_->mutable_state()->retries);
+ EXPECT_TRUE(virtual_device_factory_->mutable_state()->soft_locked);
ASSERT_TRUE(test_client_.failure_reason.has_value());
EXPECT_EQ(InterestingFailureReason::kSoftPINBlock,
*test_client_.failure_reason);
@@ -3098,11 +3103,11 @@ TEST_F(PINAuthenticatorImplTest, GetAssertionSoftLock) {
TEST_F(PINAuthenticatorImplTest, GetAssertionHardLock) {
TestServiceManagerContext smc;
- virtual_device_.mutable_state()->pin = kTestPIN;
- virtual_device_.mutable_state()->retries = 1;
+ virtual_device_factory_->mutable_state()->pin = kTestPIN;
+ virtual_device_factory_->mutable_state()->retries = 1;
PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
- ASSERT_TRUE(virtual_device_.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
options->allow_credentials[0]->id, kTestRelyingPartyId));
test_client_.expected = {{1, "wrong"}};
@@ -3111,7 +3116,7 @@ TEST_F(PINAuthenticatorImplTest, GetAssertionHardLock) {
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
callback_receiver.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
- EXPECT_EQ(0, virtual_device_.mutable_state()->retries);
+ EXPECT_EQ(0, virtual_device_factory_->mutable_state()->retries);
ASSERT_TRUE(test_client_.failure_reason.has_value());
EXPECT_EQ(InterestingFailureReason::kHardPINBlock,
*test_client_.failure_reason);
@@ -3126,7 +3131,7 @@ class InternalUVAuthenticatorImplTest : public UVAuthenticatorImplTest {
device::VirtualCtap2Device::Config config;
config.internal_uv_support = true;
config.u2f_support = true;
- virtual_device_.SetCtap2Config(config);
+ virtual_device_factory_->SetCtap2Config(config);
NavigateAndCommit(GURL(kTestOrigin1));
}
@@ -3141,7 +3146,7 @@ TEST_F(InternalUVAuthenticatorImplTest, MakeCredential) {
for (const auto fingerprints_enrolled : {false, true}) {
SCOPED_TRACE(::testing::Message()
<< "fingerprints_enrolled=" << fingerprints_enrolled);
- virtual_device_.mutable_state()->fingerprints_enrolled =
+ virtual_device_factory_->mutable_state()->fingerprints_enrolled =
fingerprints_enrolled;
for (const auto uv :
@@ -3187,7 +3192,7 @@ TEST_F(InternalUVAuthenticatorImplTest, MakeCredentialCryptotoken) {
for (const auto fingerprints_enrolled : {false, true}) {
SCOPED_TRACE(::testing::Message()
<< "fingerprints_enrolled=" << fingerprints_enrolled);
- virtual_device_.mutable_state()->fingerprints_enrolled =
+ virtual_device_factory_->mutable_state()->fingerprints_enrolled =
fingerprints_enrolled;
TestMakeCredentialCallback callback_receiver;
authenticator->MakeCredential(
@@ -3199,7 +3204,7 @@ TEST_F(InternalUVAuthenticatorImplTest, MakeCredentialCryptotoken) {
EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
// The credential should have been created over U2F.
for (const auto& registration :
- virtual_device_.mutable_state()->registrations) {
+ virtual_device_factory_->mutable_state()->registrations) {
EXPECT_TRUE(registration.second.is_u2f);
}
}
@@ -3208,13 +3213,13 @@ TEST_F(InternalUVAuthenticatorImplTest, MakeCredentialCryptotoken) {
TEST_F(InternalUVAuthenticatorImplTest, GetAssertion) {
TestServiceManagerContext smc;
AuthenticatorPtr authenticator = ConnectToAuthenticator();
- ASSERT_TRUE(virtual_device_.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
get_credential_options()->allow_credentials[0]->id, kTestRelyingPartyId));
for (const auto fingerprints_enrolled : {false, true}) {
SCOPED_TRACE(::testing::Message()
<< "fingerprints_enrolled=" << fingerprints_enrolled);
- virtual_device_.mutable_state()->fingerprints_enrolled =
+ virtual_device_factory_->mutable_state()->fingerprints_enrolled =
fingerprints_enrolled;
for (auto uv : {blink::mojom::UserVerificationRequirement::DISCOURAGED,
@@ -3238,7 +3243,7 @@ TEST_F(InternalUVAuthenticatorImplTest, GetAssertion) {
callback_receiver.WaitForCallback();
if (should_be_unrecognized) {
- EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
callback_receiver.status());
} else {
EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
@@ -3257,13 +3262,13 @@ TEST_F(InternalUVAuthenticatorImplTest, GetAssertionCryptotoken) {
url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST);
OverrideLastCommittedOrigin(main_rfh(),
url::Origin::Create(GURL(kCryptotokenOrigin)));
- ASSERT_TRUE(virtual_device_.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
get_credential_options()->allow_credentials[0]->id, kTestRelyingPartyId));
for (const auto fingerprints_enrolled : {false, true}) {
SCOPED_TRACE(::testing::Message()
<< "fingerprints_enrolled=" << fingerprints_enrolled);
- virtual_device_.mutable_state()->fingerprints_enrolled =
+ virtual_device_factory_->mutable_state()->fingerprints_enrolled =
fingerprints_enrolled;
TestGetAssertionCallback callback_receiver;
authenticator->GetAssertion(
@@ -3288,10 +3293,12 @@ class ResidentKeyTestAuthenticatorRequestDelegate
ResidentKeyTestAuthenticatorRequestDelegate(
std::string expected_accounts,
std::vector<uint8_t> selected_user_id,
- bool* might_create_resident_credential)
+ bool* might_create_resident_credential,
+ base::Optional<InterestingFailureReason>* failure_reason)
: expected_accounts_(expected_accounts),
selected_user_id_(selected_user_id),
- might_create_resident_credential_(might_create_resident_credential) {}
+ might_create_resident_credential_(might_create_resident_credential),
+ failure_reason_(failure_reason) {}
bool SupportsPIN() const override { return true; }
@@ -3343,10 +3350,17 @@ class ResidentKeyTestAuthenticatorRequestDelegate
*might_create_resident_credential_ = v;
}
+ bool DoesBlockRequestOnFailure(InterestingFailureReason reason) override {
+ *failure_reason_ = reason;
+ return AuthenticatorRequestClientDelegate::DoesBlockRequestOnFailure(
+ reason);
+ }
+
private:
const std::string expected_accounts_;
const std::vector<uint8_t> selected_user_id_;
bool* const might_create_resident_credential_;
+ base::Optional<InterestingFailureReason>* const failure_reason_;
DISALLOW_COPY_AND_ASSIGN(ResidentKeyTestAuthenticatorRequestDelegate);
};
@@ -3358,12 +3372,15 @@ class ResidentKeyTestAuthenticatorContentBrowserClient
RenderFrameHost* render_frame_host,
const std::string& relying_party_id) override {
return std::make_unique<ResidentKeyTestAuthenticatorRequestDelegate>(
- expected_accounts, selected_user_id, &might_create_resident_credential);
+ expected_accounts, selected_user_id, &might_create_resident_credential,
+ &failure_reason);
}
std::string expected_accounts;
std::vector<uint8_t> selected_user_id;
bool might_create_resident_credential = false;
+ base::Optional<AuthenticatorRequestClientDelegate::InterestingFailureReason>
+ failure_reason;
};
class ResidentKeyAuthenticatorImplTest : public UVAuthenticatorImplTest {
@@ -3379,9 +3396,9 @@ class ResidentKeyAuthenticatorImplTest : public UVAuthenticatorImplTest {
device::VirtualCtap2Device::Config config;
config.pin_support = true;
config.resident_key_support = true;
- virtual_device_.SetCtap2Config(config);
- virtual_device_.mutable_state()->pin = kTestPIN;
- virtual_device_.mutable_state()->retries = 8;
+ virtual_device_factory_->SetCtap2Config(config);
+ virtual_device_factory_->mutable_state()->pin = kTestPIN;
+ virtual_device_factory_->mutable_state()->retries = 8;
NavigateAndCommit(GURL(kTestOrigin1));
}
@@ -3427,8 +3444,8 @@ TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredential) {
device::VirtualCtap2Device::Config config;
config.resident_key_support = true;
config.internal_uv_support = true;
- virtual_device_.SetCtap2Config(config);
- virtual_device_.mutable_state()->fingerprints_enrolled = true;
+ virtual_device_factory_->SetCtap2Config(config);
+ virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
}
TestMakeCredentialCallback callback_receiver;
@@ -3439,9 +3456,10 @@ TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredential) {
EXPECT_TRUE(test_client_.might_create_resident_credential);
EXPECT_TRUE(HasUV(callback_receiver));
- ASSERT_EQ(1u, virtual_device_.mutable_state()->registrations.size());
+ ASSERT_EQ(1u,
+ virtual_device_factory_->mutable_state()->registrations.size());
const device::VirtualFidoDevice::RegistrationData& registration =
- virtual_device_.mutable_state()->registrations.begin()->second;
+ virtual_device_factory_->mutable_state()->registrations.begin()->second;
EXPECT_TRUE(registration.is_resident);
ASSERT_TRUE(registration.user.has_value());
const auto options = make_credential_options();
@@ -3452,10 +3470,37 @@ TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredential) {
}
}
+TEST_F(ResidentKeyAuthenticatorImplTest, StorageFull) {
+ TestServiceManagerContext smc;
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+ device::VirtualCtap2Device::Config config;
+ config.resident_key_support = true;
+ config.internal_uv_support = true;
+ config.resident_credential_storage = 1;
+ virtual_device_factory_->SetCtap2Config(config);
+ virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
+
+ // Add a resident key to fill the authenticator.
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
+ /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
+ /*user_id=*/{{1, 1, 1, 1}}, "test@example.com", "Test User"));
+
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(make_credential_options(),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
+ ASSERT_TRUE(test_client_.failure_reason.has_value());
+ EXPECT_EQ(AuthenticatorRequestClientDelegate::InterestingFailureReason::
+ kStorageFull,
+ test_client_.failure_reason);
+}
+
TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionSingle) {
- ASSERT_TRUE(virtual_device_.mutable_state()->InjectResidentKey(
- /*credential_id=*/{4, 3, 2, 1}, kTestRelyingPartyId,
- /*user_id=*/{1, 2, 3, 4}, "test@example.com", "Test User"));
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
+ /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
+ /*user_id=*/{{1, 2, 3, 4}}, "test@example.com", "Test User"));
TestServiceManagerContext smc;
AuthenticatorPtr authenticator = ConnectToAuthenticator();
@@ -3470,12 +3515,12 @@ TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionSingle) {
}
TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionMulti) {
- ASSERT_TRUE(virtual_device_.mutable_state()->InjectResidentKey(
- /*credential_id=*/{4, 3, 2, 1}, kTestRelyingPartyId,
- /*user_id=*/{1, 2, 3, 4}, "test@example.com", "Test User"));
- ASSERT_TRUE(virtual_device_.mutable_state()->InjectResidentKey(
- /*credential_id=*/{4, 3, 2, 2}, kTestRelyingPartyId,
- /*user_id=*/{5, 6, 7, 8}, "test2@example.com", "Test User 2"));
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
+ /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
+ /*user_id=*/{{1, 2, 3, 4}}, "test@example.com", "Test User"));
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
+ /*credential_id=*/{{4, 3, 2, 2}}, kTestRelyingPartyId,
+ /*user_id=*/{{5, 6, 7, 8}}, "test2@example.com", "Test User 2"));
TestServiceManagerContext smc;
AuthenticatorPtr authenticator = ConnectToAuthenticator();
@@ -3491,6 +3536,546 @@ TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionMulti) {
EXPECT_TRUE(HasUV(callback_receiver));
}
-// TODO(agl): test resident-key storage exhaustion.
+TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionUVDiscouraged) {
+ device::VirtualCtap2Device::Config config;
+ config.resident_key_support = true;
+ config.internal_uv_support = true;
+ config.u2f_support = true;
+ virtual_device_factory_->SetCtap2Config(config);
+ virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
+
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
+ /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
+ /*user_id=*/{{1, 2, 3, 4}}, "test@example.com", "Test User"));
+
+ TestServiceManagerContext smc;
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+ TestGetAssertionCallback callback_receiver;
+ // |SelectAccount| should not be called when there's only a single response.
+ test_client_.expected_accounts = "<invalid>";
+ PublicKeyCredentialRequestOptionsPtr options(get_credential_options());
+ options->user_verification =
+ blink::mojom::UserVerificationRequirement::DISCOURAGED;
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
+ // The UV=discouraged should have been ignored for a resident-credential
+ // request.
+ EXPECT_TRUE(HasUV(callback_receiver));
+}
+
+static const char* ProtectionPolicyDescription(
+ blink::mojom::ProtectionPolicy p) {
+ switch (p) {
+ case blink::mojom::ProtectionPolicy::UNSPECIFIED:
+ return "UNSPECIFIED";
+ case blink::mojom::ProtectionPolicy::NONE:
+ return "NONE";
+ case blink::mojom::ProtectionPolicy::UV_OR_CRED_ID_REQUIRED:
+ return "UV_OR_CRED_ID_REQUIRED";
+ case blink::mojom::ProtectionPolicy::UV_REQUIRED:
+ return "UV_REQUIRED";
+ }
+}
+
+TEST_F(ResidentKeyAuthenticatorImplTest, CredProtectRegistration) {
+ TestServiceManagerContext smc;
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+ const auto UNSPECIFIED = blink::mojom::ProtectionPolicy::UNSPECIFIED;
+ const auto NONE = blink::mojom::ProtectionPolicy::NONE;
+ const auto UV_OR_CRED =
+ blink::mojom::ProtectionPolicy::UV_OR_CRED_ID_REQUIRED;
+ const auto UV_REQ = blink::mojom::ProtectionPolicy::UV_REQUIRED;
+ const int kOk = 0;
+ const int kNonsense = 1;
+ const int kNotAllow = 2;
+
+ const struct {
+ bool supported_by_authenticator;
+ bool is_resident;
+ blink::mojom::ProtectionPolicy protection;
+ bool enforce;
+ bool uv;
+ int expected_outcome;
+ blink::mojom::ProtectionPolicy resulting_policy;
+ } kExpectations[] = {
+ // clang-format off
+ // Support | Resdnt | Level | Enf | UV || Result | Prot level
+ { false, false, UNSPECIFIED, false, false, kOk, NONE},
+ { false, false, UNSPECIFIED, true, false, kNonsense, UNSPECIFIED},
+ { false, false, NONE, false, false, kNonsense, UNSPECIFIED},
+ { false, false, NONE, true, false, kNonsense, UNSPECIFIED},
+ { false, false, UV_OR_CRED, false, false, kOk, NONE},
+ { false, false, UV_OR_CRED, true, false, kNotAllow, UNSPECIFIED},
+ { false, false, UV_OR_CRED, false, true, kOk, NONE},
+ { false, false, UV_OR_CRED, true, true, kNotAllow, UNSPECIFIED},
+ { false, false, UV_REQ, false, false, kNonsense, UNSPECIFIED},
+ { false, false, UV_REQ, false, true, kOk, NONE},
+ { false, false, UV_REQ, true, false, kNonsense, UNSPECIFIED},
+ { false, false, UV_REQ, true, true, kNotAllow, UNSPECIFIED},
+ { false, true, UNSPECIFIED, false, false, kOk, NONE},
+ { false, true, UNSPECIFIED, true, false, kNonsense, UNSPECIFIED},
+ { false, true, NONE, false, false, kOk, NONE},
+ { false, true, NONE, true, false, kNonsense, UNSPECIFIED},
+ { false, true, UV_OR_CRED, false, false, kOk, NONE},
+ { false, true, UV_OR_CRED, true, false, kNotAllow, UNSPECIFIED},
+ { false, true, UV_REQ, false, false, kNonsense, UNSPECIFIED},
+ { false, true, UV_REQ, false, true, kOk, NONE},
+ { false, true, UV_REQ, true, false, kNonsense, UNSPECIFIED},
+ { false, true, UV_REQ, true, true, kNotAllow, UNSPECIFIED},
+
+ // For the case where the authenticator supports credProtect we do not
+ // repeat the cases above that are |kNonsense| on the assumption that
+ // authenticator support is irrelevant. Therefore these are just the non-
+ // kNonsense cases from the prior block.
+ { true, false, UNSPECIFIED, false, false, kOk, NONE},
+ { true, false, UV_OR_CRED, false, false, kOk, UV_OR_CRED},
+ { true, false, UV_OR_CRED, true, false, kOk, UV_OR_CRED},
+ { true, false, UV_OR_CRED, false, true, kOk, UV_OR_CRED},
+ { true, false, UV_OR_CRED, true, true, kOk, UV_OR_CRED},
+ { true, false, UV_REQ, false, true, kOk, UV_REQ},
+ { true, false, UV_REQ, true, true, kOk, UV_REQ},
+ { true, true, UNSPECIFIED, false, false, kOk, UV_OR_CRED},
+ { true, true, NONE, false, false, kOk, NONE},
+ { true, true, UV_OR_CRED, false, false, kOk, UV_OR_CRED},
+ { true, true, UV_OR_CRED, true, false, kOk, UV_OR_CRED},
+ { true, true, UV_REQ, false, true, kOk, UV_REQ},
+ { true, true, UV_REQ, true, true, kOk, UV_REQ},
+ // clang-format on
+ };
+
+ for (const auto& test : kExpectations) {
+ device::VirtualCtap2Device::Config config;
+ config.pin_support = true;
+ config.resident_key_support = true;
+ config.cred_protect_support = test.supported_by_authenticator;
+ virtual_device_factory_->SetCtap2Config(config);
+ virtual_device_factory_->mutable_state()->registrations.clear();
+
+ SCOPED_TRACE(::testing::Message() << "uv=" << test.uv);
+ SCOPED_TRACE(::testing::Message() << "enforce=" << test.enforce);
+ SCOPED_TRACE(::testing::Message()
+ << "level=" << ProtectionPolicyDescription(test.protection));
+ SCOPED_TRACE(::testing::Message() << "resident=" << test.is_resident);
+ SCOPED_TRACE(::testing::Message()
+ << "support=" << test.supported_by_authenticator);
+
+ PublicKeyCredentialCreationOptionsPtr options = make_credential_options();
+ options->authenticator_selection->require_resident_key = test.is_resident;
+ options->protection_policy = test.protection;
+ options->enforce_protection_policy = test.enforce;
+ options->authenticator_selection->user_verification =
+ test.uv ? blink::mojom::UserVerificationRequirement::REQUIRED
+ : blink::mojom::UserVerificationRequirement::DISCOURAGED;
+
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+
+ switch (test.expected_outcome) {
+ case kOk: {
+ EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
+ ASSERT_EQ(
+ 1u, virtual_device_factory_->mutable_state()->registrations.size());
+ const base::Optional<device::CredProtect> result =
+ virtual_device_factory_->mutable_state()
+ ->registrations.begin()
+ ->second.protection;
+
+ switch (test.resulting_policy) {
+ case UNSPECIFIED:
+ NOTREACHED();
+ break;
+ case NONE:
+ EXPECT_FALSE(result);
+ break;
+ case UV_OR_CRED:
+ ASSERT_TRUE(result);
+ EXPECT_EQ(device::CredProtect::kUVOrCredIDRequired, *result);
+ break;
+ case UV_REQ:
+ ASSERT_TRUE(result);
+ EXPECT_EQ(device::CredProtect::kUVRequired, *result);
+ break;
+ }
+ break;
+ }
+ case kNonsense:
+ EXPECT_EQ(AuthenticatorStatus::PROTECTION_POLICY_INCONSISTENT,
+ callback_receiver.status());
+ break;
+ case kNotAllow:
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
+ callback_receiver.status());
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+}
+
+TEST_F(ResidentKeyAuthenticatorImplTest, ProtectedNonResidentCreds) {
+ // Until we have UVToken, there's a danger that we'll preflight UV-required
+ // credential IDs such that the authenticator denies knowledge of all of them
+ // for silent requests and then we fail the whole request.
+ device::VirtualCtap2Device::Config config;
+ config.pin_support = true;
+ config.resident_key_support = true;
+ config.cred_protect_support = true;
+ virtual_device_factory_->SetCtap2Config(config);
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
+ /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId));
+ ASSERT_EQ(1u, virtual_device_factory_->mutable_state()->registrations.size());
+ virtual_device_factory_->mutable_state()
+ ->registrations.begin()
+ ->second.protection = device::CredProtect::kUVRequired;
+
+ TestServiceManagerContext smc;
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+ TestGetAssertionCallback callback_receiver;
+ // |SelectAccount| should not be called when there's only a single response.
+ test_client_.expected_accounts = "<invalid>";
+
+ PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
+ options->allow_credentials = GetTestCredentials(5);
+ options->allow_credentials[0]->id = {4, 3, 2, 1};
+
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
+ EXPECT_TRUE(HasUV(callback_receiver));
+}
+
+TEST_F(ResidentKeyAuthenticatorImplTest, WithAppIDExtension) {
+ // Setting an AppID value for a resident-key request should be ignored.
+ device::VirtualCtap2Device::Config config;
+ config.u2f_support = true;
+ config.pin_support = true;
+ config.resident_key_support = true;
+ config.cred_protect_support = true;
+ virtual_device_factory_->SetCtap2Config(config);
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
+ /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
+ /*user_id=*/{{1, 2, 3, 4}}, "test@example.com", "Test User"));
+
+ TestServiceManagerContext smc;
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+ TestGetAssertionCallback callback_receiver;
+ // |SelectAccount| should not be called when there's only a single response.
+ test_client_.expected_accounts = "<invalid>";
+
+ PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
+ options->appid = kTestOrigin1;
+
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
+ EXPECT_TRUE(HasUV(callback_receiver));
+}
+
+#if defined(OS_WIN)
+// Requests with a credProtect extension that have |enforce_protection_policy|
+// set should be rejected if the Windows WebAuthn API doesn't support
+// credProtect.
+TEST_F(ResidentKeyAuthenticatorImplTest, WinCredProtectApiVersion) {
+ // The canned response returned by the Windows API fake is for acme.com.
+ NavigateAndCommit(GURL("https://acme.com"));
+ TestServiceManagerContext smc;
+ for (const bool supports_cred_protect : {false, true}) {
+ SCOPED_TRACE(testing::Message()
+ << "supports_cred_protect: " << supports_cred_protect);
+
+ device::ScopedFakeWinWebAuthnApi fake_api;
+ fake_api.set_version(supports_cred_protect ? WEBAUTHN_API_VERSION_2
+ : WEBAUTHN_API_VERSION_1);
+
+ PublicKeyCredentialCreationOptionsPtr options = make_credential_options();
+ options->relying_party = PublicKeyCredentialRpEntity::New();
+ options->relying_party->id = device::test_data::kRelyingPartyId;
+ options->authenticator_selection->user_verification =
+ blink::mojom::UserVerificationRequirement::REQUIRED;
+ options->authenticator_selection->require_resident_key = true;
+ options->protection_policy =
+ blink::mojom::ProtectionPolicy::UV_OR_CRED_ID_REQUIRED;
+ options->enforce_protection_policy = true;
+ options->authenticator_selection->user_verification =
+ blink::mojom::UserVerificationRequirement::REQUIRED;
+
+ TestMakeCredentialCallback callback_receiver;
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+
+ EXPECT_EQ(callback_receiver.status(),
+ supports_cred_protect ? AuthenticatorStatus::SUCCESS
+ : AuthenticatorStatus::NOT_ALLOWED_ERROR);
+ }
+}
+#endif // defined(OS_WIN)
+
+class InternalAuthenticatorImplTest : public AuthenticatorTestBase {
+ public:
+ InternalAuthenticatorImplTest() = default;
+
+ protected:
+ void TearDown() override {
+ // The |RenderFrameHost| must outlive |AuthenticatorImpl|.
+ internal_authenticator_impl_.reset();
+ content::RenderViewHostTestHarness::TearDown();
+ }
+
+ void NavigateAndCommit(const GURL& url) {
+ // The |RenderFrameHost| must outlive |AuthenticatorImpl|.
+ internal_authenticator_impl_.reset();
+ content::RenderViewHostTestHarness::NavigateAndCommit(url);
+ }
+
+ InternalAuthenticatorPtr ConnectToAuthenticator(GURL effective_origin_url) {
+ internal_authenticator_impl_ = std::make_unique<InternalAuthenticatorImpl>(
+ main_rfh(), url::Origin::Create(effective_origin_url));
+ InternalAuthenticatorPtr authenticator;
+ internal_authenticator_impl_->Bind(mojo::MakeRequest(&authenticator));
+ return authenticator;
+ }
+
+ InternalAuthenticatorPtr ConnectToAuthenticator(
+ GURL effective_origin_url,
+ service_manager::Connector* connector,
+ std::unique_ptr<base::OneShotTimer> timer) {
+ internal_authenticator_impl_.reset(new InternalAuthenticatorImpl(
+ main_rfh(), url::Origin::Create(effective_origin_url),
+ std::make_unique<AuthenticatorCommon>(main_rfh(), connector,
+ std::move(timer))));
+ InternalAuthenticatorPtr authenticator;
+ internal_authenticator_impl_->Bind(mojo::MakeRequest(&authenticator));
+ return authenticator;
+ }
+
+ InternalAuthenticatorPtr ConstructAuthenticatorWithTimer(
+ GURL effective_origin_url,
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner) {
+ connector_ = service_manager::Connector::Create(&request_);
+ fake_hid_manager_ = std::make_unique<device::FakeHidManager>();
+ connector_->OverrideBinderForTesting(
+ service_manager::ServiceFilter::ByName(device::mojom::kServiceName),
+ device::mojom::HidManager::Name_,
+ base::BindRepeating(&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(effective_origin_url, connector_.get(),
+ std::move(timer));
+ }
+
+ protected:
+ std::unique_ptr<InternalAuthenticatorImpl> internal_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.
+TEST_F(InternalAuthenticatorImplTest, MakeCredentialOriginAndRpIds) {
+ // These instances should return security errors (for circumstances
+ // that would normally crash the renderer).
+ for (auto test_case : kInvalidRelyingPartyTestCases) {
+ SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
+ std::string(test_case.origin));
+
+ GURL origin = GURL(test_case.origin);
+ if (url::Origin::Create(origin).opaque()) {
+ // Opaque origins will cause DCHECK to fail.
+ continue;
+ }
+
+ NavigateAndCommit(origin);
+ InternalAuthenticatorPtr authenticator = ConnectToAuthenticator(origin);
+ PublicKeyCredentialCreationOptionsPtr options =
+ GetTestPublicKeyCredentialCreationOptions();
+ options->relying_party->id = test_case.claimed_authority;
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::INVALID_DOMAIN, callback_receiver.status());
+ }
+
+ // These instances should bypass security errors, by setting the effective
+ // origin to a valid one.
+ for (auto test_case : kValidRelyingPartyTestCases) {
+ SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
+ std::string(test_case.origin));
+
+ NavigateAndCommit(GURL("https://this.isthewrong.origin"));
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto authenticator =
+ ConstructAuthenticatorWithTimer(GURL(test_case.origin), task_runner);
+ PublicKeyCredentialCreationOptionsPtr options =
+ GetTestPublicKeyCredentialCreationOptions();
+ options->relying_party->id = test_case.claimed_authority;
+
+ ResetVirtualDevice();
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
+ }
+}
+
+// Verify behavior for various combinations of origins and RP IDs.
+TEST_F(InternalAuthenticatorImplTest, GetAssertionOriginAndRpIds) {
+ // These instances should return security errors (for circumstances
+ // that would normally crash the renderer).
+ for (const OriginClaimedAuthorityPair& test_case :
+ kInvalidRelyingPartyTestCases) {
+ SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
+ std::string(test_case.origin));
+
+ GURL origin = GURL(test_case.origin);
+ if (url::Origin::Create(origin).opaque()) {
+ // Opaque origins will cause DCHECK to fail.
+ continue;
+ }
+
+ NavigateAndCommit(origin);
+ InternalAuthenticatorPtr authenticator = ConnectToAuthenticator(origin);
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+ options->relying_party_id = test_case.claimed_authority;
+
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::INVALID_DOMAIN, callback_receiver.status());
+ }
+
+ // These instances should bypass security errors, by setting the effective
+ // origin to a valid one.
+ for (const OriginClaimedAuthorityPair& test_case :
+ kValidRelyingPartyTestCases) {
+ SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
+ std::string(test_case.origin));
+
+ NavigateAndCommit(GURL("https://this.isthewrong.origin"));
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto authenticator =
+ ConstructAuthenticatorWithTimer(GURL(test_case.origin), task_runner);
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+ options->relying_party_id = test_case.claimed_authority;
+
+ ResetVirtualDevice();
+ ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
+ options->allow_credentials[0]->id, test_case.claimed_authority));
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
+ }
+}
+
+#if defined(OS_MACOSX)
+class TouchIdAuthenticatorRequestDelegate
+ : public AuthenticatorRequestClientDelegate {
+ public:
+ using TouchIdAuthenticatorConfig = ::device::fido::mac::AuthenticatorConfig;
+
+ explicit TouchIdAuthenticatorRequestDelegate(
+ TouchIdAuthenticatorConfig config)
+ : config_(std::move(config)) {}
+
+ base::Optional<TouchIdAuthenticatorConfig> GetTouchIdAuthenticatorConfig()
+ const override {
+ return config_;
+ }
+
+ private:
+ TouchIdAuthenticatorConfig config_;
+ DISALLOW_COPY_AND_ASSIGN(TouchIdAuthenticatorRequestDelegate);
+};
+
+class TouchIdAuthenticatorContentBrowserClient : public ContentBrowserClient {
+ public:
+ using TouchIdAuthenticatorConfig = ::device::fido::mac::AuthenticatorConfig;
+
+ std::unique_ptr<AuthenticatorRequestClientDelegate>
+ GetWebAuthenticationRequestDelegate(
+ RenderFrameHost* render_frame_host,
+ const std::string& relying_party_id) override {
+ return std::make_unique<TouchIdAuthenticatorRequestDelegate>(
+ touch_id_config);
+ }
+
+ bool IsWebAuthenticationTouchIdAuthenticatorSupported() override {
+ return supports_touch_id;
+ }
+
+ bool supports_touch_id = true;
+
+ TouchIdAuthenticatorConfig touch_id_config;
+};
+
+class TouchIdAuthenticatorContentBrowserClientTest
+ : public AuthenticatorContentBrowserClientTest {
+ protected:
+ TouchIdAuthenticatorContentBrowserClientTest() = default;
+
+ void SetUp() override {
+ AuthenticatorImplTest::SetUp();
+ old_client_ = SetBrowserClientForTesting(&test_client_);
+ NavigateAndCommit(GURL(kTestOrigin1));
+ }
+
+ void TearDown() override {
+ SetBrowserClientForTesting(old_client_);
+ AuthenticatorImplTest::TearDown();
+ }
+
+ TouchIdAuthenticatorContentBrowserClient test_client_;
+
+ API_AVAILABLE(macos(10.12.2))
+ device::fido::mac::ScopedTouchIdTestEnvironment touch_id_test_environment_;
+
+ private:
+ ContentBrowserClient* old_client_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchIdAuthenticatorContentBrowserClientTest);
+};
+
+TEST_F(TouchIdAuthenticatorContentBrowserClientTest, IsUVPAA) {
+ if (__builtin_available(macOS 10.12.2, *)) {
+ for (const bool touch_id_enabled_in_browser_client : {false, true}) {
+ SCOPED_TRACE(::testing::Message() << "touch_id_enabled_in_browser_client="
+ << touch_id_enabled_in_browser_client);
+ for (const bool touch_id_available : {false, true}) {
+ SCOPED_TRACE(::testing::Message()
+ << "touch_id_available=" << touch_id_available);
+ touch_id_test_environment_.SetTouchIdAvailable(touch_id_available);
+ test_client_.supports_touch_id = touch_id_enabled_in_browser_client;
+
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+ TestIsUvpaaCallback cb;
+ authenticator->IsUserVerifyingPlatformAuthenticatorAvailable(
+ cb.callback());
+ cb.WaitForCallback();
+ EXPECT_EQ(cb.value(),
+ touch_id_enabled_in_browser_client && touch_id_available);
+ }
+ }
+ }
+}
+#endif // defined(OS_MACOSX)
} // namespace content
diff --git a/chromium/content/browser/webauth/authenticator_type_converters.cc b/chromium/content/browser/webauth/authenticator_type_converters.cc
index c6c8337e557..91233a46031 100644
--- a/chromium/content/browser/webauth/authenticator_type_converters.cc
+++ b/chromium/content/browser/webauth/authenticator_type_converters.cc
@@ -24,6 +24,7 @@ using ::blink::mojom::PublicKeyCredentialRpEntityPtr;
using ::blink::mojom::PublicKeyCredentialType;
using ::blink::mojom::PublicKeyCredentialUserEntityPtr;
using ::blink::mojom::UserVerificationRequirement;
+using ::blink::test::mojom::ClientToAuthenticatorProtocol;
// static
::device::FidoTransportProtocol
@@ -168,10 +169,10 @@ TypeConverter<::device::PublicKeyCredentialRpEntity,
PublicKeyCredentialRpEntityPtr>::
Convert(const PublicKeyCredentialRpEntityPtr& input) {
device::PublicKeyCredentialRpEntity rp_entity(input->id);
- rp_entity.SetRpName(input->name);
- if (input->icon)
- rp_entity.SetRpIconUrl(*input->icon);
-
+ rp_entity.name = input->name;
+ if (input->icon) {
+ rp_entity.icon_url = input->icon;
+ }
return rp_entity;
}
@@ -239,4 +240,18 @@ TypeConverter<::device::AttestationConveyancePreference,
return ::device::AttestationConveyancePreference::NONE;
}
+// static
+::device::ProtocolVersion
+TypeConverter<::device::ProtocolVersion, ClientToAuthenticatorProtocol>::
+ Convert(const ClientToAuthenticatorProtocol& input) {
+ switch (input) {
+ case ClientToAuthenticatorProtocol::U2F:
+ return ::device::ProtocolVersion::kU2f;
+ case ClientToAuthenticatorProtocol::CTAP2:
+ return ::device::ProtocolVersion::kCtap2;
+ }
+ NOTREACHED();
+ return ::device::ProtocolVersion::kUnknown;
+}
+
} // namespace mojo
diff --git a/chromium/content/browser/webauth/authenticator_type_converters.h b/chromium/content/browser/webauth/authenticator_type_converters.h
index 534270b0ba4..4c82dabc7c1 100644
--- a/chromium/content/browser/webauth/authenticator_type_converters.h
+++ b/chromium/content/browser/webauth/authenticator_type_converters.h
@@ -17,6 +17,7 @@
#include "device/fido/public_key_credential_user_entity.h"
#include "mojo/public/cpp/bindings/type_converter.h"
#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
+#include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.h"
// TODO(hongjunchoi): Remove type converters and instead expose mojo interface
// directly from device/fido service.
@@ -111,6 +112,13 @@ struct TypeConverter<::device::AttestationConveyancePreference,
const ::blink::mojom::AttestationConveyancePreference& input);
};
+template <>
+struct TypeConverter<::device::ProtocolVersion,
+ ::blink::test::mojom::ClientToAuthenticatorProtocol> {
+ static ::device::ProtocolVersion Convert(
+ const ::blink::test::mojom::ClientToAuthenticatorProtocol& input);
+};
+
} // namespace mojo
#endif // CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_TYPE_CONVERTERS_H_
diff --git a/chromium/content/browser/webauth/virtual_authenticator.cc b/chromium/content/browser/webauth/virtual_authenticator.cc
index 4fbc6ae976e..e35e02a1d72 100644
--- a/chromium/content/browser/webauth/virtual_authenticator.cc
+++ b/chromium/content/browser/webauth/virtual_authenticator.cc
@@ -10,15 +10,25 @@
#include "base/containers/span.h"
#include "base/guid.h"
#include "crypto/ec_private_key.h"
+#include "device/fido/virtual_ctap2_device.h"
#include "device/fido/virtual_u2f_device.h"
namespace content {
VirtualAuthenticator::VirtualAuthenticator(
- ::device::FidoTransportProtocol transport)
- : transport_(transport),
+ ::device::ProtocolVersion protocol,
+ ::device::FidoTransportProtocol transport,
+ ::device::AuthenticatorAttachment attachment,
+ bool has_resident_key,
+ bool has_user_verification)
+ : protocol_(protocol),
+ attachment_(attachment),
+ has_resident_key_(has_resident_key),
+ has_user_verification_(has_user_verification),
unique_id_(base::GenerateGUID()),
- state_(base::MakeRefCounted<::device::VirtualFidoDevice::State>()) {}
+ state_(base::MakeRefCounted<::device::VirtualFidoDevice::State>()) {
+ state_->transport = transport;
+}
VirtualAuthenticator::~VirtualAuthenticator() = default;
@@ -28,7 +38,21 @@ void VirtualAuthenticator::AddBinding(
}
std::unique_ptr<::device::FidoDevice> VirtualAuthenticator::ConstructDevice() {
- return std::make_unique<::device::VirtualU2fDevice>(state_);
+ switch (protocol_) {
+ case ::device::ProtocolVersion::kU2f:
+ return std::make_unique<::device::VirtualU2fDevice>(state_);
+ case ::device::ProtocolVersion::kCtap2: {
+ device::VirtualCtap2Device::Config config;
+ config.resident_key_support = has_resident_key_;
+ config.internal_uv_support = has_user_verification_;
+ config.is_platform_authenticator =
+ attachment_ == ::device::AuthenticatorAttachment::kPlatform;
+ return std::make_unique<::device::VirtualCtap2Device>(state_, config);
+ }
+ default:
+ NOTREACHED();
+ return std::make_unique<::device::VirtualU2fDevice>(state_);
+ }
}
void VirtualAuthenticator::GetUniqueId(GetUniqueIdCallback callback) {
diff --git a/chromium/content/browser/webauth/virtual_authenticator.h b/chromium/content/browser/webauth/virtual_authenticator.h
index bcf5a2c05b2..c29a35ed334 100644
--- a/chromium/content/browser/webauth/virtual_authenticator.h
+++ b/chromium/content/browser/webauth/virtual_authenticator.h
@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
-#include "device/fido/fido_transport_protocol.h"
+#include "device/fido/fido_constants.h"
#include "device/fido/virtual_fido_device.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.h"
@@ -26,12 +26,18 @@ namespace content {
class CONTENT_EXPORT VirtualAuthenticator
: public blink::test::mojom::VirtualAuthenticator {
public:
- explicit VirtualAuthenticator(::device::FidoTransportProtocol transport);
+ VirtualAuthenticator(::device::ProtocolVersion protocol,
+ ::device::FidoTransportProtocol transport,
+ ::device::AuthenticatorAttachment attachment,
+ bool has_resident_key,
+ bool has_user_verification);
~VirtualAuthenticator() override;
void AddBinding(blink::test::mojom::VirtualAuthenticatorRequest request);
- ::device::FidoTransportProtocol transport() const { return transport_; }
+ ::device::FidoTransportProtocol transport() const {
+ return state_->transport;
+ }
const std::string& unique_id() const { return unique_id_; }
// Constructs a VirtualFidoDevice instance that will perform cryptographic
@@ -55,7 +61,10 @@ class CONTENT_EXPORT VirtualAuthenticator
void GetUserPresence(GetUserPresenceCallback callback) override;
private:
- const ::device::FidoTransportProtocol transport_;
+ const ::device::ProtocolVersion protocol_;
+ const ::device::AuthenticatorAttachment attachment_;
+ const bool has_resident_key_;
+ const bool has_user_verification_;
const std::string unique_id_;
scoped_refptr<::device::VirtualFidoDevice::State> state_;
mojo::BindingSet<blink::test::mojom::VirtualAuthenticator> binding_set_;
diff --git a/chromium/content/browser/webauth/virtual_discovery.cc b/chromium/content/browser/webauth/virtual_discovery.cc
index 82e022b48ed..c0642aba546 100644
--- a/chromium/content/browser/webauth/virtual_discovery.cc
+++ b/chromium/content/browser/webauth/virtual_discovery.cc
@@ -4,23 +4,24 @@
#include "content/browser/webauth/virtual_discovery.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/webauth/scoped_virtual_authenticator_environment.h"
+#include "content/browser/webauth/authenticator_environment_impl.h"
#include "device/fido/fido_device.h"
namespace content {
VirtualFidoDiscovery::VirtualFidoDiscovery(
- ScopedVirtualAuthenticatorEnvironment* environment,
::device::FidoTransportProtocol transport)
- : FidoDeviceDiscovery(transport), environment_(environment) {}
+ : FidoDeviceDiscovery(transport) {}
VirtualFidoDiscovery::~VirtualFidoDiscovery() {
- environment_->OnDiscoveryDestroyed(this);
+ AuthenticatorEnvironmentImpl::GetInstance()->OnDiscoveryDestroyed(this);
}
void VirtualFidoDiscovery::AddVirtualDevice(
@@ -46,7 +47,7 @@ void VirtualFidoDiscovery::StartInternal() {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&VirtualFidoDiscovery::NotifyDiscoveryStarted,
- base::Unretained(this), true /* success */));
+ AsWeakPtr(), true /* success */));
}
} // namespace content
diff --git a/chromium/content/browser/webauth/virtual_discovery.h b/chromium/content/browser/webauth/virtual_discovery.h
index b4c14fc205a..952ba3b72f9 100644
--- a/chromium/content/browser/webauth/virtual_discovery.h
+++ b/chromium/content/browser/webauth/virtual_discovery.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
#include "device/fido/fido_device_discovery.h"
@@ -19,18 +20,15 @@ class FidoDevice;
namespace content {
-class ScopedVirtualAuthenticatorEnvironment;
-
// A fully automated FidoDeviceDiscovery implementation, which is disconnected
// from the real world, and discovers VirtualFidoDevice instances.
class CONTENT_EXPORT VirtualFidoDiscovery
- : public ::device::FidoDeviceDiscovery {
+ : public ::device::FidoDeviceDiscovery,
+ public base::SupportsWeakPtr<VirtualFidoDiscovery> {
public:
- // The |environment| must outlive this instance.
- VirtualFidoDiscovery(ScopedVirtualAuthenticatorEnvironment* environment,
- ::device::FidoTransportProtocol transport);
+ explicit VirtualFidoDiscovery(::device::FidoTransportProtocol transport);
- // Notifies the |environment| of this instance being destroyed.
+ // Notifies the AuthenticatorEnvironment of this instance being destroyed.
~VirtualFidoDiscovery() override;
void AddVirtualDevice(std::unique_ptr<::device::FidoDevice> device);
@@ -41,8 +39,6 @@ class CONTENT_EXPORT VirtualFidoDiscovery
void StartInternal() override;
private:
- ScopedVirtualAuthenticatorEnvironment* environment_ = nullptr;
-
std::vector<std::unique_ptr<::device::FidoDevice>>
devices_pending_discovery_start_;
diff --git a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc b/chromium/content/browser/webauth/virtual_fido_discovery_factory.cc
index 992f911fc36..f011655b739 100644
--- a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc
+++ b/chromium/content/browser/webauth/virtual_fido_discovery_factory.cc
@@ -1,15 +1,17 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/webauth/scoped_virtual_authenticator_environment.h"
+#include "content/browser/webauth/virtual_fido_discovery_factory.h"
#include <utility>
+#include <vector>
#include "base/stl_util.h"
#include "content/browser/webauth/authenticator_type_converters.h"
#include "content/browser/webauth/virtual_authenticator.h"
#include "content/browser/webauth/virtual_discovery.h"
+#include "device/fido/fido_discovery_base.h"
#include "device/fido/virtual_ctap2_device.h"
namespace content {
@@ -25,29 +27,62 @@ blink::test::mojom::VirtualAuthenticatorPtr GetMojoPtrToVirtualAuthenticator(
} // namespace
-// static
-ScopedVirtualAuthenticatorEnvironment*
-ScopedVirtualAuthenticatorEnvironment::GetInstance() {
- static base::NoDestructor<ScopedVirtualAuthenticatorEnvironment> environment;
- return environment.get();
-}
-
-ScopedVirtualAuthenticatorEnvironment::ScopedVirtualAuthenticatorEnvironment()
+VirtualFidoDiscoveryFactory::VirtualFidoDiscoveryFactory()
: virtual_device_state_(new device::VirtualFidoDevice::State) {}
-ScopedVirtualAuthenticatorEnvironment::
- ~ScopedVirtualAuthenticatorEnvironment() = default;
+VirtualFidoDiscoveryFactory::~VirtualFidoDiscoveryFactory() = default;
-void ScopedVirtualAuthenticatorEnvironment::AddBinding(
+void VirtualFidoDiscoveryFactory::AddBinding(
blink::test::mojom::VirtualAuthenticatorManagerRequest request) {
bindings_.AddBinding(this, std::move(request));
}
-void ScopedVirtualAuthenticatorEnvironment::CreateAuthenticator(
+void VirtualFidoDiscoveryFactory::OnDiscoveryDestroyed(
+ VirtualFidoDiscovery* discovery) {
+ if (base::ContainsKey(discoveries_, discovery))
+ discoveries_.erase(discovery);
+}
+
+std::unique_ptr<::device::FidoDiscoveryBase>
+VirtualFidoDiscoveryFactory::Create(device::FidoTransportProtocol transport,
+ ::service_manager::Connector* connector) {
+ auto discovery = std::make_unique<VirtualFidoDiscovery>(transport);
+
+ if (bindings_.empty()) {
+ // If no bindings are active then create a virtual device. This is useful
+ // for web-platform tests which assume that they can make webauthn calls,
+ // but which don't implement the Chromium-specific mock Mojo interfaces.
+ device::VirtualCtap2Device::Config default_config;
+ auto device = std::make_unique<device::VirtualCtap2Device>(
+ virtual_device_state_, default_config);
+ discovery->AddVirtualDevice(std::move(device));
+ } else {
+ for (auto& authenticator : authenticators_) {
+ if (discovery->transport() != authenticator.second->transport())
+ continue;
+ discovery->AddVirtualDevice(authenticator.second->ConstructDevice());
+ }
+ }
+
+ discoveries_.insert(discovery.get());
+ return discovery;
+}
+
+std::unique_ptr<::device::FidoDiscoveryBase>
+VirtualFidoDiscoveryFactory::CreateCable(
+ std::vector<device::CableDiscoveryData> cable_data) {
+ return Create(device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy,
+ nullptr);
+}
+
+void VirtualFidoDiscoveryFactory::CreateAuthenticator(
blink::test::mojom::VirtualAuthenticatorOptionsPtr options,
CreateAuthenticatorCallback callback) {
auto authenticator = std::make_unique<VirtualAuthenticator>(
- mojo::ConvertTo<::device::FidoTransportProtocol>(options->transport));
+ mojo::ConvertTo<::device::ProtocolVersion>(options->protocol),
+ mojo::ConvertTo<::device::FidoTransportProtocol>(options->transport),
+ mojo::ConvertTo<::device::AuthenticatorAttachment>(options->attachment),
+ options->has_resident_key, options->has_user_verification);
auto* authenticator_ptr = authenticator.get();
authenticators_.emplace(authenticator_ptr->unique_id(),
std::move(authenticator));
@@ -61,7 +96,7 @@ void ScopedVirtualAuthenticatorEnvironment::CreateAuthenticator(
std::move(callback).Run(GetMojoPtrToVirtualAuthenticator(authenticator_ptr));
}
-void ScopedVirtualAuthenticatorEnvironment::GetAuthenticators(
+void VirtualFidoDiscoveryFactory::GetAuthenticators(
GetAuthenticatorsCallback callback) {
std::vector<blink::test::mojom::VirtualAuthenticatorPtrInfo>
mojo_authenticators;
@@ -74,7 +109,7 @@ void ScopedVirtualAuthenticatorEnvironment::GetAuthenticators(
std::move(callback).Run(std::move(mojo_authenticators));
}
-void ScopedVirtualAuthenticatorEnvironment::RemoveAuthenticator(
+void VirtualFidoDiscoveryFactory::RemoveAuthenticator(
const std::string& id,
RemoveAuthenticatorCallback callback) {
const bool removed = authenticators_.erase(id);
@@ -86,7 +121,7 @@ void ScopedVirtualAuthenticatorEnvironment::RemoveAuthenticator(
std::move(callback).Run(removed);
}
-void ScopedVirtualAuthenticatorEnvironment::ClearAuthenticators(
+void VirtualFidoDiscoveryFactory::ClearAuthenticators(
ClearAuthenticatorsCallback callback) {
for (auto& authenticator : authenticators_) {
for (auto* discovery : discoveries_) {
@@ -98,36 +133,4 @@ void ScopedVirtualAuthenticatorEnvironment::ClearAuthenticators(
std::move(callback).Run();
}
-std::unique_ptr<::device::FidoDiscoveryBase>
-ScopedVirtualAuthenticatorEnvironment::CreateFidoDiscovery(
- device::FidoTransportProtocol transport,
- ::service_manager::Connector* connector) {
- auto discovery = std::make_unique<VirtualFidoDiscovery>(this, transport);
-
- if (bindings_.empty()) {
- // If no bindings are active then create a virtual device. This is useful
- // for web-platform tests which assume that they can make webauthn calls,
- // but which don't implement the Chromium-specific mock Mojo interfaces.
- device::VirtualCtap2Device::Config default_config;
- auto device = std::make_unique<device::VirtualCtap2Device>(
- virtual_device_state_, default_config);
- discovery->AddVirtualDevice(std::move(device));
- } else {
- for (auto& authenticator : authenticators_) {
- if (discovery->transport() != authenticator.second->transport())
- continue;
- discovery->AddVirtualDevice(authenticator.second->ConstructDevice());
- }
- }
-
- discoveries_.insert(discovery.get());
- return discovery;
-}
-
-void ScopedVirtualAuthenticatorEnvironment::OnDiscoveryDestroyed(
- VirtualFidoDiscovery* discovery) {
- DCHECK(base::ContainsKey(discoveries_, discovery));
- discoveries_.erase(discovery);
-}
-
} // namespace content
diff --git a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h b/chromium/content/browser/webauth/virtual_fido_discovery_factory.h
index a74ba1424c8..8c22c5356f1 100644
--- a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h
+++ b/chromium/content/browser/webauth/virtual_fido_discovery_factory.h
@@ -1,49 +1,56 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_WEBAUTH_SCOPED_VIRTUAL_AUTHENTICATOR_ENVIRONMENT_H_
-#define CONTENT_BROWSER_WEBAUTH_SCOPED_VIRTUAL_AUTHENTICATOR_ENVIRONMENT_H_
+#ifndef CONTENT_BROWSER_WEBAUTH_VIRTUAL_FIDO_DISCOVERY_FACTORY_H_
+#define CONTENT_BROWSER_WEBAUTH_VIRTUAL_FIDO_DISCOVERY_FACTORY_H_
#include <map>
#include <memory>
+#include <set>
#include <string>
#include <vector>
#include "base/macros.h"
-#include "base/no_destructor.h"
#include "content/common/content_export.h"
#include "device/fido/fido_discovery_factory.h"
#include "device/fido/virtual_fido_device.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.h"
+namespace device {
+class FidoDiscoveryBase;
+}
+
namespace content {
class VirtualAuthenticator;
class VirtualFidoDiscovery;
-// Implements the Mojo interface representing a scoped virtual environment for
-// the Web Authentication API. While in scope, the API is disconnected from the
-// real world and allows setting up and configuration of virtual authenticator
-// devices for testing.
-//
-// This class is a singleton. The virtual state is persisted for the entire
-// lifetime of the browser process and shared by all frames in all WebContents
-// and across all BrowserContexts.
-class CONTENT_EXPORT ScopedVirtualAuthenticatorEnvironment
+// Implements the Mojo interface representing a virtual authenticator manager
+// for the Web Authentication API. Allows setting up and configurating virtual
+// authenticator devices for testing.
+class CONTENT_EXPORT VirtualFidoDiscoveryFactory
: public blink::test::mojom::VirtualAuthenticatorManager,
- protected device::internal::ScopedFidoDiscoveryFactory {
+ public device::FidoDiscoveryFactory {
public:
- static ScopedVirtualAuthenticatorEnvironment* GetInstance();
+ VirtualFidoDiscoveryFactory();
+ ~VirtualFidoDiscoveryFactory() override;
void AddBinding(
blink::test::mojom::VirtualAuthenticatorManagerRequest request);
- protected:
- ScopedVirtualAuthenticatorEnvironment();
- ~ScopedVirtualAuthenticatorEnvironment() override;
+ // Notify that a discovery has been destroyed.
+ void OnDiscoveryDestroyed(VirtualFidoDiscovery* discovery);
+ // device::FidoDiscoveryFactory:
+ std::unique_ptr<::device::FidoDiscoveryBase> Create(
+ device::FidoTransportProtocol transport,
+ ::service_manager::Connector* connector) override;
+ std::unique_ptr<::device::FidoDiscoveryBase> CreateCable(
+ std::vector<device::CableDiscoveryData> cable_data) override;
+
+ protected:
// blink::test::mojom::VirtualAuthenticatorManager:
void CreateAuthenticator(
blink::test::mojom::VirtualAuthenticatorOptionsPtr options,
@@ -53,18 +60,7 @@ class CONTENT_EXPORT ScopedVirtualAuthenticatorEnvironment
RemoveAuthenticatorCallback callback) override;
void ClearAuthenticators(ClearAuthenticatorsCallback callback) override;
- // ScopedFidoDiscoveryFactory:
- std::unique_ptr<::device::FidoDiscoveryBase> CreateFidoDiscovery(
- device::FidoTransportProtocol transport,
- ::service_manager::Connector* connector) override;
-
private:
- friend class base::NoDestructor<ScopedVirtualAuthenticatorEnvironment>;
- friend class VirtualFidoDiscovery;
-
- // Called by VirtualFidoDiscoveries when they are destructed.
- void OnDiscoveryDestroyed(VirtualFidoDiscovery* discovery);
-
mojo::BindingSet<blink::test::mojom::VirtualAuthenticatorManager> bindings_;
// The key is the unique_id of the corresponding value (the authenticator).
@@ -76,9 +72,9 @@ class CONTENT_EXPORT ScopedVirtualAuthenticatorEnvironment
scoped_refptr<device::VirtualFidoDevice::State> virtual_device_state_;
- DISALLOW_COPY_AND_ASSIGN(ScopedVirtualAuthenticatorEnvironment);
+ DISALLOW_COPY_AND_ASSIGN(VirtualFidoDiscoveryFactory);
};
} // namespace content
-#endif // CONTENT_BROWSER_WEBAUTH_SCOPED_VIRTUAL_AUTHENTICATOR_ENVIRONMENT_H_
+#endif // CONTENT_BROWSER_WEBAUTH_VIRTUAL_FIDO_DISCOVERY_FACTORY_H_
diff --git a/chromium/content/browser/webauth/webauth_browsertest.cc b/chromium/content/browser/webauth/webauth_browsertest.cc
index 8c00e09fd14..f45c8ec1754 100644
--- a/chromium/content/browser/webauth/webauth_browsertest.cc
+++ b/chromium/content/browser/webauth/webauth_browsertest.cc
@@ -15,8 +15,10 @@
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
+#include "build/build_config.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_environment_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"
@@ -38,8 +40,8 @@
#include "device/fido/fido_test_data.h"
#include "device/fido/hid/fake_hid_impl_for_testing.h"
#include "device/fido/mock_fido_device.h"
-#include "device/fido/scoped_virtual_fido_device.h"
#include "device/fido/test_callback_receiver.h"
+#include "device/fido/virtual_fido_device_factory.h"
#include "net/dns/mock_host_resolver.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -47,6 +49,10 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
+#if defined(OS_WIN)
+#include "device/fido/win/fake_webauthn_api.h"
+#endif
+
namespace content {
namespace {
@@ -70,7 +76,7 @@ constexpr char kPublicKeyErrorMessage[] =
"webauth: NotSupportedError: Required parameters missing in "
"`options.publicKey`.";
-constexpr char kTimeoutErrorMessage[] =
+constexpr char kNotAllowedErrorMessage[] =
"webauth: NotAllowedError: The operation either timed out or was not "
"allowed. See: https://w3c.github.io/webauthn/#sec-assertion-privacy.";
@@ -88,9 +94,8 @@ constexpr char kRelyingPartyUserIconUrlSecurityErrorMessage[] =
constexpr char kRelyingPartyRpIconUrlSecurityErrorMessage[] =
"webauth: SecurityError: 'rp.icon' should be a secure URL";
-constexpr char kInvalidStateError[] =
- "webauth: InvalidStateError: The user attempted to use an authenticator "
- "that recognized none of the provided credentials.";
+constexpr char kAbortErrorMessage[] =
+ "webauth: AbortError: The user aborted a request.";
// Templates to be used with base::ReplaceStringPlaceholders. Can be
// modified to include up to 9 replacements. The default values for
@@ -118,6 +123,29 @@ constexpr char kCreatePublicKeyTemplate[] =
" e => window.domAutomationController.send("
" 'webauth: ' + e.toString()));";
+constexpr char kCreatePublicKeyWithAbortSignalTemplate[] =
+ "navigator.credentials.create({ publicKey: {"
+ " challenge: new TextEncoder().encode('climb a mountain'),"
+ " rp: { id: '$3', name: 'Acme', icon: '$7'},"
+ " user: { "
+ " id: new TextEncoder().encode('1098237235409872'),"
+ " name: 'avery.a.jones@example.com',"
+ " displayName: 'Avery A. Jones', "
+ " icon: '$8'},"
+ " pubKeyCredParams: [{ type: 'public-key', alg: '$4'}],"
+ " timeout: 1000,"
+ " excludeCredentials: [],"
+ " authenticatorSelection: {"
+ " requireResidentKey: $1,"
+ " userVerification: '$2',"
+ " authenticatorAttachment: '$5',"
+ " },"
+ " attestation: '$6',"
+ "}, signal: $9}"
+ ").then(c => window.domAutomationController.send('webauth: OK'),"
+ " e => window.domAutomationController.send("
+ " 'webauth: ' + e.toString()));";
+
constexpr char kPlatform[] = "platform";
constexpr char kCrossPlatform[] = "cross-platform";
constexpr char kPreferredVerification[] = "preferred";
@@ -133,6 +161,7 @@ struct CreateParameters {
const char* attestation = "none";
const char* rp_icon = "https://pics.acme.com/00/p/aBjjjpqPb.png";
const char* user_icon = "https://pics.acme.com/00/p/aBjjjpqPb.png";
+ const char* signal = "";
};
std::string BuildCreateCallWithParameters(const CreateParameters& parameters) {
@@ -145,8 +174,13 @@ std::string BuildCreateCallWithParameters(const CreateParameters& parameters) {
substitutions.push_back(parameters.attestation);
substitutions.push_back(parameters.rp_icon);
substitutions.push_back(parameters.user_icon);
- return base::ReplaceStringPlaceholders(kCreatePublicKeyTemplate,
- substitutions, nullptr);
+ if (strlen(parameters.signal) == 0) {
+ return base::ReplaceStringPlaceholders(kCreatePublicKeyTemplate,
+ substitutions, nullptr);
+ }
+ substitutions.push_back(parameters.signal);
+ return base::ReplaceStringPlaceholders(
+ kCreatePublicKeyWithAbortSignalTemplate, substitutions, nullptr);
}
constexpr char kGetPublicKeyTemplate[] =
@@ -156,6 +190,18 @@ constexpr char kGetPublicKeyTemplate[] =
" timeout: 1000,"
" userVerification: '$1',"
" $2}"
+ "}).then(c => window.domAutomationController.send('webauth: OK'),"
+ " e => window.domAutomationController.send("
+ " 'webauth: ' + e.toString()));";
+
+constexpr char kGetPublicKeyWithAbortSignalTemplate[] =
+ "navigator.credentials.get({ publicKey: {"
+ " challenge: new TextEncoder().encode('climb a mountain'),"
+ " rpId: 'acme.com',"
+ " timeout: 1000,"
+ " userVerification: '$1',"
+ " $2},"
+ " signal: $3"
"}).catch(c => window.domAutomationController.send("
" 'webauth: ' + c.toString()));";
@@ -166,14 +212,20 @@ struct GetParameters {
"allowCredentials: [{ type: 'public-key',"
" id: new TextEncoder().encode('allowedCredential'),"
" transports: ['usb', 'nfc', 'ble']}]";
+ const char* signal = "";
};
std::string BuildGetCallWithParameters(const GetParameters& parameters) {
- std::vector<std::string> substititions;
- substititions.push_back(parameters.user_verification);
- substititions.push_back(parameters.allow_credentials);
- return base::ReplaceStringPlaceholders(kGetPublicKeyTemplate, substititions,
- nullptr);
+ std::vector<std::string> substitutions;
+ substitutions.push_back(parameters.user_verification);
+ substitutions.push_back(parameters.allow_credentials);
+ if (strlen(parameters.signal) == 0) {
+ return base::ReplaceStringPlaceholders(kGetPublicKeyTemplate, substitutions,
+ nullptr);
+ }
+ substitutions.push_back(parameters.signal);
+ return base::ReplaceStringPlaceholders(kGetPublicKeyWithAbortSignalTemplate,
+ substitutions, nullptr);
}
// Helper class that executes the given |closure| the very last moment before
@@ -335,6 +387,16 @@ class WebAuthBrowserTestBase : public content::ContentBrowserTest {
return https_server_.GetURL(hostname, relative_url);
}
+ device::test::VirtualFidoDeviceFactory* InjectVirtualFidoDeviceFactory() {
+ auto owned_virtual_device_factory =
+ std::make_unique<device::test::VirtualFidoDeviceFactory>();
+ auto* virtual_device_factory = owned_virtual_device_factory.get();
+ AuthenticatorEnvironmentImpl::GetInstance()
+ ->ReplaceDefaultDiscoveryFactoryForTesting(
+ std::move(owned_virtual_device_factory));
+ return virtual_device_factory;
+ }
+
net::EmbeddedTestServer& https_server() { return https_server_; }
WebAuthBrowserTestState* test_state() { return &test_state_; }
@@ -362,7 +424,14 @@ class WebAuthBrowserTestBase : public content::ContentBrowserTest {
// accessed from a testing client in the browser process.
class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase {
public:
- WebAuthLocalClientBrowserTest() = default;
+ WebAuthLocalClientBrowserTest() {
+ auto discovery_factory =
+ std::make_unique<device::test::FakeFidoDiscoveryFactory>();
+ discovery_factory_ = discovery_factory.get();
+ AuthenticatorEnvironmentImpl::GetInstance()
+ ->ReplaceDefaultDiscoveryFactoryForTesting(
+ std::move(discovery_factory));
+ }
~WebAuthLocalClientBrowserTest() override = default;
protected:
@@ -400,7 +469,8 @@ class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase {
base::TimeDelta::FromSeconds(30),
std::vector<blink::mojom::PublicKeyCredentialDescriptorPtr>(), nullptr,
blink::mojom::AttestationConveyancePreference::NONE, nullptr,
- false /* no hmac_secret */);
+ false /* no hmac_secret */, blink::mojom::ProtectionPolicy::UNSPECIFIED,
+ false /* protection policy not enforced */);
return mojo_options;
}
@@ -439,6 +509,8 @@ class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase {
AuthenticatorPtr& authenticator() { return authenticator_ptr_; }
+ device::test::FakeFidoDiscoveryFactory* discovery_factory_;
+
private:
AuthenticatorPtr authenticator_ptr_;
@@ -449,8 +521,7 @@ class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase {
// pending navigator.credentials.create({publicKey: ...}) call.
IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
CreatePublicKeyCredentialThenNavigateAway) {
- device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
- auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
+ auto* fake_hid_discovery = discovery_factory_->ForgeNextHidDiscovery();
TestCreateCallbackReceiver create_callback_receiver;
authenticator()->MakeCredential(BuildBasicCreateOptions(),
create_callback_receiver.callback());
@@ -462,7 +533,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();
@@ -472,8 +543,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
// pending navigator.credentials.get({publicKey: ...}) call.
IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
GetPublicKeyCredentialThenNavigateAway) {
- device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
- auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
+ auto* fake_hid_discovery = discovery_factory_->ForgeNextHidDiscovery();
TestGetCallbackReceiver get_callback_receiver;
authenticator()->GetAssertion(BuildBasicGetOptions(),
get_callback_receiver.callback());
@@ -485,7 +555,7 @@ 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();
@@ -521,7 +591,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
for (auto behavior : kAllAttestationCallbackBehaviors) {
SCOPED_TRACE(AttestationCallbackBehaviorToString(behavior));
- device::test::ScopedVirtualFidoDevice virtual_device;
+ InjectVirtualFidoDeviceFactory();
TestCreateCallbackReceiver create_callback_receiver;
auto options = BuildBasicCreateOptions();
options->attestation =
@@ -557,8 +627,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html"));
- device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
- auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
+ auto* fake_hid_discovery = discovery_factory_->ForgeNextHidDiscovery();
TestCreateCallbackReceiver create_callback_receiver;
authenticator()->MakeCredential(BuildBasicCreateOptions(),
create_callback_receiver.callback());
@@ -579,8 +648,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
create_callback_receiver.callback());
}));
- device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
- auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
+ auto* fake_hid_discovery = discovery_factory_->ForgeNextHidDiscovery();
NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html"));
WaitForConnectionError();
@@ -588,14 +656,14 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
// factory as one of the first steps. Here, the request should not have been
// serviced at all, so the fake request should still be pending on the fake
// factory.
- auto hid_discovery = ::device::FidoDiscoveryFactory::Create(
+ auto hid_discovery = discovery_factory_->Create(
::device::FidoTransportProtocol::kUsbHumanInterfaceDevice, nullptr);
ASSERT_TRUE(!!hid_discovery);
// 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();
@@ -633,8 +701,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
CreatePublicKeyCredentialWhileRequestIsPending) {
- device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
- auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
+ auto* fake_hid_discovery = discovery_factory_->ForgeNextHidDiscovery();
TestCreateCallbackReceiver callback_receiver_1;
TestCreateCallbackReceiver callback_receiver_2;
authenticator()->MakeCredential(BuildBasicCreateOptions(),
@@ -651,8 +718,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
GetPublicKeyCredentialWhileRequestIsPending) {
- device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
- auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
+ auto* fake_hid_discovery = discovery_factory_->ForgeNextHidDiscovery();
TestGetCallbackReceiver callback_receiver_1;
TestGetCallbackReceiver callback_receiver_2;
authenticator()->GetAssertion(BuildBasicGetOptions(),
@@ -683,7 +749,7 @@ class WebAuthJavascriptClientBrowserTest : public WebAuthBrowserTestBase {
};
constexpr device::ProtocolVersion kAllProtocols[] = {
- device::ProtocolVersion::kCtap, device::ProtocolVersion::kU2f};
+ device::ProtocolVersion::kCtap2, device::ProtocolVersion::kU2f};
// Tests that when navigator.credentials.create() is called with an invalid
// relying party id, we get a SecurityError.
@@ -749,8 +815,8 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
CreatePublicKeyCredentialWithUserVerification) {
for (const auto protocol : kAllProtocols) {
- device::test::ScopedVirtualFidoDevice virtual_device;
- virtual_device.SetSupportedProtocol(protocol);
+ auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
+ virtual_device_factory->SetSupportedProtocol(protocol);
CreateParameters parameters;
parameters.user_verification = kRequiredVerification;
@@ -758,7 +824,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
ASSERT_TRUE(content::ExecuteScriptAndExtractString(
shell()->web_contents()->GetMainFrame(),
BuildCreateCallWithParameters(parameters), &result));
- ASSERT_EQ(kTimeoutErrorMessage, result);
+ ASSERT_EQ(kNotAllowedErrorMessage, result);
}
}
@@ -767,8 +833,8 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
CreatePublicKeyCredentialWithResidentKeyRequired) {
for (const auto protocol : kAllProtocols) {
- device::test::ScopedVirtualFidoDevice virtual_device;
- virtual_device.SetSupportedProtocol(protocol);
+ auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
+ virtual_device_factory->SetSupportedProtocol(protocol);
CreateParameters parameters;
parameters.require_resident_key = true;
@@ -786,8 +852,8 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
CreatePublicKeyCredentialAlgorithmNotSupported) {
for (const auto protocol : kAllProtocols) {
- device::test::ScopedVirtualFidoDevice virtual_device;
- virtual_device.SetSupportedProtocol(protocol);
+ auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
+ virtual_device_factory->SetSupportedProtocol(protocol);
CreateParameters parameters;
parameters.algorithm_identifier = "123";
@@ -796,7 +862,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
shell()->web_contents()->GetMainFrame(),
BuildCreateCallWithParameters(parameters), &result));
- ASSERT_EQ(kTimeoutErrorMessage, result);
+ ASSERT_EQ(kNotAllowedErrorMessage, result);
}
}
@@ -805,8 +871,8 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
CreatePublicKeyCredentialPlatformAuthenticator) {
for (const auto protocol : kAllProtocols) {
- device::test::ScopedVirtualFidoDevice virtual_device;
- virtual_device.SetSupportedProtocol(protocol);
+ auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
+ virtual_device_factory->SetSupportedProtocol(protocol);
CreateParameters parameters;
parameters.authenticator_attachment = kPlatform;
@@ -815,9 +881,66 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
shell()->web_contents()->GetMainFrame(),
BuildCreateCallWithParameters(parameters), &result));
- ASSERT_EQ(kTimeoutErrorMessage, result);
+ ASSERT_EQ(kNotAllowedErrorMessage, result);
}
}
+// Tests that when navigator.credentials.create() is called with abort
+// signal's aborted flag not set, we get a SUCCESS.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ CreatePublicKeyCredentialWithAbortNotSet) {
+ for (const auto protocol : kAllProtocols) {
+ auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
+ virtual_device_factory->SetSupportedProtocol(protocol);
+
+ CreateParameters parameters;
+ parameters.signal = "authAbortSignal";
+ std::string result;
+ std::string script =
+ "authAbortController = new AbortController();"
+ "authAbortSignal = authAbortController.signal;" +
+ BuildCreateCallWithParameters(parameters);
+
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ shell()->web_contents()->GetMainFrame(), script, &result));
+ ASSERT_EQ("webauth: OK", result);
+ }
+}
+
+// Tests that when navigator.credentials.create() is called with abort
+// signal's aborted flag set before sending request, we get an AbortError.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ CreatePublicKeyCredentialWithAbortSetBeforeCreate) {
+ CreateParameters parameters;
+ parameters.signal = "authAbortSignal";
+ std::string result;
+ std::string script =
+ "authAbortController = new AbortController();"
+ "authAbortSignal = authAbortController.signal;"
+ "authAbortController.abort();" +
+ BuildCreateCallWithParameters(parameters);
+
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ shell()->web_contents()->GetMainFrame(), script, &result));
+ ASSERT_EQ(kAbortErrorMessage, result.substr(0, strlen(kAbortErrorMessage)));
+}
+
+// Tests that when navigator.credentials.create() is called with abort
+// signal's aborted flag set after sending request, we get an AbortError.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ CreatePublicKeyCredentialWithAbortSetAfterCreate) {
+ CreateParameters parameters;
+ parameters.signal = "authAbortSignal";
+ std::string result;
+ std::string script =
+ "authAbortController = new AbortController();"
+ "authAbortSignal = authAbortController.signal;" +
+ BuildCreateCallWithParameters(parameters) +
+ "authAbortController.abort();";
+
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ shell()->web_contents()->GetMainFrame(), script, &result));
+ ASSERT_EQ(kAbortErrorMessage, result.substr(0, strlen(kAbortErrorMessage)));
+}
// Tests that when navigator.credentials.get() is called with user verification
// required, we get an InvalidStateError because the virtual device isn't
@@ -827,8 +950,8 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
GetPublicKeyCredentialUserVerification) {
for (const auto protocol : kAllProtocols) {
- device::test::ScopedVirtualFidoDevice virtual_device;
- virtual_device.SetSupportedProtocol(protocol);
+ auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
+ virtual_device_factory->SetSupportedProtocol(protocol);
GetParameters parameters;
parameters.user_verification = "required";
@@ -836,7 +959,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
ASSERT_TRUE(content::ExecuteScriptAndExtractString(
shell()->web_contents()->GetMainFrame(),
BuildGetCallWithParameters(parameters), &result));
- ASSERT_EQ(kInvalidStateError, result);
+ ASSERT_EQ(kNotAllowedErrorMessage, result);
}
}
@@ -844,7 +967,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
// allowCredentials list, we get a NotSupportedError.
IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
GetPublicKeyCredentialEmptyAllowCredentialsList) {
- device::test::ScopedVirtualFidoDevice virtual_device;
+ InjectVirtualFidoDeviceFactory();
GetParameters parameters;
parameters.allow_credentials = "";
std::string result;
@@ -854,19 +977,79 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
ASSERT_EQ(kResidentCredentialsErrorMessage, result);
}
+// Tests that when navigator.credentials.get() is called with abort
+// signal's aborted flag not set, we get a NOT_ALLOWED_ERROR, because the
+// virtual device does not have any registered credentials.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ GetPublicKeyCredentialWithAbortNotSet) {
+ for (const auto protocol : kAllProtocols) {
+ auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
+ virtual_device_factory->SetSupportedProtocol(protocol);
+
+ GetParameters parameters;
+ parameters.signal = "authAbortSignal";
+ std::string result;
+ std::string script =
+ "authAbortController = new AbortController();"
+ "authAbortSignal = authAbortController.signal;" +
+ BuildGetCallWithParameters(parameters);
+
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ shell()->web_contents()->GetMainFrame(), script, &result));
+ ASSERT_EQ(kNotAllowedErrorMessage, result);
+ }
+}
+
+// Tests that when navigator.credentials.get() is called with abort
+// signal's aborted flag set before sending request, we get an AbortError.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ GetPublicKeyCredentialWithAbortSetBeforeGet) {
+ GetParameters parameters;
+ parameters.signal = "authAbortSignal";
+ std::string result;
+ std::string script =
+ "authAbortController = new AbortController();"
+ "authAbortSignal = authAbortController.signal;"
+ "authAbortController.abort();" +
+ BuildGetCallWithParameters(parameters);
+
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ shell()->web_contents()->GetMainFrame(), script, &result));
+ ASSERT_EQ(kAbortErrorMessage, result.substr(0, strlen(kAbortErrorMessage)));
+}
+
+// Tests that when navigator.credentials.get() is called with abort
+// signal's aborted flag set after sending request, we get an AbortError.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ GetPublicKeyCredentialWithAbortSetAfterGet) {
+ GetParameters parameters;
+ parameters.signal = "authAbortSignal";
+ std::string result;
+ std::string script =
+ "authAbortController = new AbortController();"
+ "authAbortSignal = authAbortController.signal;" +
+ BuildGetCallWithParameters(parameters) + "authAbortController.abort();";
+
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ shell()->web_contents()->GetMainFrame(), script, &result));
+ ASSERT_EQ(kAbortErrorMessage, result.substr(0, strlen(kAbortErrorMessage)));
+}
+
// WebAuthBrowserBleDisabledTest
// ----------------------------------------------
// A test fixture that does not enable BLE discovery.
class WebAuthBrowserBleDisabledTest : public WebAuthLocalClientBrowserTest {
public:
- WebAuthBrowserBleDisabledTest() = default;
+ WebAuthBrowserBleDisabledTest() {}
protected:
std::vector<base::Feature> GetFeaturesToEnable() override {
return {features::kWebAuth};
}
+ device::test::FakeFidoDiscoveryFactory* discovery_factory;
+
private:
base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(WebAuthBrowserBleDisabledTest);
@@ -875,9 +1058,8 @@ 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) {
- device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
- auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
- auto* fake_ble_discovery = discovery_factory.ForgeNextBleDiscovery();
+ auto* fake_hid_discovery = discovery_factory_->ForgeNextHidDiscovery();
+ auto* fake_ble_discovery = discovery_factory_->ForgeNextBleDiscovery();
// Do something that will start discoveries.
TestCreateCallbackReceiver create_callback_receiver;
@@ -927,9 +1109,9 @@ base::Optional<std::string> ExecuteScriptAndExtractPrefixedString(
// request is waiting for user consent.
IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
NavigateSubframeDuringPress) {
- device::test::ScopedVirtualFidoDevice virtual_device;
+ auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
bool prompt_callback_was_invoked = false;
- virtual_device.mutable_state()->simulate_press_callback =
+ virtual_device_factory->mutable_state()->simulate_press_callback =
base::BindLambdaForTesting([&]() {
prompt_callback_was_invoked = true;
NavigateIframeToURL(shell()->web_contents(), "test_iframe",
@@ -951,7 +1133,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
NavigateSubframeDuringAttestationPrompt) {
- device::test::ScopedVirtualFidoDevice virtual_device;
+ InjectVirtualFidoDeviceFactory();
for (auto behavior : kAllAttestationCallbackBehaviors) {
if (behavior == AttestationCallbackBehavior::IGNORE_CALLBACK) {
@@ -1007,6 +1189,76 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
}
}
+#if defined(OS_WIN)
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest, WinMakeCredential) {
+ NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title1.html"));
+
+ device::ScopedFakeWinWebAuthnApi fake_api;
+ fake_api.set_is_uvpaa(true);
+ fake_api.set_hresult(S_OK);
+
+ base::Optional<std::string> result = ExecuteScriptAndExtractPrefixedString(
+ shell()->web_contents(),
+ BuildCreateCallWithParameters(CreateParameters()), "webauth: ");
+ ASSERT_TRUE(result);
+ ASSERT_EQ("webauth: OK", *result);
+}
+
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ WinMakeCredentialReturnCodeFailure) {
+ NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title1.html"));
+
+ device::ScopedFakeWinWebAuthnApi fake_api;
+ fake_api.set_is_uvpaa(true);
+ fake_api.set_hresult(E_FAIL);
+
+ // The authenticator response was good but the return code indicated failure.
+ base::Optional<std::string> result = ExecuteScriptAndExtractPrefixedString(
+ shell()->web_contents(),
+ BuildCreateCallWithParameters(CreateParameters()), "webauth: ");
+ ASSERT_TRUE(result);
+ ASSERT_EQ(kNotAllowedErrorMessage, *result);
+}
+
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest, WinGetAssertion) {
+ NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title1.html"));
+
+ device::ScopedFakeWinWebAuthnApi fake_api;
+ fake_api.set_is_uvpaa(true);
+ fake_api.set_hresult(S_OK);
+
+ base::Optional<std::string> result = ExecuteScriptAndExtractPrefixedString(
+ shell()->web_contents(), BuildGetCallWithParameters(GetParameters()),
+ "webauth: ");
+ ASSERT_TRUE(result);
+ ASSERT_EQ("webauth: OK", *result);
+
+ // The authenticator response was good but the return code indicated failure.
+ fake_api.set_hresult(E_FAIL);
+ result = ExecuteScriptAndExtractPrefixedString(
+ shell()->web_contents(), BuildGetCallWithParameters(GetParameters()),
+ "webauth: ");
+ ASSERT_TRUE(result);
+ ASSERT_EQ(kNotAllowedErrorMessage, *result);
+}
+
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ WinGetAssertionReturnCodeFailure) {
+ NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title1.html"));
+
+ device::ScopedFakeWinWebAuthnApi fake_api;
+ fake_api.set_is_uvpaa(true);
+ fake_api.set_hresult(E_FAIL);
+
+ // The authenticator response was good but the return code indicated failure.
+ base::Optional<std::string> result = ExecuteScriptAndExtractPrefixedString(
+ shell()->web_contents(), BuildGetCallWithParameters(GetParameters()),
+ "webauth: ");
+ ASSERT_TRUE(result);
+ ASSERT_EQ(kNotAllowedErrorMessage, *result);
+}
+#endif
+
// WebAuthBrowserCtapTest ----------------------------------------------
class WebAuthBrowserCtapTest : public WebAuthLocalClientBrowserTest {
@@ -1019,8 +1271,8 @@ class WebAuthBrowserCtapTest : public WebAuthLocalClientBrowserTest {
IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest, TestMakeCredential) {
for (const auto protocol : kAllProtocols) {
- device::test::ScopedVirtualFidoDevice virtual_device;
- virtual_device.SetSupportedProtocol(protocol);
+ auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
+ virtual_device_factory->SetSupportedProtocol(protocol);
TestCreateCallbackReceiver create_callback_receiver;
authenticator()->MakeCredential(BuildBasicCreateOptions(),
@@ -1034,8 +1286,8 @@ IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest, TestMakeCredential) {
IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest,
TestMakeCredentialWithDuplicateKeyHandle) {
for (const auto protocol : kAllProtocols) {
- device::test::ScopedVirtualFidoDevice virtual_device;
- virtual_device.SetSupportedProtocol(protocol);
+ auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
+ virtual_device_factory->SetSupportedProtocol(protocol);
auto make_credential_request = BuildBasicCreateOptions();
auto excluded_credential = blink::mojom::PublicKeyCredentialDescriptor::New(
blink::mojom::PublicKeyCredentialType::PUBLIC_KEY,
@@ -1046,7 +1298,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest,
make_credential_request->exclude_credentials.push_back(
std::move(excluded_credential));
- ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory->mutable_state()->InjectRegistration(
device::fido_parsing_utils::Materialize(
device::test_data::kCtap2MakeCredentialCredentialId),
make_credential_request->relying_party->id));
@@ -1063,10 +1315,10 @@ IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest,
IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest, TestGetAssertion) {
for (const auto protocol : kAllProtocols) {
- device::test::ScopedVirtualFidoDevice virtual_device;
- virtual_device.SetSupportedProtocol(protocol);
+ auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
+ virtual_device_factory->SetSupportedProtocol(protocol);
auto get_assertion_request_params = BuildBasicGetOptions();
- ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ ASSERT_TRUE(virtual_device_factory->mutable_state()->InjectRegistration(
device::fido_parsing_utils::Materialize(
device::test_data::kTestGetAssertionCredentialId),
get_assertion_request_params->relying_party_id));
@@ -1082,15 +1334,15 @@ IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest, TestGetAssertion) {
IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest,
TestGetAssertionWithNoMatchingKeyHandles) {
for (const auto protocol : kAllProtocols) {
- device::test::ScopedVirtualFidoDevice virtual_device;
- virtual_device.SetSupportedProtocol(protocol);
+ auto* virtual_device_factory = InjectVirtualFidoDeviceFactory();
+ virtual_device_factory->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,
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
get_callback_receiver.status());
}
}
diff --git a/chromium/content/browser/webkit_browsertest.cc b/chromium/content/browser/webkit_browsertest.cc
index bde19649011..eacc310b317 100644
--- a/chromium/content/browser/webkit_browsertest.cc
+++ b/chromium/content/browser/webkit_browsertest.cc
@@ -28,8 +28,8 @@ bool AbortOnEndInterceptor(URLLoaderInterceptor::RequestParams* params) {
"HTTP/1.1 400 This is not OK\n"
"Content-type: text/plain\n";
net::HttpResponseInfo info;
- info.headers = new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length()));
+ info.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(headers));
network::ResourceResponseHead response;
response.headers = info.headers;
response.headers->GetMimeType(&response.mime_type);
diff --git a/chromium/content/browser/webrtc/OWNERS b/chromium/content/browser/webrtc/OWNERS
index 11f9e9d4091..99868f95e87 100644
--- a/chromium/content/browser/webrtc/OWNERS
+++ b/chromium/content/browser/webrtc/OWNERS
@@ -1,11 +1,11 @@
chfremer@chromium.org
-emircan@chromium.org
guidou@chromium.org
tommi@chromium.org
per-file *test*=phoglund@chromium.org
# Original (legacy) owner.
+emircan@chromium.org
mcasas@chromium.org
# COMPONENT: Blink>WebRTC
diff --git a/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc b/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
index 9dc33f77002..1d68345484d 100644
--- a/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
@@ -90,8 +90,45 @@ class WebRtcAudioBrowserTest : public WebRtcContentBrowserTestBase,
base::test::ScopedFeatureList audio_service_features_;
};
+#if defined(OS_MACOSX)
+
+// Flaky on MacOS: http://crbug.com/982421
+#define MAYBE_CanMakeVideoCallAndThenRenegotiateToAudio \
+ DISABLED_CanMakeVideoCallAndThenRenegotiateToAudio
+#define MAYBE_EstablishAudioVideoCallAndEnsureAudioIsPlaying \
+ DISABLED_EstablishAudioVideoCallAndEnsureAudioIsPlaying
+#define MAYBE_EstablishAudioOnlyCallAndEnsureAudioIsPlaying \
+ DISABLED_EstablishAudioOnlyCallAndEnsureAudioIsPlaying
+#define MAYBE_EstablishIsac16KCallAndEnsureAudioIsPlaying \
+ DISABLED_EstablishIsac16KCallAndEnsureAudioIsPlaying
+#define MAYBE_EnsureLocalVideoMuteDoesntMuteAudio \
+ DISABLED_EnsureLocalVideoMuteDoesntMuteAudio
+#define MAYBE_EnsureRemoteVideoMuteDoesntMuteAudio \
+ DISABLED_EnsureRemoteVideoMuteDoesntMuteAudio
+#define MAYBE_EstablishAudioVideoCallAndVerifyUnmutingWorks \
+ DISABLED_EstablishAudioVideoCallAndVerifyUnmutingWorks
+
+#else
+
+#define MAYBE_CanMakeVideoCallAndThenRenegotiateToAudio \
+ CanMakeVideoCallAndThenRenegotiateToAudio
+#define MAYBE_EstablishAudioVideoCallAndEnsureAudioIsPlaying \
+ EstablishAudioVideoCallAndEnsureAudioIsPlaying
+#define MAYBE_EstablishAudioOnlyCallAndEnsureAudioIsPlaying \
+ EstablishAudioOnlyCallAndEnsureAudioIsPlaying
+#define MAYBE_EstablishIsac16KCallAndEnsureAudioIsPlaying \
+ EstablishIsac16KCallAndEnsureAudioIsPlaying
+#define MAYBE_EnsureLocalVideoMuteDoesntMuteAudio \
+ EnsureLocalVideoMuteDoesntMuteAudio
+#define MAYBE_EnsureRemoteVideoMuteDoesntMuteAudio \
+ EnsureRemoteVideoMuteDoesntMuteAudio
+#define MAYBE_EstablishAudioVideoCallAndVerifyUnmutingWorks \
+ EstablishAudioVideoCallAndVerifyUnmutingWorks
+
+#endif // defined(OS_MACOSX)
+
IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
- CanMakeVideoCallAndThenRenegotiateToAudio) {
+ MAYBE_CanMakeVideoCallAndThenRenegotiateToAudio) {
std::string constraints =
BuildConstraints(kAudioConstraints, kVideoConstraints);
std::string audio_only_constraints = BuildConstraints(kAudioConstraints, "");
@@ -101,7 +138,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
}
IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
- EstablishAudioVideoCallAndEnsureAudioIsPlaying) {
+ MAYBE_EstablishAudioVideoCallAndEnsureAudioIsPlaying) {
std::string constraints =
BuildConstraints(kAudioConstraints, kVideoConstraints);
MakeAudioDetectingPeerConnectionCall("callAndEnsureAudioIsPlaying(" +
@@ -109,7 +146,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
}
IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
- EstablishAudioOnlyCallAndEnsureAudioIsPlaying) {
+ MAYBE_EstablishAudioOnlyCallAndEnsureAudioIsPlaying) {
std::string constraints =
BuildConstraints(kAudioConstraints, kVideoConstraints);
MakeAudioDetectingPeerConnectionCall("callAndEnsureAudioIsPlaying(" +
@@ -117,7 +154,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
}
IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
- EstablishIsac16KCallAndEnsureAudioIsPlaying) {
+ MAYBE_EstablishIsac16KCallAndEnsureAudioIsPlaying) {
std::string constraints =
BuildConstraints(kAudioConstraints, kVideoConstraints);
MakeAudioDetectingPeerConnectionCall(
@@ -141,7 +178,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
}
IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
- EnsureLocalVideoMuteDoesntMuteAudio) {
+ MAYBE_EnsureLocalVideoMuteDoesntMuteAudio) {
std::string constraints =
BuildConstraints(kAudioConstraints, kVideoConstraints);
MakeAudioDetectingPeerConnectionCall(
@@ -149,7 +186,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
}
IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
- EnsureRemoteVideoMuteDoesntMuteAudio) {
+ MAYBE_EnsureRemoteVideoMuteDoesntMuteAudio) {
std::string constraints =
BuildConstraints(kAudioConstraints, kVideoConstraints);
MakeAudioDetectingPeerConnectionCall(
@@ -157,14 +194,14 @@ IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
}
IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
- EstablishAudioVideoCallAndVerifyUnmutingWorks) {
+ MAYBE_EstablishAudioVideoCallAndVerifyUnmutingWorks) {
std::string constraints =
BuildConstraints(kAudioConstraints, kVideoConstraints);
MakeAudioDetectingPeerConnectionCall("callAndEnsureAudioTrackUnmutingWorks(" +
constraints + ");");
}
-// We run these tests with the audio service both in and out of the the browser
+// We run these tests with the audio service both in and out of 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)
diff --git a/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc b/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
index 1702155e133..a9cbde1694e 100644
--- a/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
@@ -152,16 +152,10 @@ IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest,
kCanvasCaptureColorTestHtmlFile);
}
-// See https://crbug.com/898286.
-#if defined(OS_ANDROID)
-#define MAYBE_CaptureFromOpaqueCanvas2DHandlesContextLoss \
- DISABLED_CaptureFromOpaqueCanvas2DHandlesContextLoss
-#else
-#define MAYBE_CaptureFromOpaqueCanvas2DHandlesContextLoss \
- CaptureFromOpaqueCanvas2DHandlesContextLoss
-#endif
+// Not supported on android https://crbug.com/898286.
+// Not supported on accelerated canvases https://crbug.com/954142.
IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest,
- MAYBE_CaptureFromOpaqueCanvas2DHandlesContextLoss) {
+ DISABLED_CaptureFromOpaqueCanvas2DHandlesContextLoss) {
MakeTypicalCall("testCanvas2DContextLoss(false);",
kCanvasCaptureColorTestHtmlFile);
}
diff --git a/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
index 818311f0f73..d2767b3cce9 100644
--- a/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -756,9 +756,8 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
}
// Flaky on Win, see https://crbug.com/915135
-// Flaky on tsan and asan with accelerated canvases,
-// see https://crbug.com/952381
-#if defined(OS_WIN) || defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
+// Flaky on Linux, see https://crbug.com/952381
+#if defined(OS_WIN) || defined(OS_LINUX)
#define MAYBE_ApplyConstraintsNonDevice DISABLED_ApplyConstraintsNonDevice
#else
#define MAYBE_ApplyConstraintsNonDevice ApplyConstraintsNonDevice
diff --git a/chromium/content/browser/webrtc/webrtc_image_capture_browsertest.cc b/chromium/content/browser/webrtc/webrtc_image_capture_browsertest.cc
index 7137b79784f..ca2a8dcddfc 100644
--- a/chromium/content/browser/webrtc/webrtc_image_capture_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_image_capture_browsertest.cc
@@ -23,28 +23,20 @@
namespace content {
+// Disable FocusDistance test which fails with Logitec cameras.
+// TODO(crbug.com/957020): renable these tests when we have a way to detect
+// which device is connected and hence avoid running it if the camera is
+// Logitech.
+#define MAYBE_ManipulateFocusDistance DISABLED_ManipulateFocusDistance
+
#if defined(OS_ANDROID)
-// TODO(chfremer): Re-enable test on Android as soon as the cause for
-// https://crbug.com/793859 is understood and fixed.
-#define MAYBE_GetPhotoCapabilities GetPhotoCapabilities
-#define MAYBE_GetPhotoSettings GetPhotoSettings
-#define MAYBE_TakePhoto TakePhoto
-#define MAYBE_GrabFrame GrabFrame
-#define MAYBE_GetTrackCapabilities GetTrackCapabilities
-#define MAYBE_GetTrackSettings GetTrackSettings
+// TODO(crbug.com/793859): Re-enable test on Android as soon as the cause for
+// the bug is understood and fixed.
#define MAYBE_ManipulateZoom DISABLED_ManipulateZoom
#define MAYBE_ManipulateExposureTime DISABLED_ManipulateExposureTime
-#define MAYBE_ManipulateFocusDistance DISABLED_ManipulateFocusDistance
#else
-#define MAYBE_GetPhotoCapabilities GetPhotoCapabilities
-#define MAYBE_GetPhotoSettings GetPhotoSettings
-#define MAYBE_TakePhoto TakePhoto
-#define MAYBE_GrabFrame GrabFrame
-#define MAYBE_GetTrackCapabilities GetTrackCapabilities
-#define MAYBE_GetTrackSettings GetTrackSettings
#define MAYBE_ManipulateZoom ManipulateZoom
#define MAYBE_ManipulateExposureTime ManipulateExposureTime
-#define MAYBE_ManipulateFocusDistance ManipulateFocusDistance
#endif
namespace {
@@ -171,18 +163,6 @@ class WebRtcImageCaptureSucceedsBrowserTest
}
}
- bool RunImageCaptureTestCase(const std::string& command) override {
- // TODO(chfremer): Enable test cases using the video capture service with
- // real cameras as soon as root cause for https://crbug.com/733582 is
- // understood and resolved.
- if ((std::get<0>(GetParam()) == TargetCamera::REAL_WEBCAM) &&
- (std::get<1>(GetParam()).use_video_capture_service)) {
- LOG(INFO) << "Skipping this test case";
- return true;
- }
- return WebRtcImageCaptureBrowserTestBase::RunImageCaptureTestCase(command);
- }
-
private:
base::test::ScopedFeatureList scoped_feature_list_;
@@ -190,37 +170,37 @@ class WebRtcImageCaptureSucceedsBrowserTest
};
IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureSucceedsBrowserTest,
- MAYBE_GetPhotoCapabilities) {
+ GetPhotoCapabilities) {
embedded_test_server()->StartAcceptingConnections();
ASSERT_TRUE(
RunImageCaptureTestCase("testCreateAndGetPhotoCapabilitiesSucceeds()"));
}
IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureSucceedsBrowserTest,
- MAYBE_GetPhotoSettings) {
+ GetPhotoSettings) {
embedded_test_server()->StartAcceptingConnections();
ASSERT_TRUE(
RunImageCaptureTestCase("testCreateAndGetPhotoSettingsSucceeds()"));
}
-IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureSucceedsBrowserTest, MAYBE_TakePhoto) {
+IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureSucceedsBrowserTest, TakePhoto) {
embedded_test_server()->StartAcceptingConnections();
ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndTakePhotoSucceeds()"));
}
-IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureSucceedsBrowserTest, MAYBE_GrabFrame) {
+IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureSucceedsBrowserTest, GrabFrame) {
embedded_test_server()->StartAcceptingConnections();
ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndGrabFrameSucceeds()"));
}
IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureSucceedsBrowserTest,
- MAYBE_GetTrackCapabilities) {
+ GetTrackCapabilities) {
embedded_test_server()->StartAcceptingConnections();
ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndGetTrackCapabilities()"));
}
IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureSucceedsBrowserTest,
- MAYBE_GetTrackSettings) {
+ GetTrackSettings) {
embedded_test_server()->StartAcceptingConnections();
ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndGetTrackSettings()"));
}
diff --git a/chromium/content/browser/webrtc/webrtc_internals_ui.cc b/chromium/content/browser/webrtc/webrtc_internals_ui.cc
index ea7d20f6d43..cb45023d62d 100644
--- a/chromium/content/browser/webrtc/webrtc_internals_ui.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals_ui.cc
@@ -21,7 +21,6 @@ WebUIDataSource* CreateWebRTCInternalsHTMLSource() {
source->SetJsonPath("strings.js");
source->AddResourcePath("webrtc_internals.js", IDR_WEBRTC_INTERNALS_JS);
source->SetDefaultResource(IDR_WEBRTC_INTERNALS_HTML);
- source->UseGzip();
return source;
}
diff --git a/chromium/content/browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc b/chromium/content/browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc
index 77c35f1e0f9..bb47bd472ad 100644
--- a/chromium/content/browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc
@@ -16,6 +16,8 @@
#include "services/service_manager/public/cpp/connector.h"
#include "services/video_capture/public/cpp/mock_receiver.h"
#include "services/video_capture/public/mojom/constants.mojom.h"
+#include "services/video_capture/public/mojom/device.mojom.h"
+#include "services/video_capture/public/mojom/device_factory.mojom.h"
#include "services/video_capture/public/mojom/device_factory_provider.mojom.h"
#include "services/video_capture/public/mojom/video_source.mojom.h"
#include "services/video_capture/public/mojom/video_source_provider.mojom.h"
@@ -31,6 +33,26 @@ namespace content {
namespace {
+enum class ServiceApi { kSingleClient, kMultiClient };
+
+struct TestParams {
+ ServiceApi api_to_use;
+ media::VideoCaptureBufferType buffer_type_to_request;
+
+ media::mojom::VideoBufferHandle::Tag GetExpectedBufferHandleTag() const {
+ switch (buffer_type_to_request) {
+ case media::VideoCaptureBufferType::kSharedMemory:
+ return media::mojom::VideoBufferHandle::Tag::SHARED_BUFFER_HANDLE;
+ case media::VideoCaptureBufferType::kSharedMemoryViaRawFileDescriptor:
+ return media::mojom::VideoBufferHandle::Tag::
+ SHARED_MEMORY_VIA_RAW_FILE_DESCRIPTOR;
+ case media::VideoCaptureBufferType::kMailboxHolder:
+ NOTREACHED();
+ return media::mojom::VideoBufferHandle::Tag::SHARED_BUFFER_HANDLE;
+ }
+ }
+};
+
static const char kVideoCaptureHtmlFile[] = "/media/video_capture_test.html";
static const char kStartVideoCaptureAndVerify[] =
"startVideoCaptureAndVerifySize(%d, %d)";
@@ -43,7 +65,9 @@ static const gfx::Size kVideoSize(320, 200);
// opens the device from clients. One client is the test calling into the
// video capture service directly. The second client is the Browser, which the
// test exercises through JavaScript.
-class WebRtcVideoCaptureSharedDeviceBrowserTest : public ContentBrowserTest {
+class WebRtcVideoCaptureSharedDeviceBrowserTest
+ : public ContentBrowserTest,
+ public testing::WithParamInterface<TestParams> {
public:
WebRtcVideoCaptureSharedDeviceBrowserTest() : weak_factory_(this) {
scoped_feature_list_.InitAndEnableFeature(features::kMojoVideoCapture);
@@ -51,18 +75,25 @@ class WebRtcVideoCaptureSharedDeviceBrowserTest : public ContentBrowserTest {
~WebRtcVideoCaptureSharedDeviceBrowserTest() override {}
- void OpenDeviceViaService(
- media::VideoCaptureBufferType buffer_type_to_request,
- base::OnceClosure done_cb) {
+ void OpenDeviceViaService() {
connector_->BindInterface(video_capture::mojom::kServiceName,
&device_factory_provider_);
- device_factory_provider_->ConnectToVideoSourceProvider(
- mojo::MakeRequest(&video_source_provider_));
-
- video_source_provider_->GetSourceInfos(base::BindOnce(
- &WebRtcVideoCaptureSharedDeviceBrowserTest::OnSourceInfosReceived,
- weak_factory_.GetWeakPtr(), buffer_type_to_request,
- std::move(done_cb)));
+ switch (GetParam().api_to_use) {
+ case ServiceApi::kSingleClient:
+ device_factory_provider_->ConnectToDeviceFactory(
+ mojo::MakeRequest(&device_factory_));
+ device_factory_->GetDeviceInfos(base::BindOnce(
+ &WebRtcVideoCaptureSharedDeviceBrowserTest::OnDeviceInfosReceived,
+ weak_factory_.GetWeakPtr(), GetParam().buffer_type_to_request));
+ break;
+ case ServiceApi::kMultiClient:
+ device_factory_provider_->ConnectToVideoSourceProvider(
+ mojo::MakeRequest(&video_source_provider_));
+ video_source_provider_->GetSourceInfos(base::BindOnce(
+ &WebRtcVideoCaptureSharedDeviceBrowserTest::OnSourceInfosReceived,
+ weak_factory_.GetWeakPtr(), GetParam().buffer_type_to_request));
+ break;
+ }
}
void OpenDeviceInRendererAndWaitForPlaying() {
@@ -112,9 +143,35 @@ class WebRtcVideoCaptureSharedDeviceBrowserTest : public ContentBrowserTest {
std::unique_ptr<video_capture::MockReceiver> mock_receiver_;
private:
+ void OnDeviceInfosReceived(
+ media::VideoCaptureBufferType buffer_type_to_request,
+ const std::vector<media::VideoCaptureDeviceInfo>& infos) {
+ ASSERT_FALSE(infos.empty());
+ device_factory_->CreateDevice(
+ infos[0].descriptor.device_id, mojo::MakeRequest(&device_),
+ base::BindOnce(
+ &WebRtcVideoCaptureSharedDeviceBrowserTest::OnCreateDeviceCallback,
+ weak_factory_.GetWeakPtr(), infos, buffer_type_to_request));
+ }
+
+ void OnCreateDeviceCallback(
+ const std::vector<media::VideoCaptureDeviceInfo>& infos,
+ media::VideoCaptureBufferType buffer_type_to_request,
+ video_capture::mojom::DeviceAccessResultCode result_code) {
+ ASSERT_EQ(video_capture::mojom::DeviceAccessResultCode::SUCCESS,
+ result_code);
+
+ media::VideoCaptureParams requestable_settings;
+ ASSERT_FALSE(infos[0].supported_formats.empty());
+ requestable_settings.requested_format = infos[0].supported_formats[0];
+ requestable_settings.requested_format.frame_size = kVideoSize;
+ requestable_settings.buffer_type = buffer_type_to_request;
+
+ device_->Start(requestable_settings, std::move(receiver_proxy_));
+ }
+
void OnSourceInfosReceived(
media::VideoCaptureBufferType buffer_type_to_request,
- base::OnceClosure done_cb,
const std::vector<media::VideoCaptureDeviceInfo>& infos) {
ASSERT_FALSE(infos.empty());
video_source_provider_->GetVideoSource(infos[0].descriptor.device_id,
@@ -133,24 +190,29 @@ class WebRtcVideoCaptureSharedDeviceBrowserTest : public ContentBrowserTest {
mojo::MakeRequest(&subscription_),
base::BindOnce(&WebRtcVideoCaptureSharedDeviceBrowserTest::
OnCreatePushSubscriptionCallback,
- weak_factory_.GetWeakPtr(), std::move(done_cb)));
+ weak_factory_.GetWeakPtr()));
}
void OnCreatePushSubscriptionCallback(
- base::OnceClosure done_cb,
video_capture::mojom::CreatePushSubscriptionResultCode result_code,
const media::VideoCaptureParams& params) {
ASSERT_NE(video_capture::mojom::CreatePushSubscriptionResultCode::kFailed,
result_code);
subscription_->Activate();
- std::move(done_cb).Run();
}
base::test::ScopedFeatureList scoped_feature_list_;
video_capture::mojom::DeviceFactoryProviderPtr device_factory_provider_;
+
+ // For single-client API case only
+ video_capture::mojom::DeviceFactoryPtr device_factory_;
+ video_capture::mojom::DevicePtr device_;
+
+ // For multi-client API case only
video_capture::mojom::VideoSourceProviderPtr video_source_provider_;
video_capture::mojom::VideoSourcePtr video_source_;
video_capture::mojom::PushVideoStreamSubscriptionPtr subscription_;
+
video_capture::mojom::ReceiverPtr receiver_proxy_;
base::WeakPtrFactory<WebRtcVideoCaptureSharedDeviceBrowserTest> weak_factory_;
@@ -160,18 +222,18 @@ class WebRtcVideoCaptureSharedDeviceBrowserTest : public ContentBrowserTest {
// Tests that a single fake video capture device can be opened via JavaScript
// by the Renderer while it is already in use by a direct client of the
// video capture service.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
WebRtcVideoCaptureSharedDeviceBrowserTest,
ReceiveFrameInRendererWhileDeviceAlreadyInUseViaDirectServiceClient) {
Initialize();
base::RunLoop receive_frame_from_service_wait_loop;
+ auto expected_buffer_handle_tag = GetParam().GetExpectedBufferHandleTag();
ON_CALL(*mock_receiver_, DoOnNewBuffer(_, _))
.WillByDefault(Invoke(
- [](int32_t, media::mojom::VideoBufferHandlePtr* buffer_handle) {
- ASSERT_EQ(
- media::mojom::VideoBufferHandle::Tag::SHARED_BUFFER_HANDLE,
- (*buffer_handle)->which());
+ [expected_buffer_handle_tag](
+ int32_t, media::mojom::VideoBufferHandlePtr* buffer_handle) {
+ ASSERT_EQ(expected_buffer_handle_tag, (*buffer_handle)->which());
}));
EXPECT_CALL(*mock_receiver_, DoOnFrameReadyInBuffer(_, _, _, _))
.WillOnce(InvokeWithoutArgs([&receive_frame_from_service_wait_loop]() {
@@ -179,68 +241,30 @@ IN_PROC_BROWSER_TEST_F(
}))
.WillRepeatedly(Return());
- base::RunLoop open_device_via_service_run_loop;
- OpenDeviceViaService(media::VideoCaptureBufferType::kSharedMemory,
- open_device_via_service_run_loop.QuitClosure());
- open_device_via_service_run_loop.Run();
-
- OpenDeviceInRendererAndWaitForPlaying();
-
+ OpenDeviceViaService();
+ // Note, if we do not wait for the first frame to arrive before opening the
+ // device in the Renderer, it could happen that the Renderer takes ove access
+ // to the device before a first frame is received by mock_receiver_.
receive_frame_from_service_wait_loop.Run();
-}
-
-#if defined(OS_LINUX)
-
-// Tests that a single fake video capture device can be opened via JavaScript
-// by the Renderer while it is already in use by a direct client of the
-// video capture service that requested to get buffers as raw file handles.
-IN_PROC_BROWSER_TEST_F(
- WebRtcVideoCaptureSharedDeviceBrowserTest,
- ReceiveFrameInRendererWhileDeviceAlreadyInUseUsingRawFileHandleBuffers) {
- Initialize();
-
- base::RunLoop receive_frame_from_service_wait_loop;
- ON_CALL(*mock_receiver_, DoOnNewBuffer(_, _))
- .WillByDefault(Invoke(
- [](int32_t, media::mojom::VideoBufferHandlePtr* buffer_handle) {
- ASSERT_EQ(media::mojom::VideoBufferHandle::Tag::
- SHARED_MEMORY_VIA_RAW_FILE_DESCRIPTOR,
- (*buffer_handle)->which());
- }));
- EXPECT_CALL(*mock_receiver_, DoOnFrameReadyInBuffer(_, _, _, _))
- .WillOnce(InvokeWithoutArgs([&receive_frame_from_service_wait_loop]() {
- receive_frame_from_service_wait_loop.Quit();
- }))
- .WillRepeatedly(Return());
-
- base::RunLoop open_device_via_service_run_loop;
- OpenDeviceViaService(
- media::VideoCaptureBufferType::kSharedMemoryViaRawFileDescriptor,
- open_device_via_service_run_loop.QuitClosure());
- open_device_via_service_run_loop.Run();
OpenDeviceInRendererAndWaitForPlaying();
-
- receive_frame_from_service_wait_loop.Run();
}
// Tests that a single fake video capture device can be opened by a direct
-// client of the video capture service that requests to get buffers as raw
-// file handles while it is already in use via JavaScript by the Renderer.
-IN_PROC_BROWSER_TEST_F(
+// client of the video capture service while it is already in use via JavaScript
+// by the Renderer.
+IN_PROC_BROWSER_TEST_P(
WebRtcVideoCaptureSharedDeviceBrowserTest,
- ReceiveFrameFromServiceViaRawFileHandlesWhileDeviceAlreadyInUseByRenderer) {
+ ReceiveFrameViaDirectServiceClientWhileDeviceAlreadyInUseViaRenderer) {
Initialize();
- OpenDeviceInRendererAndWaitForPlaying();
-
base::RunLoop receive_frame_from_service_wait_loop;
+ auto expected_buffer_handle_tag = GetParam().GetExpectedBufferHandleTag();
ON_CALL(*mock_receiver_, DoOnNewBuffer(_, _))
.WillByDefault(Invoke(
- [](int32_t, media::mojom::VideoBufferHandlePtr* buffer_handle) {
- ASSERT_EQ(media::mojom::VideoBufferHandle::Tag::
- SHARED_MEMORY_VIA_RAW_FILE_DESCRIPTOR,
- (*buffer_handle)->which());
+ [expected_buffer_handle_tag](
+ int32_t, media::mojom::VideoBufferHandlePtr* buffer_handle) {
+ ASSERT_EQ(expected_buffer_handle_tag, (*buffer_handle)->which());
}));
EXPECT_CALL(*mock_receiver_, DoOnFrameReadyInBuffer(_, _, _, _))
.WillOnce(InvokeWithoutArgs([&receive_frame_from_service_wait_loop]() {
@@ -248,15 +272,31 @@ IN_PROC_BROWSER_TEST_F(
}))
.WillRepeatedly(Return());
- base::RunLoop open_device_via_service_run_loop;
- OpenDeviceViaService(
- media::VideoCaptureBufferType::kSharedMemoryViaRawFileDescriptor,
- open_device_via_service_run_loop.QuitClosure());
- open_device_via_service_run_loop.Run();
+ OpenDeviceInRendererAndWaitForPlaying();
+ OpenDeviceViaService();
receive_frame_from_service_wait_loop.Run();
}
+INSTANTIATE_TEST_SUITE_P(
+ ,
+ WebRtcVideoCaptureSharedDeviceBrowserTest,
+ ::testing::Values(
+ TestParams{ServiceApi::kSingleClient,
+ media::VideoCaptureBufferType::kSharedMemory},
+ TestParams {
+ ServiceApi::kMultiClient, media::VideoCaptureBufferType::kSharedMemory
+ }
+#if defined(OS_LINUX)
+ ,
+ TestParams{
+ ServiceApi::kSingleClient,
+ media::VideoCaptureBufferType::kSharedMemoryViaRawFileDescriptor},
+ TestParams {
+ ServiceApi::kMultiClient,
+ media::VideoCaptureBufferType::kSharedMemoryViaRawFileDescriptor
+ }
#endif // defined(OS_LINUX)
+ ));
} // namespace content
diff --git a/chromium/content/browser/websockets/websocket_handshake_request_info_impl.cc b/chromium/content/browser/websockets/websocket_handshake_request_info_impl.cc
index 13b7761fd54..8422ba07f91 100644
--- a/chromium/content/browser/websockets/websocket_handshake_request_info_impl.cc
+++ b/chromium/content/browser/websockets/websocket_handshake_request_info_impl.cc
@@ -31,15 +31,15 @@ void WebSocketHandshakeRequestInfoImpl::CreateInfoAndAssociateWithRequest(
child_id, render_frame_id)));
}
-int WebSocketHandshakeRequestInfoImpl::GetChildId() const {
+int WebSocketHandshakeRequestInfoImpl::GetChildId() {
return child_id_;
}
-int WebSocketHandshakeRequestInfoImpl::GetRenderFrameId() const {
+int WebSocketHandshakeRequestInfoImpl::GetRenderFrameId() {
return render_frame_id_;
}
-const WebSocketHandshakeRequestInfo* WebSocketHandshakeRequestInfo::ForRequest(
+WebSocketHandshakeRequestInfo* WebSocketHandshakeRequestInfo::ForRequest(
const net::URLRequest* request) {
return static_cast<WebSocketHandshakeRequestInfoImpl*>(
request->GetUserData(&g_tag));
diff --git a/chromium/content/browser/websockets/websocket_handshake_request_info_impl.h b/chromium/content/browser/websockets/websocket_handshake_request_info_impl.h
index 2a3ed3160e5..97ddb37be75 100644
--- a/chromium/content/browser/websockets/websocket_handshake_request_info_impl.h
+++ b/chromium/content/browser/websockets/websocket_handshake_request_info_impl.h
@@ -22,8 +22,8 @@ class WebSocketHandshakeRequestInfoImpl final
int render_frame_id,
net::URLRequest* request);
- int GetChildId() const override;
- int GetRenderFrameId() const override;
+ int GetChildId() override;
+ int GetRenderFrameId() override;
private:
WebSocketHandshakeRequestInfoImpl(int child_id, int render_frame_id);
diff --git a/chromium/content/browser/websockets/websocket_manager.cc b/chromium/content/browser/websockets/websocket_manager.cc
index d7f72559e80..ebe947e7ad3 100644
--- a/chromium/content/browser/websockets/websocket_manager.cc
+++ b/chromium/content/browser/websockets/websocket_manager.cc
@@ -57,13 +57,14 @@ class WebSocketManager::Delegate final : public network::WebSocket::Delegate {
const GURL& url,
int child_id,
int frame_id,
+ int net_error,
const net::SSLInfo& ssl_info,
bool fatal) override {
ssl_error_handler_delegate_ =
std::make_unique<SSLErrorHandlerDelegate>(std::move(callbacks));
SSLManager::OnSSLCertificateSubresourceError(
ssl_error_handler_delegate_->GetWeakPtr(), url, child_id, frame_id,
- ssl_info, fatal);
+ net_error, ssl_info, fatal);
}
void ReportBadMessage(BadMessageReason reason,
diff --git a/chromium/content/browser/webui/shared_resources_data_source.cc b/chromium/content/browser/webui/shared_resources_data_source.cc
index 4d99ada9dc1..cce93419019 100644
--- a/chromium/content/browser/webui/shared_resources_data_source.cc
+++ b/chromium/content/browser/webui/shared_resources_data_source.cc
@@ -15,6 +15,8 @@
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
#include "build/build_config.h"
+#include "content/grit/content_resources.h"
+#include "content/grit/content_resources_map.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
@@ -41,11 +43,7 @@ namespace content {
namespace {
-struct IdrGzipped {
- int idr;
- bool gzipped;
-};
-using ResourcesMap = std::unordered_map<std::string, IdrGzipped>;
+using ResourcesMap = std::unordered_map<std::string, int>;
#if defined(OS_CHROMEOS)
const char kPolymerHtml[] = "polymer/v1_0/polymer/polymer.html";
@@ -58,8 +56,7 @@ const char kHtmlImportsV0Js[] =
// Utility for determining if both Polymer 1 and Polymer 2 are needed.
bool UsingMultiplePolymerVersions() {
- return base::FeatureList::IsEnabled(features::kWebUIPolymer2) &&
- base::FeatureList::IsEnabled(features::kWebUIPolymer2Exceptions);
+ return base::FeatureList::IsEnabled(features::kWebUIPolymer2Exceptions);
}
#endif // defined(OS_CHROMEOS)
@@ -69,6 +66,8 @@ const std::map<std::string, std::string> CreatePathPrefixAliasesMap() {
std::map<std::string, std::string> aliases = {
{"../../../third_party/polymer/v1_0/components-chromium/",
"polymer/v1_0/"},
+ {"../../../third_party/polymer/v3_0/components-chromium/",
+ "polymer/v3_0/"},
{"../../../third_party/web-animations-js/sources/",
"polymer/v1_0/web-animations-js/"},
{"../../views/resources/default_100_percent/common/", "images/apps/"},
@@ -83,26 +82,48 @@ const std::map<std::string, std::string> CreatePathPrefixAliasesMap() {
#endif // defined(OS_CHROMEOS)
#if !defined(OS_ANDROID)
- if (base::FeatureList::IsEnabled(features::kWebUIPolymer2)) {
- aliases["../../../third_party/polymer/v1_0/components-chromium/polymer2/"] =
- "polymer/v1_0/polymer/";
- } else {
- aliases
- ["../../../third_party/polymer/v1_0/components-chromium/"
- "html-imports-v0/"] = "polymer/v1_0/html-imports/";
- }
+ aliases["../../../third_party/polymer/v1_0/components-chromium/polymer2/"] =
+ "polymer/v1_0/polymer/";
#endif // !defined(OS_ANDROID)
return aliases;
}
+const std::map<int, std::string> CreateContentResourceIdToAliasMap() {
+ return std::map<int, std::string>{
+ {IDR_ORIGIN_MOJO_HTML, "mojo/url/mojom/origin.mojom.html"},
+ {IDR_ORIGIN_MOJO_JS, "mojo/url/mojom/origin.mojom-lite.js"},
+ {IDR_UNGUESSABLE_TOKEN_MOJO_HTML,
+ "mojo/mojo/public/mojom/base/unguessable_token.mojom.html"},
+ {IDR_UNGUESSABLE_TOKEN_MOJO_JS,
+ "mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js"},
+ {IDR_URL_MOJO_HTML, "mojo/url/mojom/url.mojom.html"},
+ {IDR_URL_MOJO_JS, "mojo/url/mojom/url.mojom-lite.js"},
+ };
+}
+
const std::map<int, std::string> CreateMojoResourceIdToAliasMap() {
return std::map<int, std::string> {
- {IDR_MOJO_MOJO_BINDINGS_LITE_JS, "js/mojo_bindings_lite.js"},
- {IDR_MOJO_BIG_BUFFER_MOJOM_LITE_JS, "js/big_buffer.mojom-lite.js"},
- {IDR_MOJO_FILE_MOJOM_LITE_JS, "js/file.mojom-lite.js"},
- {IDR_MOJO_STRING16_MOJOM_LITE_JS, "js/string16.mojom-lite.js"},
+ {IDR_MOJO_MOJO_BINDINGS_LITE_HTML,
+ "mojo/mojo/public/js/mojo_bindings_lite.html"},
+ {IDR_MOJO_MOJO_BINDINGS_LITE_JS,
+ "mojo/mojo/public/js/mojo_bindings_lite.js"},
+ {IDR_MOJO_BIG_BUFFER_MOJOM_HTML,
+ "mojo/mojo/public/mojom/base/big_buffer.mojom.html"},
+ {IDR_MOJO_BIG_BUFFER_MOJOM_LITE_JS,
+ "mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js"},
+ {IDR_MOJO_FILE_MOJOM_HTML,
+ "mojo/mojo/public/mojom/base/file.mojom.html"},
+ {IDR_MOJO_FILE_MOJOM_LITE_JS,
+ "mojo/mojo/public/mojom/base/file.mojom-lite.js"},
+ {IDR_MOJO_STRING16_MOJOM_HTML,
+ "mojo/mojo/public/mojom/base/string16.mojom.html"},
+ {IDR_MOJO_STRING16_MOJOM_LITE_JS,
+ "mojo/mojo/public/mojom/base/string16.mojom-lite.js"},
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
- {IDR_MOJO_TIME_MOJOM_LITE_JS, "js/time.mojom-lite.js"},
+ {IDR_MOJO_TIME_MOJOM_HTML,
+ "mojo/mojo/public/mojom/base/time.mojom.html"},
+ {IDR_MOJO_TIME_MOJOM_LITE_JS,
+ "mojo/mojo/public/mojom/base/time.mojom-lite.js"},
#endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
};
}
@@ -110,14 +131,36 @@ const std::map<int, std::string> CreateMojoResourceIdToAliasMap() {
#if defined(OS_CHROMEOS)
const std::map<int, std::string> CreateChromeosMojoResourceIdToAliasMap() {
return std::map<int, std::string>{
+ {IDR_CELLULAR_SETUP_MOJOM_HTML,
+ "mojo/chromeos/services/cellular_setup/public/mojom/"
+ "cellular_setup.mojom.html"},
+ {IDR_CELLULAR_SETUP_MOJOM_LITE_JS,
+ "mojo/chromeos/services/cellular_setup/public/mojom/"
+ "cellular_setup.mojom-lite.js"},
+ {IDR_MULTIDEVICE_DEVICE_SYNC_MOJOM_HTML,
+ "mojo/chromeos/services/device_sync/public/mojom/"
+ "device_sync.mojom.html"},
{IDR_MULTIDEVICE_DEVICE_SYNC_MOJOM_LITE_JS,
- "js/chromeos/device_sync.mojom-lite.js"},
+ "mojo/chromeos/services/device_sync/public/mojom/"
+ "device_sync.mojom-lite.js"},
+ {IDR_MULTIDEVICE_MULTIDEVICE_SETUP_MOJOM_HTML,
+ "mojo/chromeos/services/multidevice_setup/public/mojom/"
+ "multidevice_setup.mojom.html"},
{IDR_MULTIDEVICE_MULTIDEVICE_SETUP_MOJOM_LITE_JS,
- "js/chromeos/multidevice_setup.mojom-lite.js"},
+ "mojo/chromeos/services/multidevice_setup/public/mojom/"
+ "multidevice_setup.mojom-lite.js"},
+ {IDR_MULTIDEVICE_MULTIDEVICE_SETUP_CONSTANTS_MOJOM_HTML,
+ "mojo/chromeos/services/multidevice_setup/public/mojom/"
+ "constants.mojom.html"},
{IDR_MULTIDEVICE_MULTIDEVICE_SETUP_CONSTANTS_MOJOM_LITE_JS,
- "js/chromeos/multidevice_setup_constants.mojom-lite.js"},
+ "mojo/chromeos/services/multidevice_setup/public/mojom/"
+ "constants.mojom-lite.js"},
+ {IDR_MULTIDEVICE_MULTIDEVICE_TYPES_MOJOM_HTML,
+ "mojo/chromeos/components/multidevice/mojom/"
+ "multidevice_types.mojom.html"},
{IDR_MULTIDEVICE_MULTIDEVICE_TYPES_MOJOM_LITE_JS,
- "js/chromeos/multidevice_types.mojom-lite.js"},
+ "mojo/chromeos/components/multidevice/mojom/"
+ "multidevice_types.mojom-lite.js"},
};
}
#endif // !defined(OS_CHROMEOS)
@@ -129,27 +172,14 @@ bool ShouldIgnore(std::string resource) {
return false;
#endif // defined(OS_CHROMEOS)
- if (base::FeatureList::IsEnabled(features::kWebUIPolymer2) &&
- (base::StartsWith(
- resource,
- "../../../third_party/polymer/v1_0/components-chromium/polymer/",
- base::CompareCase::SENSITIVE) ||
- base::StartsWith(resource,
- "../../../third_party/polymer/v1_0/components-chromium/"
- "html-imports-v0/",
- 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) ||
- base::StartsWith(resource,
- "../../../third_party/polymer/v1_0/components-chromium/"
- "html-imports/",
- base::CompareCase::SENSITIVE))) {
+ if (base::StartsWith(
+ resource,
+ "../../../third_party/polymer/v1_0/components-chromium/polymer/",
+ base::CompareCase::SENSITIVE) ||
+ base::StartsWith(resource,
+ "../../../third_party/polymer/v1_0/components-chromium/"
+ "html-imports-v0/",
+ base::CompareCase::SENSITIVE)) {
return true;
}
@@ -159,10 +189,8 @@ bool ShouldIgnore(std::string resource) {
void AddResource(const std::string& path,
int resource_id,
- bool gzipped,
ResourcesMap* resources_map) {
- IdrGzipped idr_gzipped = {resource_id, gzipped};
- if (!resources_map->insert(std::make_pair(path, idr_gzipped)).second)
+ if (!resources_map->insert(std::make_pair(path, resource_id)).second)
NOTREACHED() << "Redefinition of '" << path << "'";
}
@@ -178,14 +206,14 @@ void AddResourcesToMap(ResourcesMap* resources_map) {
continue;
#endif // !defined(OS_ANDROID)
- AddResource(resource.name, resource.value, resource.gzipped, resources_map);
+ AddResource(resource.name, resource.value, resources_map);
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(it->second + resource_name.substr(it->first.length()),
- resource.value, resource.gzipped, resources_map);
+ resource.value, resources_map);
}
}
}
@@ -196,7 +224,7 @@ void AddResourcesToMap(ResourcesMap* resources_map) {
// alias. Note that resources which do not have an alias will not be added.
void AddAliasedResourcesToMap(
const std::map<int, std::string>& resource_aliases,
- const GzippedGritResourceMap resources[],
+ const GritResourceMap resources[],
size_t resources_size,
ResourcesMap* resources_map) {
for (size_t i = 0; i < resources_size; ++i) {
@@ -206,13 +234,15 @@ void AddAliasedResourcesToMap(
if (it == resource_aliases.end())
continue;
- AddResource(it->second, resource.value, resource.gzipped, resources_map);
+ AddResource(it->second, resource.value, resources_map);
}
}
const ResourcesMap* CreateResourcesMap() {
ResourcesMap* result = new ResourcesMap();
AddResourcesToMap(result);
+ AddAliasedResourcesToMap(CreateContentResourceIdToAliasMap(),
+ kContentResources, kContentResourcesSize, result);
AddAliasedResourcesToMap(CreateMojoResourceIdToAliasMap(),
kMojoBindingsResources, kMojoBindingsResourcesSize,
result);
@@ -232,7 +262,7 @@ const ResourcesMap& GetResourcesMap() {
int GetIdrForPath(const std::string& path) {
const ResourcesMap& resources_map = GetResourcesMap();
auto it = resources_map.find(path);
- return it != resources_map.end() ? it->second.idr : -1;
+ return it != resources_map.end() ? it->second : -1;
}
} // namespace
@@ -375,9 +405,7 @@ SharedResourcesDataSource::GetAccessControlAllowOriginForOrigin(
}
bool SharedResourcesDataSource::IsGzipped(const std::string& path) const {
- auto it = GetResourcesMap().find(path);
- DCHECK(it != GetResourcesMap().end()) << "missing shared resource: " << path;
- return it != GetResourcesMap().end() ? it->second.gzipped : false;
+ return GetContentClient()->IsDataResourceGzipped(GetIdrForPath(path));
}
#if defined(OS_CHROMEOS)
diff --git a/chromium/content/browser/webui/url_data_manager_backend_unittest.cc b/chromium/content/browser/webui/url_data_manager_backend_unittest.cc
index f898d9de6e5..ce79d2797eb 100644
--- a/chromium/content/browser/webui/url_data_manager_backend_unittest.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend_unittest.cc
@@ -8,8 +8,10 @@
#include "base/macros.h"
#include "base/run_loop.h"
+#include "content/public/common/url_constants.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -49,8 +51,8 @@ class UrlDataManagerBackendTest : public testing::Test {
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
// URLRequestJobFactory takes ownership of the passed in ProtocolHandler.
url_request_job_factory_.SetProtocolHandler(
- "chrome", URLDataManagerBackend::CreateProtocolHandler(
- &resource_context_, nullptr));
+ kChromeUIScheme, URLDataManagerBackend::CreateProtocolHandler(
+ &resource_context_, nullptr));
url_request_context_.set_job_factory(&url_request_job_factory_);
}
@@ -59,7 +61,7 @@ class UrlDataManagerBackendTest : public testing::Test {
const char* origin) {
std::unique_ptr<net::URLRequest> request =
url_request_context_.CreateRequest(
- GURL("chrome://resources/css/text_defaults.css"), net::HIGHEST,
+ GetWebUIURL("resources/css/text_defaults.css"), net::HIGHEST,
delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
request->SetExtraRequestHeaderByName("Origin", origin, true);
return request;
@@ -75,11 +77,11 @@ class UrlDataManagerBackendTest : public testing::Test {
TEST_F(UrlDataManagerBackendTest, AccessControlAllowOriginChromeUrl) {
std::unique_ptr<net::URLRequest> request(
- CreateRequest(&delegate_, "chrome://webui"));
+ CreateRequest(&delegate_, GetWebUIURLString("webui").c_str()));
request->Start();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(request->response_headers()->HasHeaderValue(
- "Access-Control-Allow-Origin", "chrome://webui"));
+ "Access-Control-Allow-Origin", GetWebUIURLString("webui").c_str()));
}
TEST_F(UrlDataManagerBackendTest, AccessControlAllowOriginNonChromeUrl) {
@@ -94,7 +96,7 @@ TEST_F(UrlDataManagerBackendTest, AccessControlAllowOriginNonChromeUrl) {
// Check that the URLRequest isn't passed headers after cancellation.
TEST_F(UrlDataManagerBackendTest, CancelBeforeResponseStarts) {
std::unique_ptr<net::URLRequest> request(
- CreateRequest(&delegate_, "chrome://webui"));
+ CreateRequest(&delegate_, GetWebUIURLString("webui").c_str()));
request->Start();
request->Cancel();
base::RunLoop().RunUntilIdle();
@@ -106,7 +108,7 @@ TEST_F(UrlDataManagerBackendTest, CancelBeforeResponseStarts) {
TEST_F(UrlDataManagerBackendTest, CancelAfterFirstReadStarted) {
CancelAfterFirstReadURLRequestDelegate cancel_delegate;
std::unique_ptr<net::URLRequest> request(
- CreateRequest(&cancel_delegate, "chrome://webui"));
+ CreateRequest(&cancel_delegate, GetWebUIURLString("webui").c_str()));
request->Start();
base::RunLoop().RunUntilIdle();
@@ -118,7 +120,7 @@ TEST_F(UrlDataManagerBackendTest, CancelAfterFirstReadStarted) {
// Check for a network error page request via chrome://network-error/.
TEST_F(UrlDataManagerBackendTest, ChromeNetworkErrorPageRequest) {
std::unique_ptr<net::URLRequest> error_request =
- url_request_context_.CreateRequest(GURL("chrome://network-error/-105"),
+ url_request_context_.CreateRequest(GetWebUIURL("network-error/-105"),
net::HIGHEST, &delegate_,
TRAFFIC_ANNOTATION_FOR_TESTS);
error_request->Start();
@@ -131,7 +133,7 @@ TEST_F(UrlDataManagerBackendTest, ChromeNetworkErrorPageRequest) {
TEST_F(UrlDataManagerBackendTest, ChromeNetworkErrorPageRequestFailed) {
std::unique_ptr<net::URLRequest> error_request =
url_request_context_.CreateRequest(
- GURL("chrome://network-error/-123456789"), net::HIGHEST, &delegate_,
+ GetWebUIURL("network-error/-123456789"), net::HIGHEST, &delegate_,
TRAFFIC_ANNOTATION_FOR_TESTS);
error_request->Start();
base::RunLoop().Run();
diff --git a/chromium/content/browser/webui/web_ui_data_source_impl.cc b/chromium/content/browser/webui/web_ui_data_source_impl.cc
index 580c0ca24af..789bb88152c 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.cc
@@ -118,8 +118,7 @@ WebUIDataSourceImpl::WebUIDataSourceImpl(const std::string& source_name)
frame_src_set_(false),
deny_xframe_options_(true),
add_load_time_data_defaults_(true),
- replace_existing_source_(true),
- use_gzip_(false) {}
+ replace_existing_source_(true) {}
WebUIDataSourceImpl::~WebUIDataSourceImpl() {
}
@@ -221,16 +220,6 @@ void WebUIDataSourceImpl::DisableDenyXFrameOptions() {
deny_xframe_options_ = false;
}
-void WebUIDataSourceImpl::UseGzip() {
- use_gzip_ = true;
-}
-
-void WebUIDataSourceImpl::UseGzip(
- base::RepeatingCallback<bool(const std::string&)> is_gzipped_callback) {
- UseGzip();
- is_gzipped_callback_ = std::move(is_gzipped_callback);
-}
-
const ui::TemplateReplacements* WebUIDataSourceImpl::GetReplacements() const {
return &replacements_;
}
@@ -295,12 +284,7 @@ void WebUIDataSourceImpl::StartDataRequest(
return;
}
- int resource_id = default_resource_;
- std::map<std::string, int>::iterator result;
- // Remove the query string for named resource lookups.
- result = path_to_idr_map_.find(CleanUpPath(path));
- if (result != path_to_idr_map_.end())
- resource_id = result->second;
+ int resource_id = PathToIdrOrDefault(CleanUpPath(path));
DCHECK_NE(resource_id, -1);
scoped_refptr<base::RefCountedMemory> response(
GetContentClient()->GetDataResourceBytes(resource_id));
@@ -319,9 +303,6 @@ const base::DictionaryValue* WebUIDataSourceImpl::GetLocalizedStrings() const {
}
bool WebUIDataSourceImpl::IsGzipped(const std::string& path) const {
- if (!use_gzip_)
- return false;
-
// Note: In the hypothetical case of requests handled by |filter_callback_|
// that involve gzipped data, the callback itself is responsible for
// ungzipping, and IsGzipped will return false for such cases.
@@ -330,12 +311,22 @@ bool WebUIDataSourceImpl::IsGzipped(const std::string& path) const {
return false;
}
- // TODO(dbeam): does anybody care about the "dirty" path (i.e. stuff after ?).
- const std::string clean_path = CleanUpPath(path);
- if (!json_path_.empty() && clean_path == json_path_)
+ if (!json_path_.empty() && path == json_path_) {
+ return false;
+ }
+
+ std::string file_path = CleanUpPath(path);
+ int idr = PathToIdrOrDefault(file_path);
+ if (idr == -1) {
return false;
+ }
+
+ return GetContentClient()->IsDataResourceGzipped(idr);
+}
- return is_gzipped_callback_.is_null() || is_gzipped_callback_.Run(clean_path);
+int WebUIDataSourceImpl::PathToIdrOrDefault(const std::string& path) const {
+ auto it = path_to_idr_map_.find(path);
+ return it == path_to_idr_map_.end() ? default_resource_ : it->second;
}
} // namespace content
diff --git a/chromium/content/browser/webui/web_ui_data_source_impl.h b/chromium/content/browser/webui/web_ui_data_source_impl.h
index 40278d67aaa..9de2d81886b 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.h
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.h
@@ -50,9 +50,6 @@ class CONTENT_EXPORT WebUIDataSourceImpl : public URLDataSourceImpl,
void OverrideContentSecurityPolicyObjectSrc(const std::string& data) override;
void OverrideContentSecurityPolicyChildSrc(const std::string& data) override;
void DisableDenyXFrameOptions() override;
- void UseGzip() override;
- void UseGzip(base::RepeatingCallback<bool(const std::string&)>
- is_gzipped_callback) override;
std::string GetSource() const override;
// URLDataSourceImpl:
@@ -81,7 +78,8 @@ class CONTENT_EXPORT WebUIDataSourceImpl : public URLDataSourceImpl,
friend class WebUIDataSourceTest;
FRIEND_TEST_ALL_PREFIXES(WebUIDataSourceTest, IsGzipped);
- FRIEND_TEST_ALL_PREFIXES(WebUIDataSourceTest, IsGzippedWithCallback);
+ FRIEND_TEST_ALL_PREFIXES(WebUIDataSourceTest, IsGzippedNoDefaultResource);
+ FRIEND_TEST_ALL_PREFIXES(WebUIDataSourceTest, IsGzippedWithRequestFiltering);
// Methods that match URLDataSource which are called by
// InternalDataSource.
@@ -91,6 +89,8 @@ class CONTENT_EXPORT WebUIDataSourceImpl : public URLDataSourceImpl,
const ResourceRequestInfo::WebContentsGetter& wc_getter,
const URLDataSource::GotDataCallback& callback);
+ int PathToIdrOrDefault(const std::string& path) const;
+
// Note: this must be called before StartDataRequest() to have an effect.
void disable_load_time_data_defaults_for_testing() {
add_load_time_data_defaults_ = false;
@@ -126,8 +126,6 @@ class CONTENT_EXPORT WebUIDataSourceImpl : public URLDataSourceImpl,
bool deny_xframe_options_;
bool add_load_time_data_defaults_;
bool replace_existing_source_;
- bool use_gzip_;
- base::RepeatingCallback<bool(const std::string&)> is_gzipped_callback_;
DISALLOW_COPY_AND_ASSIGN(WebUIDataSourceImpl);
};
diff --git a/chromium/content/browser/webui/web_ui_data_source_unittest.cc b/chromium/content/browser/webui/web_ui_data_source_unittest.cc
index 6c2f7dea2aa..6b6fde807c9 100644
--- a/chromium/content/browser/webui/web_ui_data_source_unittest.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_unittest.cc
@@ -24,7 +24,7 @@ const char kDummyResource[] = "<html>blah</html>";
class TestClient : public TestContentClient {
public:
- TestClient() {}
+ TestClient() : is_gzipped_(false) {}
~TestClient() override {}
base::string16 GetLocalizedString(int message_id) const override {
@@ -45,6 +45,16 @@ class TestClient : public TestContentClient {
}
return bytes;
}
+
+ bool IsDataResourceGzipped(int resource_id) const override {
+ return is_gzipped_;
+ }
+
+ // Sets the response for |IsDataResourceGzipped()|.
+ void SetIsDataResourceGzipped(bool is_gzipped) { is_gzipped_ = is_gzipped; }
+
+ private:
+ bool is_gzipped_;
};
} // namespace
@@ -75,6 +85,7 @@ class WebUIDataSourceTest : public testing::Test {
protected:
std::string request_path_;
+ TestClient client_;
private:
void SetUp() override {
@@ -88,7 +99,6 @@ class WebUIDataSourceTest : public testing::Test {
TestBrowserThreadBundle thread_bundle_;
scoped_refptr<WebUIDataSourceImpl> source_;
- TestClient client_;
};
void EmptyStringsCallback(scoped_refptr<base::RefCountedMemory> data) {
@@ -180,7 +190,8 @@ TEST_F(WebUIDataSourceTest, RequestFilterQueryString) {
request_path_ = std::string();
source()->SetRequestFilter(
base::BindRepeating([](const std::string& path) { return true; }),
- base::Bind(&WebUIDataSourceTest::HandleRequest, base::Unretained(this)));
+ base::BindRepeating(&WebUIDataSourceTest::HandleRequest,
+ base::Unretained(this)));
source()->SetDefaultResource(kDummyDefaultResourceId);
source()->AddResourcePath("foobar", kDummyResourceId);
StartDataRequest(
@@ -217,32 +228,48 @@ TEST_F(WebUIDataSourceTest, MimeType) {
}
TEST_F(WebUIDataSourceTest, IsGzipped) {
+ source()->SetJsonPath("strings.js");
+ source()->SetDefaultResource(kDummyDefaultResourceId);
+
+ // Test that WebUIDataSource delegates IsGzipped to the content client.
+ client_.SetIsDataResourceGzipped(false);
EXPECT_FALSE(source()->IsGzipped("foobar"));
EXPECT_FALSE(source()->IsGzipped(""));
- source()->UseGzip();
+ // Test that |json_path_| is correctly reported as non-gzipped.
+ EXPECT_FALSE(source()->IsGzipped("strings.js"));
+
+ client_.SetIsDataResourceGzipped(true);
EXPECT_TRUE(source()->IsGzipped("foobar"));
EXPECT_TRUE(source()->IsGzipped(""));
+ // Test that |json_path_| is correctly reported as non-gzipped.
+ EXPECT_FALSE(source()->IsGzipped("strings.js"));
}
-TEST_F(WebUIDataSourceTest, IsGzippedWithCallback) {
+TEST_F(WebUIDataSourceTest, IsGzippedNoDefaultResource) {
+ // Test that WebUIDataSource reports non existing resources as non-gzipped
+ // and does not trigger any CHECKs.
+ client_.SetIsDataResourceGzipped(false);
EXPECT_FALSE(source()->IsGzipped("foobar"));
- source()->AddResourcePath("foobar", kDummyResourceId);
- source()->SetDefaultResource(kDummyDefaultResourceId);
- source()->SetJsonPath("strings.js");
- source()->UseGzip(base::BindRepeating(
- [](const std::string& path) { return path != "json/special/path"; }));
+ client_.SetIsDataResourceGzipped(true);
+ EXPECT_FALSE(source()->IsGzipped("foobar"));
+}
- EXPECT_TRUE(source()->IsGzipped("foobar"));
- EXPECT_TRUE(source()->IsGzipped("foobar?query"));
+TEST_F(WebUIDataSourceTest, IsGzippedWithRequestFiltering) {
+ source()->SetRequestFilter(
+ base::BindRepeating(
+ [](const std::string& path) { return path == "json/special/path"; }),
+ base::BindRepeating(&WebUIDataSourceTest::HandleRequest,
+ base::Unretained(this)));
+ source()->SetDefaultResource(kDummyDefaultResourceId);
- EXPECT_TRUE(source()->IsGzipped("unknown_path"));
- EXPECT_TRUE(source()->IsGzipped("unknown_path?query"));
+ client_.SetIsDataResourceGzipped(false);
+ EXPECT_FALSE(source()->IsGzipped("json/special/path"));
+ EXPECT_FALSE(source()->IsGzipped("other/path"));
+ client_.SetIsDataResourceGzipped(true);
EXPECT_FALSE(source()->IsGzipped("json/special/path"));
- EXPECT_FALSE(source()->IsGzipped("json/special/path?query"));
- EXPECT_FALSE(source()->IsGzipped("strings.js"));
- EXPECT_FALSE(source()->IsGzipped("strings.js?query"));
+ EXPECT_TRUE(source()->IsGzipped("other/path"));
}
TEST_F(WebUIDataSourceTest, ShouldServeMimeTypeAsContentTypeHeader) {
diff --git a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
index f94314b8479..a90057166ad 100644
--- a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -34,6 +34,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/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/data/web_ui_test_mojo_bindings.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -264,10 +265,8 @@ class WebUIMojoTest : public ContentBrowserTest {
void NavigateWithNewWebUI(const std::string& path) {
// Load a dummy WebUI URL first so that a new WebUI is set up when we load
// the URL we're actually interested in.
- EXPECT_TRUE(NavigateToURL(shell(), GURL("chrome://dummy-web-ui")));
-
- constexpr char kChromeUIMojoWebUIOrigin[] = "chrome://mojo-web-ui/";
- EXPECT_TRUE(NavigateToURL(shell(), GURL(kChromeUIMojoWebUIOrigin + path)));
+ EXPECT_TRUE(NavigateToURL(shell(), GetWebUIURL("dummy-web-ui")));
+ EXPECT_TRUE(NavigateToURL(shell(), GetWebUIURL("mojo-web-ui/" + path)));
}
// Run |script| and return a boolean result.
@@ -308,7 +307,7 @@ IN_PROC_BROWSER_TEST_F(WebUIMojoTest, EndToEndPing) {
g_got_message = false;
base::RunLoop run_loop;
factory()->set_run_loop(&run_loop);
- GURL test_url("chrome://mojo-web-ui/web_ui_mojo.html?ping");
+ GURL test_url(GetWebUIURL("mojo-web-ui/web_ui_mojo.html?ping"));
NavigateToURL(shell(), test_url);
// RunLoop is quit when message received from page.
run_loop.Run();
diff --git a/chromium/content/browser/worker_host/dedicated_worker_host.cc b/chromium/content/browser/worker_host/dedicated_worker_host.cc
index 9947f430e68..933766f3d9c 100644
--- a/chromium/content/browser/worker_host/dedicated_worker_host.cc
+++ b/chromium/content/browser/worker_host/dedicated_worker_host.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "content/browser/appcache/appcache_navigation_handle.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/interface_provider_filtering.h"
#include "content/browser/renderer_interface_binders.h"
@@ -101,7 +102,7 @@ class DedicatedWorkerHost : public service_manager::mojom::InterfaceProvider {
process_id_, script_url, request_initiator_origin,
ResourceType::kWorker,
storage_partition_impl->GetServiceWorkerContext(),
- appcache_handle_->core(), std::move(blob_url_loader_factory),
+ appcache_handle_->core(), std::move(blob_url_loader_factory), nullptr,
storage_partition_impl,
base::BindOnce(&DedicatedWorkerHost::DidStartScriptLoad,
weak_factory_.GetWeakPtr(), std::move(client)));
@@ -116,6 +117,8 @@ class DedicatedWorkerHost : public service_manager::mojom::InterfaceProvider {
&DedicatedWorkerHost::CreateWebUsbService, base::Unretained(this)));
registry_.AddInterface(base::BindRepeating(
&DedicatedWorkerHost::CreateDedicatedWorker, base::Unretained(this)));
+ registry_.AddInterface(base::BindRepeating(
+ &DedicatedWorkerHost::CreateIdleManager, base::Unretained(this)));
}
// Called from WorkerScriptFetchInitiator. Continues starting the dedicated
@@ -143,8 +146,7 @@ class DedicatedWorkerHost : public service_manager::mojom::InterfaceProvider {
blink::mojom::DedicatedWorkerHostFactoryClientPtr client,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
@@ -252,6 +254,21 @@ class DedicatedWorkerHost : public service_manager::mojom::InterfaceProvider {
origin_, std::move(request));
}
+ void CreateIdleManager(blink::mojom::IdleManagerRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ auto* host =
+ RenderFrameHostImpl::FromID(process_id_, ancestor_render_frame_id_);
+ if (!host->IsFeatureEnabled(
+ blink::mojom::FeaturePolicyFeature::kIdleDetection)) {
+ mojo::ReportBadMessage("Feature policy blocks access to IdleDetection.");
+ return;
+ }
+ static_cast<StoragePartitionImpl*>(
+ host->GetProcess()->GetStoragePartition())
+ ->GetIdleManager()
+ ->CreateService(std::move(request));
+ }
+
const int process_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
diff --git a/chromium/content/browser/worker_host/mock_shared_worker.cc b/chromium/content/browser/worker_host/mock_shared_worker.cc
index da0ad9dd313..ddafdbc2a1a 100644
--- a/chromium/content/browser/worker_host/mock_shared_worker.cc
+++ b/chromium/content/browser/worker_host/mock_shared_worker.cc
@@ -106,9 +106,8 @@ void MockSharedWorkerFactory::CreateSharedWorker(
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- int appcache_host_id,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ const base::Optional<base::UnguessableToken>& appcache_host_id,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
diff --git a/chromium/content/browser/worker_host/mock_shared_worker.h b/chromium/content/browser/worker_host/mock_shared_worker.h
index ea408bcc2c8..4562137da66 100644
--- a/chromium/content/browser/worker_host/mock_shared_worker.h
+++ b/chromium/content/browser/worker_host/mock_shared_worker.h
@@ -81,9 +81,8 @@ class MockSharedWorkerFactory : public blink::mojom::SharedWorkerFactory {
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- int appcache_host_id,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ const base::Optional<base::UnguessableToken>& appcache_host_id,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
diff --git a/chromium/content/browser/worker_host/shared_worker_connector_impl.cc b/chromium/content/browser/worker_host/shared_worker_connector_impl.cc
index 4b410f1384b..fb9aa3bb96f 100644
--- a/chromium/content/browser/worker_host/shared_worker_connector_impl.cc
+++ b/chromium/content/browser/worker_host/shared_worker_connector_impl.cc
@@ -5,6 +5,7 @@
#include "content/browser/worker_host/shared_worker_connector_impl.h"
#include "base/memory/ptr_util.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/worker_host/shared_worker_service_impl.h"
#include "content/public/browser/browser_context.h"
@@ -12,6 +13,7 @@
#include "content/public/browser/render_process_host.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
+#include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h"
#include "third_party/blink/public/mojom/worker/shared_worker_info.mojom.h"
namespace content {
diff --git a/chromium/content/browser/worker_host/shared_worker_host.cc b/chromium/content/browser/worker_host/shared_worker_host.cc
index 798e6ba7f85..96d6821ed91 100644
--- a/chromium/content/browser/worker_host/shared_worker_host.cc
+++ b/chromium/content/browser/worker_host/shared_worker_host.cc
@@ -173,8 +173,7 @@ void SharedWorkerHost::Start(
blink::mojom::SharedWorkerFactoryPtr factory,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
@@ -277,8 +276,9 @@ void SharedWorkerHost::Start(
std::move(info), pause_on_start, devtools_worker_token,
std::move(renderer_preferences), std::move(preference_watcher_request),
std::move(content_settings), std::move(service_worker_provider_info),
- appcache_handle_ ? appcache_handle_->appcache_host_id()
- : blink::mojom::kAppCacheNoHostId,
+ appcache_handle_
+ ? base::make_optional(appcache_handle_->appcache_host_id())
+ : base::nullopt,
std::move(main_script_loader_factory), std::move(main_script_load_params),
std::move(subresource_loader_factories), std::move(controller),
std::move(host), std::move(worker_request_),
diff --git a/chromium/content/browser/worker_host/shared_worker_host.h b/chromium/content/browser/worker_host/shared_worker_host.h
index 4e72cc3e1b9..888d83a1732 100644
--- a/chromium/content/browser/worker_host/shared_worker_host.h
+++ b/chromium/content/browser/worker_host/shared_worker_host.h
@@ -100,8 +100,7 @@ class CONTENT_EXPORT SharedWorkerHost
blink::mojom::SharedWorkerFactoryPtr factory,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
diff --git a/chromium/content/browser/worker_host/shared_worker_host_unittest.cc b/chromium/content/browser/worker_host/shared_worker_host_unittest.cc
index 92e273874af..12052810c15 100644
--- a/chromium/content/browser/worker_host/shared_worker_host_unittest.cc
+++ b/chromium/content/browser/worker_host/shared_worker_host_unittest.cc
@@ -11,19 +11,18 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "content/browser/appcache/chrome_appcache_service.h"
+#include "content/browser/navigation_subresource_loader_params.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/worker_host/mock_shared_worker.h"
#include "content/browser/worker_host/shared_worker_connector_impl.h"
#include "content/browser/worker_host/shared_worker_instance.h"
#include "content/browser/worker_host/shared_worker_service_impl.h"
-#include "content/common/navigation_subresource_loader_params.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_utils.h"
#include "content/test/not_implemented_network_url_loader_factory.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "services/network/public/cpp/features.h"
@@ -42,10 +41,15 @@ class SharedWorkerHostTest : public testing::Test {
}
SharedWorkerHostTest()
- : mock_render_process_host_(&browser_context_),
+ : default_mock_url_loader_factory_(
+ std::make_unique<NotImplementedNetworkURLLoaderFactory>()),
+ mock_render_process_host_(&browser_context_),
service_(nullptr /* storage_partition */,
nullptr /* service_worker_context */,
- nullptr /* appcache_service */) {}
+ nullptr /* appcache_service */) {
+ mock_render_process_host_.OverrideURLLoaderFactory(
+ default_mock_url_loader_factory_.get());
+ }
base::WeakPtr<SharedWorkerHost> CreateHost() {
GURL url("http://www.example.com/w.js");
@@ -73,8 +77,7 @@ class SharedWorkerHostTest : public testing::Test {
void StartWorker(SharedWorkerHost* host,
blink::mojom::SharedWorkerFactoryPtr factory) {
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr provider_info = nullptr;
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory;
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory;
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params;
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories;
@@ -106,7 +109,7 @@ class SharedWorkerHostTest : public testing::Test {
helper_->context()->AsWeakPtr(), mock_render_process_host_.GetID(),
&provider_info);
- mojo::MakeStrongAssociatedBinding(
+ mojo::MakeStrongBinding(
std::make_unique<NotImplementedNetworkURLLoaderFactory>(),
mojo::MakeRequest(&main_script_loader_factory));
@@ -142,6 +145,8 @@ class SharedWorkerHostTest : public testing::Test {
protected:
TestBrowserThreadBundle test_browser_thread_bundle_;
TestBrowserContext browser_context_;
+ std::unique_ptr<network::mojom::URLLoaderFactory>
+ default_mock_url_loader_factory_;
MockRenderProcessHost mock_render_process_host_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
diff --git a/chromium/content/browser/worker_host/shared_worker_service_impl.cc b/chromium/content/browser/worker_host/shared_worker_service_impl.cc
index 618f7208c0f..6282f24a458 100644
--- a/chromium/content/browser/worker_host/shared_worker_service_impl.cc
+++ b/chromium/content/browser/worker_host/shared_worker_service_impl.cc
@@ -103,6 +103,11 @@ void SharedWorkerServiceImpl::SetWorkerTerminationCallbackForTesting(
terminate_all_workers_callback_ = std::move(callback);
}
+void SharedWorkerServiceImpl::SetURLLoaderFactoryForTesting(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
+ url_loader_factory_override_ = std::move(url_loader_factory);
+}
+
void SharedWorkerServiceImpl::ConnectToWorker(
int process_id,
int frame_id,
@@ -209,7 +214,8 @@ void SharedWorkerServiceImpl::CreateWorker(
process_id, weak_host->instance()->url(),
weak_host->instance()->constructor_origin(), ResourceType::kSharedWorker,
service_worker_context_, appcache_handle_core,
- std::move(blob_url_loader_factory), storage_partition_,
+ std::move(blob_url_loader_factory), url_loader_factory_override_,
+ storage_partition_,
base::BindOnce(&SharedWorkerServiceImpl::DidCreateScriptLoader,
weak_factory_.GetWeakPtr(), std::move(instance), weak_host,
std::move(client), process_id, frame_id, message_port));
@@ -224,8 +230,7 @@ void SharedWorkerServiceImpl::DidCreateScriptLoader(
const blink::MessagePortChannel& message_port,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
@@ -262,8 +267,7 @@ void SharedWorkerServiceImpl::StartWorker(
const blink::MessagePortChannel& message_port,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
diff --git a/chromium/content/browser/worker_host/shared_worker_service_impl.h b/chromium/content/browser/worker_host/shared_worker_service_impl.h
index bc34b7fd267..6105d48790a 100644
--- a/chromium/content/browser/worker_host/shared_worker_service_impl.h
+++ b/chromium/content/browser/worker_host/shared_worker_service_impl.h
@@ -53,6 +53,11 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
void TerminateAllWorkersForTesting(base::OnceClosure callback);
void SetWorkerTerminationCallbackForTesting(base::OnceClosure callback);
+ // Uses |url_loader_factory| to load workers' scripts instead of
+ // StoragePartition's URLLoaderFactoryGetter.
+ void SetURLLoaderFactoryForTesting(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+
// Creates the worker if necessary or connects to an already existing worker.
void ConnectToWorker(
int process_id,
@@ -88,8 +93,7 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
const blink::MessagePortChannel& message_port,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
@@ -106,8 +110,7 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
const blink::MessagePortChannel& message_port,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
@@ -128,6 +131,7 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
StoragePartitionImpl* const storage_partition_;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
scoped_refptr<ChromeAppCacheService> appcache_service_;
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_override_;
base::WeakPtrFactory<SharedWorkerServiceImpl> weak_factory_;
diff --git a/chromium/content/browser/worker_host/shared_worker_service_impl_unittest.cc b/chromium/content/browser/worker_host/shared_worker_service_impl_unittest.cc
index ddddded0d5f..71d5077c602 100644
--- a/chromium/content/browser/worker_host/shared_worker_service_impl_unittest.cc
+++ b/chromium/content/browser/worker_host/shared_worker_service_impl_unittest.cc
@@ -15,9 +15,12 @@
#include "content/browser/site_instance_impl.h"
#include "content/browser/worker_host/mock_shared_worker.h"
#include "content/browser/worker_host/shared_worker_connector_impl.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_utils.h"
+#include "content/test/fake_network_url_loader_factory.h"
#include "content/test/not_implemented_network_url_loader_factory.h"
#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
@@ -25,6 +28,8 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/test_support/test_utils.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
#include "third_party/blink/public/mojom/worker/shared_worker_info.mojom.h"
@@ -44,13 +49,15 @@ class SharedWorkerServiceImplTest : public RenderViewHostImplTestHarness {
return connector;
}
- static bool CheckReceivedFactoryRequest(
- blink::mojom::SharedWorkerFactoryRequest* request) {
- if (s_factory_request_received_.empty())
- return false;
- *request = std::move(s_factory_request_received_.front());
+ static blink::mojom::SharedWorkerFactoryRequest WaitForFactoryRequest() {
+ if (s_factory_request_received_.empty()) {
+ base::RunLoop run_loop;
+ s_factory_request_callback_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+ auto rv = std::move(s_factory_request_received_.front());
s_factory_request_received_.pop();
- return true;
+ return rv;
}
static bool CheckNotReceivedFactoryRequest() {
@@ -58,6 +65,8 @@ class SharedWorkerServiceImplTest : public RenderViewHostImplTestHarness {
}
static void BindSharedWorkerFactory(mojo::ScopedMessagePipeHandle handle) {
+ if (s_factory_request_callback_)
+ std::move(s_factory_request_callback_).Run();
s_factory_request_received_.push(
blink::mojom::SharedWorkerFactoryRequest(std::move(handle)));
}
@@ -79,11 +88,26 @@ class SharedWorkerServiceImplTest : public RenderViewHostImplTestHarness {
std::make_unique<MockRenderProcessHostFactory>();
RenderProcessHostImpl::set_render_process_host_factory_for_testing(
render_process_host_factory_.get());
- url_loader_factory_ =
- std::make_unique<NotImplementedNetworkURLLoaderFactory>();
+
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ fake_url_loader_factory_ =
+ std::make_unique<FakeNetworkURLLoaderFactory>();
+ url_loader_factory_wrapper_ =
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ fake_url_loader_factory_.get());
+ static_cast<SharedWorkerServiceImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context_.get())
+ ->GetSharedWorkerService())
+ ->SetURLLoaderFactoryForTesting(url_loader_factory_wrapper_);
+ } else {
+ url_loader_factory_ =
+ std::make_unique<NotImplementedNetworkURLLoaderFactory>();
+ }
}
void TearDown() override {
+ if (url_loader_factory_wrapper_)
+ url_loader_factory_wrapper_->Detach();
browser_context_.reset();
RenderViewHostImplTestHarness::TearDown();
}
@@ -91,9 +115,14 @@ class SharedWorkerServiceImplTest : public RenderViewHostImplTestHarness {
std::unique_ptr<TestBrowserContext> browser_context_;
static std::queue<blink::mojom::SharedWorkerFactoryRequest>
s_factory_request_received_;
+ static base::OnceClosure s_factory_request_callback_;
std::unique_ptr<MockRenderProcessHostFactory> render_process_host_factory_;
std::unique_ptr<NotImplementedNetworkURLLoaderFactory> url_loader_factory_;
+ std::unique_ptr<FakeNetworkURLLoaderFactory> fake_url_loader_factory_;
+ scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
+ url_loader_factory_wrapper_;
+
private:
DISALLOW_COPY_AND_ASSIGN(SharedWorkerServiceImplTest);
};
@@ -102,6 +131,9 @@ class SharedWorkerServiceImplTest : public RenderViewHostImplTestHarness {
std::queue<blink::mojom::SharedWorkerFactoryRequest>
SharedWorkerServiceImplTest::s_factory_request_received_;
+// static
+base::OnceClosure SharedWorkerServiceImplTest::s_factory_request_callback_;
+
namespace {
void ConnectToSharedWorker(blink::mojom::SharedWorkerConnectorPtr connector,
@@ -135,7 +167,8 @@ TEST_F(SharedWorkerServiceImplTest, BasicTest) {
renderer_host->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host->OverrideURLLoaderFactory(url_loader_factory_.get());
MockSharedWorkerClient client;
MessagePortChannel local_port;
@@ -144,10 +177,8 @@ TEST_F(SharedWorkerServiceImplTest, BasicTest) {
renderer_host, render_frame_host->GetRoutingID()),
kUrl, "name", &client, &local_port);
- base::RunLoop().RunUntilIdle();
-
- blink::mojom::SharedWorkerFactoryRequest factory_request;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request));
+ blink::mojom::SharedWorkerFactoryRequest factory_request =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory(std::move(factory_request));
base::RunLoop().RunUntilIdle();
@@ -211,7 +242,8 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
renderer_host0->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
MockSharedWorkerClient client0;
MessagePortChannel local_port0;
@@ -222,8 +254,8 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
base::RunLoop().RunUntilIdle();
- blink::mojom::SharedWorkerFactoryRequest factory_request;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request));
+ blink::mojom::SharedWorkerFactoryRequest factory_request =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory(std::move(factory_request));
base::RunLoop().RunUntilIdle();
@@ -280,7 +312,8 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
renderer_host1->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
MockSharedWorkerClient client1;
MessagePortChannel local_port1;
@@ -342,7 +375,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase) {
renderer_host0->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -362,8 +396,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase) {
kUrl, kName, &client0, &local_port0);
base::RunLoop().RunUntilIdle();
- blink::mojom::SharedWorkerFactoryRequest factory_request;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request));
+ blink::mojom::SharedWorkerFactoryRequest factory_request =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory(std::move(factory_request));
base::RunLoop().RunUntilIdle();
@@ -414,7 +448,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_URLMismatch) {
renderer_host0->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -424,7 +459,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_URLMismatch) {
renderer_host1->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
// First client, creates worker.
@@ -435,8 +471,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_URLMismatch) {
kUrl0, kName, &client0, &local_port0);
base::RunLoop().RunUntilIdle();
- blink::mojom::SharedWorkerFactoryRequest factory_request0;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request0));
+ blink::mojom::SharedWorkerFactoryRequest factory_request0 =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory0(std::move(factory_request0));
base::RunLoop().RunUntilIdle();
@@ -460,8 +496,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_URLMismatch) {
kUrl1, kName, &client1, &local_port1);
base::RunLoop().RunUntilIdle();
- blink::mojom::SharedWorkerFactoryRequest factory_request1;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request1));
+ blink::mojom::SharedWorkerFactoryRequest factory_request1 =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory1(std::move(factory_request1));
base::RunLoop().RunUntilIdle();
@@ -499,7 +535,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_NameMismatch) {
renderer_host0->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -509,7 +546,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_NameMismatch) {
renderer_host1->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
// First client, creates worker.
@@ -520,8 +558,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_NameMismatch) {
kUrl, kName0, &client0, &local_port0);
base::RunLoop().RunUntilIdle();
- blink::mojom::SharedWorkerFactoryRequest factory_request0;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request0));
+ blink::mojom::SharedWorkerFactoryRequest factory_request0 =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory0(std::move(factory_request0));
base::RunLoop().RunUntilIdle();
@@ -545,8 +583,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_NameMismatch) {
kUrl, kName1, &client1, &local_port1);
base::RunLoop().RunUntilIdle();
- blink::mojom::SharedWorkerFactoryRequest factory_request1;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request1));
+ blink::mojom::SharedWorkerFactoryRequest factory_request1 =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory1(std::move(factory_request1));
base::RunLoop().RunUntilIdle();
@@ -583,7 +621,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase) {
renderer_host0->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -593,7 +632,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase) {
renderer_host1->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
// First client and second client are created before the worker starts.
@@ -613,8 +653,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase) {
// Check that the worker was created.
- blink::mojom::SharedWorkerFactoryRequest factory_request;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request));
+ blink::mojom::SharedWorkerFactoryRequest factory_request =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory(std::move(factory_request));
base::RunLoop().RunUntilIdle();
@@ -658,7 +698,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_URLMismatch) {
renderer_host0->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -668,7 +709,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_URLMismatch) {
renderer_host1->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
// First client and second client are created before the workers start.
@@ -688,12 +730,12 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_URLMismatch) {
// Check that both workers were created.
- blink::mojom::SharedWorkerFactoryRequest factory_request0;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request0));
+ blink::mojom::SharedWorkerFactoryRequest factory_request0 =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory0(std::move(factory_request0));
- blink::mojom::SharedWorkerFactoryRequest factory_request1;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request1));
+ blink::mojom::SharedWorkerFactoryRequest factory_request1 =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory1(std::move(factory_request1));
base::RunLoop().RunUntilIdle();
@@ -747,7 +789,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_NameMismatch) {
renderer_host0->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -757,7 +800,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_NameMismatch) {
renderer_host1->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
// First client and second client are created before the workers start.
@@ -777,12 +821,12 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_NameMismatch) {
// Check that both workers were created.
- blink::mojom::SharedWorkerFactoryRequest factory_request0;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request0));
+ blink::mojom::SharedWorkerFactoryRequest factory_request0 =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory0(std::move(factory_request0));
- blink::mojom::SharedWorkerFactoryRequest factory_request1;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request1));
+ blink::mojom::SharedWorkerFactoryRequest factory_request1 =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory1(std::move(factory_request1));
base::RunLoop().RunUntilIdle();
@@ -836,7 +880,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
renderer_host0->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
std::unique_ptr<TestWebContents> web_contents1 =
CreateWebContents(GURL("http://example.com/"));
@@ -845,7 +890,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
renderer_host1->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
std::unique_ptr<TestWebContents> web_contents2 =
CreateWebContents(GURL("http://example.com/"));
@@ -854,7 +900,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
renderer_host2->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host2->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host2->OverrideURLLoaderFactory(url_loader_factory_.get());
MockSharedWorkerClient client0;
MessagePortChannel local_port0;
@@ -866,8 +913,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
// Starts a worker.
- blink::mojom::SharedWorkerFactoryRequest factory_request0;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request0));
+ blink::mojom::SharedWorkerFactoryRequest factory_request0 =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory0(std::move(factory_request0));
base::RunLoop().RunUntilIdle();
@@ -900,8 +947,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
// The previous worker is unavailable, so a new worker is created.
- blink::mojom::SharedWorkerFactoryRequest factory_request1;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request1));
+ blink::mojom::SharedWorkerFactoryRequest factory_request1 =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory1(std::move(factory_request1));
base::RunLoop().RunUntilIdle();
@@ -947,7 +994,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) {
renderer_host0->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
std::unique_ptr<TestWebContents> web_contents1 =
CreateWebContents(GURL("http://example.com/"));
@@ -956,7 +1004,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) {
renderer_host1->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
std::unique_ptr<TestWebContents> web_contents2 =
CreateWebContents(GURL("http://example.com/"));
@@ -965,7 +1014,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) {
renderer_host2->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host2->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host2->OverrideURLLoaderFactory(url_loader_factory_.get());
MockSharedWorkerClient client0;
MessagePortChannel local_port0;
@@ -987,8 +1037,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) {
// The previous worker is unavailable, so a new worker is created.
- blink::mojom::SharedWorkerFactoryRequest factory_request1;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request1));
+ blink::mojom::SharedWorkerFactoryRequest factory_request1 =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory1(std::move(factory_request1));
EXPECT_TRUE(CheckNotReceivedFactoryRequest());
@@ -1035,7 +1085,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest3) {
blink::mojom::SharedWorkerFactory::Name_,
base::BindRepeating(
&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -1046,7 +1097,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest3) {
blink::mojom::SharedWorkerFactory::Name_,
base::BindRepeating(
&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
- renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
// Both clients try to connect/create a worker.
@@ -1064,8 +1116,8 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest3) {
base::RunLoop().RunUntilIdle();
// Expect a factory request.
- blink::mojom::SharedWorkerFactoryRequest factory_request;
- EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request));
+ blink::mojom::SharedWorkerFactoryRequest factory_request =
+ WaitForFactoryRequest();
MockSharedWorkerFactory factory(std::move(factory_request));
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/worker_host/worker_browsertest.cc b/chromium/content/browser/worker_host/worker_browsertest.cc
index 06b4520da47..ace531dcbf6 100644
--- a/chromium/content/browser/worker_host/worker_browsertest.cc
+++ b/chromium/content/browser/worker_host/worker_browsertest.cc
@@ -10,10 +10,12 @@
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
+#include "base/test/bind_test_util.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/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/client_certificate_delegate.h"
@@ -23,14 +25,18 @@
#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/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_content_browser_client.h"
+#include "content/test/content_browser_test_utils_internal.h"
#include "net/base/escape.h"
#include "net/base/filename_util.h"
+#include "net/dns/mock_host_resolver.h"
#include "net/ssl/ssl_server_config.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
#include "net/test/test_data_directory.h"
+#include "services/network/public/cpp/features.h"
#include "url/gurl.h"
namespace content {
@@ -56,17 +62,13 @@ class WorkerTest : public ContentBrowserTest {
WorkerTest() : select_certificate_count_(0) {}
void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
ShellContentBrowserClient::Get()->set_select_client_certificate_callback(
- base::Bind(&WorkerTest::OnSelectClientCertificate,
- base::Unretained(this)));
+ base::BindOnce(&WorkerTest::OnSelectClientCertificate,
+ base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
}
- void TearDownOnMainThread() override {
- ShellContentBrowserClient::Get()->set_select_client_certificate_callback(
- base::Closure());
- }
-
int select_certificate_count() const { return select_certificate_count_; }
GURL GetTestFileURL(const std::string& test_case) {
@@ -106,7 +108,7 @@ class WorkerTest : public ContentBrowserTest {
ShellContentBrowserClient::Get();
scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
browser_client->set_login_request_callback(
- base::Bind(&QuitUIMessageLoop, runner->QuitClosure()));
+ base::BindOnce(&QuitUIMessageLoop, runner->QuitClosure()));
shell()->LoadURL(url);
runner->Run();
}
@@ -272,4 +274,62 @@ IN_PROC_BROWSER_TEST_F(WorkerTest,
"pass_messageport_to_sharedworker_dont_wait_for_connect.html", ""));
}
+// Tests the value of |request_initiator| for shared worker resources.
+IN_PROC_BROWSER_TEST_F(WorkerTest, VerifyInitiatorSharedWorker) {
+ // TODO(cammie): Remove the condition that network service must be
+ // enabled once it is enabled on all platforms?
+ // The main body of the test won't currently work unless network service
+ // is enabled (e.g. not on cast-shell-linux as of 2019/04).
+ if (!SupportsSharedWorker() ||
+ !base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
+ const GURL start_url(embedded_test_server()->GetURL("/frame_tree/top.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+
+ // To make things tricky about |top_frame_origin|, this test navigates to
+ // a page on |embedded_test_server()| which has a cross-origin iframe that
+ // registers the worker.
+ std::string cross_site_domain("cross-site.com");
+ const GURL test_url(embedded_test_server()->GetURL(
+ cross_site_domain, "/workers/simple_shared_worker.html"));
+
+ // There are three requests to test:
+ // 1) The request for the worker itself ("worker.js")
+ // 2) importScripts("empty.js") from the worker
+ // 3) fetch("empty.html") from the worker
+ const GURL worker_url(
+ embedded_test_server()->GetURL(cross_site_domain, "/workers/worker.js"));
+ const GURL script_url(
+ embedded_test_server()->GetURL(cross_site_domain, "/workers/empty.js"));
+ const GURL resource_url(
+ embedded_test_server()->GetURL(cross_site_domain, "/workers/empty.html"));
+
+ std::set<GURL> expected_request_urls = {worker_url, script_url, resource_url};
+ const url::Origin expected_origin =
+ url::Origin::Create(worker_url.GetOrigin());
+
+ base::RunLoop waiter;
+ URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
+ [&](URLLoaderInterceptor::RequestParams* params) {
+ auto it = expected_request_urls.find(params->url_request.url);
+ if (it != expected_request_urls.end()) {
+ EXPECT_FALSE(params->url_request.top_frame_origin.has_value());
+ EXPECT_TRUE(params->url_request.request_initiator.has_value());
+ EXPECT_EQ(expected_origin,
+ params->url_request.request_initiator.value());
+ expected_request_urls.erase(it);
+ }
+ if (expected_request_urls.empty())
+ waiter.Quit();
+ return false;
+ }));
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ NavigateFrameToURL(root->child_at(0), test_url);
+ waiter.Run();
+}
+
} // namespace content
diff --git a/chromium/content/browser/worker_host/worker_script_fetch_initiator.cc b/chromium/content/browser/worker_host/worker_script_fetch_initiator.cc
index 33693a1124c..ad61ea12650 100644
--- a/chromium/content/browser/worker_host/worker_script_fetch_initiator.cc
+++ b/chromium/content/browser/worker_host/worker_script_fetch_initiator.cc
@@ -15,6 +15,7 @@
#include "content/browser/appcache/appcache_navigation_handle_core.h"
#include "content/browser/data_url_loader_factory.h"
#include "content/browser/file_url_loader_factory.h"
+#include "content/browser/navigation_subresource_loader_params.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/url_loader_factory_getter.h"
@@ -23,7 +24,6 @@
#include "content/browser/worker_host/worker_script_loader.h"
#include "content/browser/worker_host/worker_script_loader_factory.h"
#include "content/common/content_constants_internal.h"
-#include "content/common/navigation_subresource_loader_params.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -35,12 +35,11 @@
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/origin_util.h"
-#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/network/loader_util.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "third_party/blink/public/common/loader//url_loader_factory_bundle.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
#include "url/origin.h"
@@ -55,6 +54,7 @@ void WorkerScriptFetchInitiator::Start(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
AppCacheNavigationHandleCore* appcache_handle_core,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_override,
StoragePartitionImpl* storage_partition,
CompletionCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -120,6 +120,8 @@ void WorkerScriptFetchInitiator::Start(
std::move(subresource_loader_factories), resource_context,
std::move(service_worker_context), appcache_handle_core,
blob_url_loader_factory ? blob_url_loader_factory->Clone() : nullptr,
+ url_loader_factory_override ? url_loader_factory_override->Clone()
+ : nullptr,
std::move(callback)));
}
@@ -223,20 +225,8 @@ void WorkerScriptFetchInitiator::AddAdditionalRequestHeaders(
if ((base::FeatureList::IsEnabled(network::features::kFetchMetadata) ||
experimental_features_enabled) &&
IsOriginSecure(resource_request->url)) {
- // The worker's origin can be different from the constructor's origin, for
- // example, when the worker created from the extension.
- // TODO(hiroshige): Add DCHECK to make sure the same-originness once the
- // cross-origin workers are deprecated (https://crbug.com/867302).
- std::string site_value = "cross-site";
- if (resource_request->request_initiator->IsSameOriginWith(
- url::Origin::Create(resource_request->url))) {
- site_value = "same-origin";
- }
- resource_request->headers.SetHeaderIfMissing("Sec-Fetch-Site",
- site_value.c_str());
resource_request->headers.SetHeaderIfMissing("Sec-Fetch-Mode",
"same-origin");
- // We don't set `Sec-Fetch-User` for subresource requests.
if (base::FeatureList::IsEnabled(
network::features::kFetchMetadataDestination) ||
@@ -244,6 +234,10 @@ void WorkerScriptFetchInitiator::AddAdditionalRequestHeaders(
resource_request->headers.SetHeaderIfMissing("Sec-Fetch-Dest",
"sharedworker");
}
+
+ // Note that the `Sec-Fetch-User` header is always false (and therefore
+ // omitted) for subresource requests. Also note that `Sec-Fetch-Site` is
+ // covered elsewhere - by the network::SetSecFetchSiteHeader function.
}
}
@@ -260,6 +254,8 @@ void WorkerScriptFetchInitiator::CreateScriptLoaderOnIO(
AppCacheNavigationHandleCore* appcache_handle_core,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
blob_url_loader_factory_info,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ url_loader_factory_override_info,
CompletionCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(resource_context);
@@ -278,6 +274,10 @@ void WorkerScriptFetchInitiator::CreateScriptLoaderOnIO(
// creating a new URLLoaderFactoryBundle.
url_loader_factory = network::SharedURLLoaderFactory::Create(
std::move(blob_url_loader_factory_info));
+ } else if (url_loader_factory_override_info) {
+ // For unit tests.
+ url_loader_factory = network::SharedURLLoaderFactory::Create(
+ std::move(url_loader_factory_override_info));
} else {
// Add the default factory to the bundle for browser if NetworkService
// is on. When NetworkService is off, we already created the default factory
@@ -338,8 +338,8 @@ void WorkerScriptFetchInitiator::CreateScriptLoaderOnIO(
}
// Create the WorkerScriptLoaderFactory.
- network::mojom::URLLoaderFactoryAssociatedPtrInfo main_script_loader_factory;
- mojo::MakeStrongAssociatedBinding(
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory;
+ mojo::MakeStrongBinding(
std::make_unique<WorkerScriptLoaderFactory>(
process_id, std::move(service_worker_host), std::move(appcache_host),
resource_context_getter, std::move(url_loader_factory)),
@@ -357,8 +357,7 @@ void WorkerScriptFetchInitiator::DidCreateScriptLoaderOnIO(
CompletionCallback callback,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
diff --git a/chromium/content/browser/worker_host/worker_script_fetch_initiator.h b/chromium/content/browser/worker_host/worker_script_fetch_initiator.h
index d334e29ed59..1c8b7c03d3a 100644
--- a/chromium/content/browser/worker_host/worker_script_fetch_initiator.h
+++ b/chromium/content/browser/worker_host/worker_script_fetch_initiator.h
@@ -46,7 +46,7 @@ class WorkerScriptFetchInitiator {
public:
using CompletionCallback = base::OnceCallback<void(
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo,
+ network::mojom::URLLoaderFactoryPtr,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>,
blink::mojom::WorkerMainScriptLoadParamsPtr,
blink::mojom::ControllerServiceWorkerInfoPtr,
@@ -63,6 +63,8 @@ class WorkerScriptFetchInitiator {
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
AppCacheNavigationHandleCore* appcache_handle_core,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+ scoped_refptr<network::SharedURLLoaderFactory>
+ url_loader_factory_override,
StoragePartitionImpl* storage_partition,
CompletionCallback callback);
@@ -92,13 +94,14 @@ class WorkerScriptFetchInitiator {
AppCacheNavigationHandleCore* appcache_handle_core,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
blob_url_loader_factory_info,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ url_loader_factory_override_info,
CompletionCallback callback);
static void DidCreateScriptLoaderOnIO(
CompletionCallback callback,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
diff --git a/chromium/content/browser/worker_host/worker_script_fetcher.cc b/chromium/content/browser/worker_host/worker_script_fetcher.cc
index 05b8ce7eae7..f8609adc3f1 100644
--- a/chromium/content/browser/worker_host/worker_script_fetcher.cc
+++ b/chromium/content/browser/worker_host/worker_script_fetcher.cc
@@ -5,6 +5,7 @@
#include "content/browser/worker_host/worker_script_fetcher.h"
#include "base/feature_list.h"
+#include "content/browser/loader/navigation_url_loader_impl.h"
#include "content/browser/worker_host/worker_script_loader.h"
#include "content/browser/worker_host/worker_script_loader_factory.h"
#include "content/common/throttling_url_loader.h"
@@ -90,8 +91,9 @@ void WorkerScriptFetcher::Start(
// workers (https://crbug.com/906991).
int32_t routing_id = MSG_ROUTING_NONE;
- // NetworkService is not interested in the request ID.
- int request_id = -1;
+ // Use NavigationURLLoaderImpl to get a unique request id across
+ // browser-initiated navigations and worker script fetch.
+ int request_id = NavigationURLLoaderImpl::MakeGlobalRequestID().request_id;
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
std::move(shared_url_loader_factory), std::move(throttles), routing_id,
@@ -175,8 +177,7 @@ void WorkerScriptFetcher::OnUploadProgress(int64_t current_position,
NOTREACHED();
}
-void WorkerScriptFetcher::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
+void WorkerScriptFetcher::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
NOTREACHED();
}
diff --git a/chromium/content/browser/worker_host/worker_script_fetcher.h b/chromium/content/browser/worker_host/worker_script_fetcher.h
index 19dc520df30..c0753503b0a 100644
--- a/chromium/content/browser/worker_host/worker_script_fetcher.h
+++ b/chromium/content/browser/worker_host/worker_script_fetcher.h
@@ -7,7 +7,7 @@
#include "base/callback.h"
#include "base/optional.h"
-#include "content/common/navigation_subresource_loader_params.h"
+#include "content/browser/navigation_subresource_loader_params.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -65,7 +65,7 @@ class WorkerScriptFetcher : public network::mojom::URLLoaderClient {
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
diff --git a/chromium/content/browser/worker_host/worker_script_loader.cc b/chromium/content/browser/worker_host/worker_script_loader.cc
index 6c344828fd2..c0a33e7ca15 100644
--- a/chromium/content/browser/worker_host/worker_script_loader.cc
+++ b/chromium/content/browser/worker_host/worker_script_loader.cc
@@ -233,9 +233,8 @@ void WorkerScriptLoader::OnUploadProgress(
std::move(ack_callback));
}
-void WorkerScriptLoader::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
- client_->OnReceiveCachedMetadata(data);
+void WorkerScriptLoader::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
+ client_->OnReceiveCachedMetadata(std::move(data));
}
void WorkerScriptLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
diff --git a/chromium/content/browser/worker_host/worker_script_loader.h b/chromium/content/browser/worker_host/worker_script_loader.h
index 21176874105..ecb5e78b7ce 100644
--- a/chromium/content/browser/worker_host/worker_script_loader.h
+++ b/chromium/content/browser/worker_host/worker_script_loader.h
@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "base/optional.h"
-#include "content/common/navigation_subresource_loader_params.h"
+#include "content/browser/navigation_subresource_loader_params.h"
#include "content/common/single_request_url_loader_factory.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
@@ -87,7 +87,7 @@ class WorkerScriptLoader : public network::mojom::URLLoader,
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
diff --git a/chromium/content/browser/worker_host/worker_script_loader_factory.h b/chromium/content/browser/worker_host/worker_script_loader_factory.h
index 27a53af2d5f..61b316506b3 100644
--- a/chromium/content/browser/worker_host/worker_script_loader_factory.h
+++ b/chromium/content/browser/worker_host/worker_script_loader_factory.h
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_WORKER_HOST_WORKER_SCRIPT_LOADER_FACTORY_H_
#include "base/macros.h"
-#include "content/common/navigation_subresource_loader_params.h"
+#include "content/browser/navigation_subresource_loader_params.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace network {
diff --git a/chromium/content/browser/worker_host/worker_script_loader_factory_unittest.cc b/chromium/content/browser/worker_host/worker_script_loader_factory_unittest.cc
index 51746d5d889..2e4b8cab48d 100644
--- a/chromium/content/browser/worker_host/worker_script_loader_factory_unittest.cc
+++ b/chromium/content/browser/worker_host/worker_script_loader_factory_unittest.cc
@@ -10,10 +10,8 @@
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/test/test_browser_thread_bundle.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "net/http/http_util.h"
+#include "content/test/fake_network_url_loader_factory.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -22,56 +20,6 @@ namespace content {
namespace {
-// A URLLoaderFactory that returns 200 OK with an empty javascript to any
-// request.
-// TODO(bashi): Avoid duplicated MockNetworkURLLoaderFactory. This is almost the
-// same as EmbeddedWorkerTestHelper::MockNetworkURLLoaderFactory.
-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 {
- const std::string headers =
- "HTTP/1.1 200 OK\n"
- "Content-Type: application/javascript\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);
-
- const 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);
-};
-
const int kProcessId = 1;
} // namespace
@@ -95,7 +43,7 @@ class WorkerScriptLoaderFactoryTest : public testing::Test {
// Set up the network factory.
network_loader_factory_instance_ =
- std::make_unique<MockNetworkURLLoaderFactory>();
+ std::make_unique<FakeNetworkURLLoaderFactory>();
network::mojom::URLLoaderFactoryPtrInfo factory;
network_loader_factory_instance_->Clone(mojo::MakeRequest(&factory));
auto info = std::make_unique<network::WrapperSharedURLLoaderFactoryInfo>(
@@ -132,7 +80,7 @@ class WorkerScriptLoaderFactoryTest : public testing::Test {
TestBrowserThreadBundle browser_thread_bundle_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
- std::unique_ptr<MockNetworkURLLoaderFactory> network_loader_factory_instance_;
+ std::unique_ptr<FakeNetworkURLLoaderFactory> network_loader_factory_instance_;
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
diff --git a/chromium/content/child/BUILD.gn b/chromium/content/child/BUILD.gn
index 16e1d03b4d4..d696471083b 100644
--- a/chromium/content/child/BUILD.gn
+++ b/chromium/content/child/BUILD.gn
@@ -112,7 +112,6 @@ target(link_target_type, "child") {
"//storage/common",
"//third_party/blink/public:blink_headers",
"//third_party/blink/public:buildflags",
- "//third_party/blink/public:mojo_bindings",
"//third_party/blink/public:resources",
"//third_party/blink/public:scaled_resources",
"//third_party/blink/public/common",
@@ -129,18 +128,15 @@ target(link_target_type, "child") {
"//v8",
]
- if (!use_default_render_theme) {
- sources -= [
- "webthemeengine_impl_default.cc",
- "webthemeengine_impl_default.h",
- ]
- }
-
if (is_android) {
deps += [ "//third_party/android_sdk:cpu_features" ]
if (notouch_build) {
configs += [ ":notouch_config" ]
}
+ sources -= [
+ "webthemeengine_impl_default.cc",
+ "webthemeengine_impl_default.h",
+ ]
}
if (is_linux) {
diff --git a/chromium/content/child/blink_platform_impl.cc b/chromium/content/child/blink_platform_impl.cc
index 3ce31a5ea07..353e35a78ce 100644
--- a/chromium/content/child/blink_platform_impl.cc
+++ b/chromium/content/child/blink_platform_impl.cc
@@ -33,6 +33,7 @@
#include "content/app/resources/grit/content_resources.h"
#include "content/app/strings/grit/content_strings.h"
#include "content/child/child_thread_impl.h"
+#include "content/common/appcache_interfaces.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
@@ -50,8 +51,19 @@
#include "third_party/blink/public/resources/grit/blink_resources.h"
#include "third_party/zlib/google/compression_utils.h"
#include "ui/base/layout.h"
+#include "ui/base/ui_base_features.h"
#include "ui/events/gestures/blink/web_gesture_curve_impl.h"
+#if defined(OS_ANDROID)
+#include "content/child/webthemeengine_impl_android.h"
+#else
+#include "content/child/webthemeengine_impl_default.h"
+#endif
+
+#if defined(OS_MACOSX)
+#include "content/child/webthemeengine_impl_mac.h"
+#endif
+
using blink::WebData;
using blink::WebLocalizedString;
using blink::WebString;
@@ -61,7 +73,21 @@ using blink::WebURLError;
namespace content {
-static int ToMessageID(WebLocalizedString::Name name) {
+namespace {
+
+std::unique_ptr<blink::WebThemeEngine> GetWebThemeEngine() {
+#if defined(OS_ANDROID)
+ return std::make_unique<WebThemeEngineAndroid>();
+#elif defined(OS_MACOSX)
+ if (features::IsFormControlsRefreshEnabled())
+ return std::make_unique<WebThemeEngineDefault>();
+ return std::make_unique<WebThemeEngineMac>();
+#else
+ return std::make_unique<WebThemeEngineDefault>();
+#endif
+}
+
+int ToMessageID(WebLocalizedString::Name name) {
switch (name) {
case WebLocalizedString::kAXAMPMFieldText:
return IDS_AX_AM_PM_FIELD_TEXT;
@@ -323,30 +349,6 @@ static int ToMessageID(WebLocalizedString::Name name) {
return -1;
}
-// TODO(skyostil): Ensure that we always have an active task runner when
-// constructing the platform.
-BlinkPlatformImpl::BlinkPlatformImpl()
- : BlinkPlatformImpl(base::ThreadTaskRunnerHandle::IsSet()
- ? base::ThreadTaskRunnerHandle::Get()
- : nullptr,
- nullptr) {}
-
-BlinkPlatformImpl::BlinkPlatformImpl(
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner)
- : main_thread_task_runner_(std::move(main_thread_task_runner)),
- io_thread_task_runner_(std::move(io_thread_task_runner)) {}
-
-BlinkPlatformImpl::~BlinkPlatformImpl() {
-}
-
-void BlinkPlatformImpl::RecordAction(const blink::UserMetricsAction& name) {
- if (ChildThread* child_thread = ChildThread::Get())
- child_thread->RecordComputedAction(name.Action());
-}
-
-namespace {
-
WebData loadAudioSpatializationResource(const char* name) {
#ifdef IDR_AUDIO_SPATIALIZATION_COMPOSITE
if (!strcmp(name, "Composite")) {
@@ -533,6 +535,28 @@ class NestedMessageLoopRunnerImpl
} // namespace
+// TODO(skyostil): Ensure that we always have an active task runner when
+// constructing the platform.
+BlinkPlatformImpl::BlinkPlatformImpl()
+ : BlinkPlatformImpl(base::ThreadTaskRunnerHandle::IsSet()
+ ? base::ThreadTaskRunnerHandle::Get()
+ : nullptr,
+ nullptr) {}
+
+BlinkPlatformImpl::BlinkPlatformImpl(
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner)
+ : main_thread_task_runner_(std::move(main_thread_task_runner)),
+ io_thread_task_runner_(std::move(io_thread_task_runner)),
+ native_theme_engine_(GetWebThemeEngine()) {}
+
+BlinkPlatformImpl::~BlinkPlatformImpl() {}
+
+void BlinkPlatformImpl::RecordAction(const blink::UserMetricsAction& name) {
+ if (ChildThread* child_thread = ChildThread::Get())
+ child_thread->RecordComputedAction(name.Action());
+}
+
WebData BlinkPlatformImpl::GetDataResource(const char* name) {
// Some clients will call into this method with an empty |name| when they have
// optional resources. For example, the PopupMenuChromium code can have icons
@@ -624,13 +648,12 @@ const char* BlinkPlatformImpl::GetBrowserServiceName() const {
return mojom::kBrowserServiceName;
}
-blink::WebMediaCapabilitiesClient*
-BlinkPlatformImpl::MediaCapabilitiesClient() {
- return &media_capabilities_client_;
+WebThemeEngine* BlinkPlatformImpl::ThemeEngine() {
+ return native_theme_engine_.get();
}
-WebThemeEngine* BlinkPlatformImpl::ThemeEngine() {
- return &native_theme_engine_;
+bool BlinkPlatformImpl::IsURLSupportedForAppCache(const blink::WebURL& url) {
+ return IsSchemeSupportedForAppCache(url);
}
base::File BlinkPlatformImpl::DatabaseOpenFile(
diff --git a/chromium/content/child/blink_platform_impl.h b/chromium/content/child/blink_platform_impl.h
index aa60edda9b7..7bde51bf3d0 100644
--- a/chromium/content/child/blink_platform_impl.h
+++ b/chromium/content/child/blink_platform_impl.h
@@ -16,23 +16,12 @@
#include "build/build_config.h"
#include "components/webcrypto/webcrypto_impl.h"
#include "content/common/content_export.h"
-#include "media/blink/webmediacapabilitiesclient_impl.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_gesture_device.h"
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/public_buildflags.h"
#include "ui/base/layout.h"
-#if BUILDFLAG(USE_DEFAULT_RENDER_THEME)
-#include "content/child/webthemeengine_impl_default.h"
-#elif defined(OS_WIN)
-#include "content/child/webthemeengine_impl_win.h"
-#elif defined(OS_MACOSX)
-#include "content/child/webthemeengine_impl_mac.h"
-#elif defined(OS_ANDROID)
-#include "content/child/webthemeengine_impl_android.h"
-#endif
-
namespace content {
class WebCryptoImpl;
@@ -47,6 +36,7 @@ class CONTENT_EXPORT BlinkPlatformImpl : public blink::Platform {
// Platform methods (partial implementation):
blink::WebThemeEngine* ThemeEngine() override;
+ bool IsURLSupportedForAppCache(const blink::WebURL& url) override;
base::File DatabaseOpenFile(const blink::WebString& vfs_file_name,
int desired_flags) override;
int DatabaseDeleteFile(const blink::WebString& vfs_file_name,
@@ -77,7 +67,6 @@ class CONTENT_EXPORT BlinkPlatformImpl : public blink::Platform {
const blink::WebSecurityOrigin& script_origin) override;
blink::WebCrypto* Crypto() override;
const char* GetBrowserServiceName() const override;
- blink::WebMediaCapabilitiesClient* MediaCapabilitiesClient() override;
scoped_refptr<base::SingleThreadTaskRunner> GetIOTaskRunner() const override;
std::unique_ptr<NestedMessageLoopRunner> CreateNestedMessageLoopRunner()
@@ -86,9 +75,8 @@ class CONTENT_EXPORT BlinkPlatformImpl : public blink::Platform {
private:
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_;
- WebThemeEngineImpl native_theme_engine_;
+ std::unique_ptr<blink::WebThemeEngine> native_theme_engine_;
webcrypto::WebCryptoImpl web_crypto_;
- media::WebMediaCapabilitiesClientImpl media_capabilities_client_;
};
} // namespace content
diff --git a/chromium/content/child/child_process.cc b/chromium/content/child/child_process.cc
index 9313e993d91..3d4cd9e7b63 100644
--- a/chromium/content/child/child_process.cc
+++ b/chromium/content/child/child_process.cc
@@ -24,10 +24,10 @@ base::LazyInstance<base::ThreadLocalPointer<ChildProcess>>::DestructorAtExit
g_lazy_child_process_tls = LAZY_INSTANCE_INITIALIZER;
}
-ChildProcess::ChildProcess(
- base::ThreadPriority io_thread_priority,
- const std::string& thread_pool_name,
- std::unique_ptr<base::ThreadPool::InitParams> thread_pool_init_params)
+ChildProcess::ChildProcess(base::ThreadPriority io_thread_priority,
+ const std::string& thread_pool_name,
+ std::unique_ptr<base::ThreadPoolInstance::InitParams>
+ thread_pool_init_params)
: ref_count_(0),
shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED),
@@ -35,18 +35,19 @@ ChildProcess::ChildProcess(
DCHECK(!g_lazy_child_process_tls.Pointer()->Get());
g_lazy_child_process_tls.Pointer()->Set(this);
- // Initialize ThreadPool if not already done. A ThreadPool may already
- // exist when ChildProcess is instantiated in the browser process or in a
- // test process.
- if (!base::ThreadPool::GetInstance()) {
+ // Initialize ThreadPoolInstance if not already done. A ThreadPoolInstance may
+ // already exist when ChildProcess is instantiated in the browser process or
+ // in a test process.
+ if (!base::ThreadPoolInstance::Get()) {
if (thread_pool_init_params) {
- base::ThreadPool::Create(thread_pool_name);
- base::ThreadPool::GetInstance()->Start(*thread_pool_init_params.get());
+ base::ThreadPoolInstance::Create(thread_pool_name);
+ base::ThreadPoolInstance::Get()->Start(*thread_pool_init_params.get());
} else {
- base::ThreadPool::CreateAndStartWithDefaultParams(thread_pool_name);
+ base::ThreadPoolInstance::CreateAndStartWithDefaultParams(
+ thread_pool_name);
}
- DCHECK(base::ThreadPool::GetInstance());
+ DCHECK(base::ThreadPoolInstance::Get());
initialized_thread_pool_ = true;
}
@@ -85,8 +86,8 @@ ChildProcess::~ChildProcess() {
io_thread_.Stop();
if (initialized_thread_pool_) {
- DCHECK(base::ThreadPool::GetInstance());
- base::ThreadPool::GetInstance()->Shutdown();
+ DCHECK(base::ThreadPoolInstance::Get());
+ base::ThreadPoolInstance::Get()->Shutdown();
}
}
diff --git a/chromium/content/child/child_process.h b/chromium/content/child/child_process.h
index 71c9e34524b..e82fb51d54c 100644
--- a/chromium/content/child/child_process.h
+++ b/chromium/content/child/child_process.h
@@ -43,8 +43,8 @@ class CONTENT_EXPORT ChildProcess {
ChildProcess(
base::ThreadPriority io_thread_priority = base::ThreadPriority::NORMAL,
const std::string& thread_pool_name = "ContentChild",
- std::unique_ptr<base::ThreadPool::InitParams> thread_pool_init_params =
- nullptr);
+ std::unique_ptr<base::ThreadPoolInstance::InitParams>
+ thread_pool_init_params = nullptr);
virtual ~ChildProcess();
// May be NULL if the main thread hasn't been set explicitly.
@@ -97,7 +97,7 @@ class CONTENT_EXPORT ChildProcess {
// io_thread_.
std::unique_ptr<ChildThreadImpl> main_thread_;
- // Whether this ChildProcess initialized ThreadPool.
+ // Whether this ChildProcess initialized ThreadPoolInstance.
bool initialized_thread_pool_ = false;
DISALLOW_COPY_AND_ASSIGN(ChildProcess);
diff --git a/chromium/content/child/child_process_sandbox_support_impl_mac.cc b/chromium/content/child/child_process_sandbox_support_impl_mac.cc
index 2eb514c648f..bb5559dea58 100644
--- a/chromium/content/child/child_process_sandbox_support_impl_mac.cc
+++ b/chromium/content/child/child_process_sandbox_support_impl_mac.cc
@@ -21,7 +21,7 @@ namespace content {
WebSandboxSupportMac::WebSandboxSupportMac(
service_manager::Connector* connector) {
- connector->BindInterface(content::mojom::kBrowserServiceName,
+ connector->BindInterface(content::mojom::kSystemServiceName,
mojo::MakeRequest(&sandbox_support_));
sandbox_support_->GetSystemColors(base::BindOnce(
&WebSandboxSupportMac::OnGotSystemColors, base::Unretained(this)));
diff --git a/chromium/content/child/child_thread_impl.cc b/chromium/content/child/child_thread_impl.cc
index caab65d3c9c..e7807e56ebb 100644
--- a/chromium/content/child/child_thread_impl.cc
+++ b/chromium/content/child/child_thread_impl.cc
@@ -240,8 +240,10 @@ class ChannelBootstrapFilter : public ConnectionFilter {
const std::string& interface_name,
mojo::ScopedMessagePipeHandle* interface_pipe,
service_manager::Connector* connector) override {
- if (source_info.identity.name() != mojom::kBrowserServiceName)
+ if (source_info.identity.name() != mojom::kBrowserServiceName &&
+ source_info.identity.name() != mojom::kSystemServiceName) {
return;
+ }
if (interface_name == IPC::mojom::ChannelBootstrap::Name_) {
DCHECK(bootstrap_.is_valid());
@@ -367,7 +369,7 @@ void ChildThreadImpl::OnFieldTrialGroupFinalized(
const std::string& trial_name,
const std::string& group_name) {
mojom::FieldTrialRecorderPtr field_trial_recorder;
- GetConnector()->BindInterface(mojom::kBrowserServiceName,
+ GetConnector()->BindInterface(mojom::kSystemServiceName,
&field_trial_recorder);
field_trial_recorder->FieldTrialActivated(trial_name);
}
@@ -614,7 +616,7 @@ void ChildThreadImpl::ReleaseCachedFonts() {
mojom::FontCacheWin* ChildThreadImpl::GetFontCacheWin() {
if (!font_cache_win_ptr_) {
- GetConnector()->BindInterface(mojom::kBrowserServiceName,
+ GetConnector()->BindInterface(mojom::kSystemServiceName,
&font_cache_win_ptr_);
}
return font_cache_win_ptr_.get();
diff --git a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_impl_win.cc b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_impl_win.cc
index 83a2859feff..f9166904638 100644
--- a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_impl_win.cc
+++ b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_impl_win.cc
@@ -59,7 +59,7 @@ void InitializeDWriteFontProxy(service_manager::Connector* connector) {
if (g_connection_callback_override) {
dwrite_font_proxy = g_connection_callback_override->Run();
} else if (connector) {
- connector->BindInterface(mojom::kBrowserServiceName,
+ connector->BindInterface(mojom::kSystemServiceName,
mojo::MakeRequest(&dwrite_font_proxy));
}
// If |connector| is not provided, the connection to the browser will be
@@ -91,7 +91,7 @@ void InitializeDWriteFontProxy(service_manager::Connector* connector) {
// This flag can be removed when Win8.0 and earlier are no longer supported.
bool fallback_available = g_font_fallback != nullptr;
DCHECK_EQ(fallback_available,
- base::win::GetVersion() > base::win::VERSION_WIN8);
+ base::win::GetVersion() > base::win::Version::WIN8);
blink::WebFontRendering::SetUseSkiaFontFallback(fallback_available);
}
diff --git a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
index c28736ebd80..8b0ed34dc4b 100644
--- a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
+++ b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
@@ -369,13 +369,13 @@ blink::mojom::DWriteFontProxy& DWriteFontCollectionProxy::GetFontProxy() {
blink::mojom::DWriteFontProxyPtrInfo dwrite_font_proxy;
if (main_task_runner_->RunsTasksInCurrentSequence()) {
ChildThread::Get()->GetConnector()->BindInterface(
- mojom::kBrowserServiceName, mojo::MakeRequest(&dwrite_font_proxy));
+ mojom::kSystemServiceName, mojo::MakeRequest(&dwrite_font_proxy));
} else {
main_task_runner_->PostTask(
FROM_HERE, base::BindOnce(
[](blink::mojom::DWriteFontProxyRequest request) {
ChildThread::Get()->GetConnector()->BindInterface(
- mojom::kBrowserServiceName, std::move(request));
+ mojom::kSystemServiceName, std::move(request));
},
mojo::MakeRequest(&dwrite_font_proxy)));
}
diff --git a/chromium/content/child/font_warmup_win.cc b/chromium/content/child/font_warmup_win.cc
index 87de0591ea9..4de26d24aec 100644
--- a/chromium/content/child/font_warmup_win.cc
+++ b/chromium/content/child/font_warmup_win.cc
@@ -388,7 +388,7 @@ void PatchServiceManagerCalls() {
if (is_patched)
return;
const char* service_provider_dll =
- (base::win::GetVersion() >= base::win::VERSION_WIN8
+ (base::win::GetVersion() >= base::win::Version::WIN8
? "api-ms-win-service-management-l1-1-0.dll"
: "advapi32.dll");
diff --git a/chromium/content/child/font_warmup_win_unittest.cc b/chromium/content/child/font_warmup_win_unittest.cc
index 32b556a0827..00564b98a16 100644
--- a/chromium/content/child/font_warmup_win_unittest.cc
+++ b/chromium/content/child/font_warmup_win_unittest.cc
@@ -136,7 +136,7 @@ int CALLBACK EnumFontCallbackTest(const LOGFONT* log_font,
} // namespace
TEST_F(GDIFontEmulationTest, CreateDeleteDCSuccess) {
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ if (base::win::GetVersion() < base::win::Version::WIN8)
return;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_FALSE(!patch_data);
@@ -149,7 +149,7 @@ TEST_F(GDIFontEmulationTest, CreateDeleteDCSuccess) {
}
TEST_F(GDIFontEmulationTest, CreateUniqueDCSuccess) {
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ if (base::win::GetVersion() < base::win::Version::WIN8)
return;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
@@ -166,7 +166,7 @@ TEST_F(GDIFontEmulationTest, CreateUniqueDCSuccess) {
}
TEST_F(GDIFontEmulationTest, CreateFontSuccess) {
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ if (base::win::GetVersion() < base::win::Version::WIN8)
return;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
@@ -179,7 +179,7 @@ TEST_F(GDIFontEmulationTest, CreateFontSuccess) {
}
TEST_F(GDIFontEmulationTest, CreateFontFailure) {
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ if (base::win::GetVersion() < base::win::Version::WIN8)
return;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
@@ -190,7 +190,7 @@ TEST_F(GDIFontEmulationTest, CreateFontFailure) {
}
TEST_F(GDIFontEmulationTest, EnumFontFamilySuccess) {
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ if (base::win::GetVersion() < base::win::Version::WIN8)
return;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
@@ -204,7 +204,7 @@ TEST_F(GDIFontEmulationTest, EnumFontFamilySuccess) {
}
TEST_F(GDIFontEmulationTest, EnumFontFamilyFailure) {
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ if (base::win::GetVersion() < base::win::Version::WIN8)
return;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
@@ -218,7 +218,7 @@ TEST_F(GDIFontEmulationTest, EnumFontFamilyFailure) {
}
TEST_F(GDIFontEmulationTest, DeleteDCFailure) {
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ if (base::win::GetVersion() < base::win::Version::WIN8)
return;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
@@ -227,7 +227,7 @@ TEST_F(GDIFontEmulationTest, DeleteDCFailure) {
}
TEST_F(GDIFontEmulationTest, DeleteObjectFailure) {
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ if (base::win::GetVersion() < base::win::Version::WIN8)
return;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
@@ -236,7 +236,7 @@ TEST_F(GDIFontEmulationTest, DeleteObjectFailure) {
}
TEST_F(GDIFontEmulationTest, GetFontDataSizeSuccess) {
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ if (base::win::GetVersion() < base::win::Version::WIN8)
return;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
@@ -255,7 +255,7 @@ TEST_F(GDIFontEmulationTest, GetFontDataSizeSuccess) {
}
TEST_F(GDIFontEmulationTest, GetFontDataInvalidTagSuccess) {
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ if (base::win::GetVersion() < base::win::Version::WIN8)
return;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
@@ -273,7 +273,7 @@ TEST_F(GDIFontEmulationTest, GetFontDataInvalidTagSuccess) {
}
TEST_F(GDIFontEmulationTest, GetFontDataInvalidFontSuccess) {
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ if (base::win::GetVersion() < base::win::Version::WIN8)
return;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
@@ -285,7 +285,7 @@ TEST_F(GDIFontEmulationTest, GetFontDataInvalidFontSuccess) {
}
TEST_F(GDIFontEmulationTest, GetFontDataDataSuccess) {
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ if (base::win::GetVersion() < base::win::Version::WIN8)
return;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
diff --git a/chromium/content/child/runtime_features.cc b/chromium/content/child/runtime_features.cc
index 06bde878ad2..d292b5ac80b 100644
--- a/chromium/content/child/runtime_features.cc
+++ b/chromium/content/child/runtime_features.cc
@@ -23,6 +23,7 @@
#include "services/network/public/cpp/features.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/web_runtime_features.h"
+#include "ui/base/ui_base_features.h"
#include "ui/events/blink/blink_features.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
@@ -49,7 +50,7 @@ void SetRuntimeFeatureDefaultsForPlatform() {
#endif
#if defined(OS_WIN)
- if (base::win::GetVersion() >= base::win::VERSION_WIN10)
+ if (base::win::GetVersion() >= base::win::Version::WIN10)
WebRuntimeFeatures::EnableWebBluetooth(true);
#endif
}
@@ -66,12 +67,16 @@ void SetIndividualRuntimeFeatures(
WebRuntimeFeatures::EnableBlinkHeapIncrementalMarking(
base::FeatureList::IsEnabled(features::kBlinkHeapIncrementalMarking));
+ WebRuntimeFeatures::EnableBlinkHeapUnifiedGCScheduling(
+ base::FeatureList::IsEnabled(features::kBlinkHeapUnifiedGCScheduling));
+
if (base::FeatureList::IsEnabled(features::kBloatedRendererDetection))
WebRuntimeFeatures::EnableBloatedRendererDetection(true);
- WebRuntimeFeatures::EnableBlockingFocusWithoutUserActivation(
- base::FeatureList::IsEnabled(
- blink::features::kBlockingFocusWithoutUserActivation));
+ if (base::FeatureList::IsEnabled(
+ blink::features::kBlockingFocusWithoutUserActivation)) {
+ WebRuntimeFeatures::EnableBlockingFocusWithoutUserActivation(true);
+ }
if (command_line.HasSwitch(switches::kDisableDatabases))
WebRuntimeFeatures::EnableDatabase(false);
@@ -105,8 +110,11 @@ void SetIndividualRuntimeFeatures(
if (command_line.HasSwitch(switches::kDisableFileSystem))
WebRuntimeFeatures::EnableFileSystem(false);
- if (!command_line.HasSwitch(switches::kDisableAcceleratedJpegDecoding))
- WebRuntimeFeatures::EnableDecodeToYUV(true);
+ if (!command_line.HasSwitch(switches::kDisableYUVImageDecoding) &&
+ base::FeatureList::IsEnabled(
+ blink::features::kDecodeLossyWebPImagesToYUV)) {
+ WebRuntimeFeatures::EnableDecodeLossyWebPImagesToYUV(true);
+ }
#if defined(SUPPORT_WEBGL2_COMPUTE_CONTEXT)
if (command_line.HasSwitch(switches::kEnableWebGL2ComputeContext)) {
@@ -170,8 +178,11 @@ void SetIndividualRuntimeFeatures(
WebRuntimeFeatures::EnableNetInfoDownlinkMax(true);
}
- if (command_line.HasSwitch(switches::kReducedReferrerGranularity))
- WebRuntimeFeatures::EnableReducedReferrerGranularity(true);
+ WebRuntimeFeatures::EnableReducedReferrerGranularity(
+ base::FeatureList::IsEnabled(features::kReducedReferrerGranularity));
+
+ if (base::FeatureList::IsEnabled(features::kPeriodicBackgroundSync))
+ WebRuntimeFeatures::EnablePeriodicBackgroundSync(true);
if (command_line.HasSwitch(switches::kDisablePermissionsAPI))
WebRuntimeFeatures::EnablePermissionsAPI(false);
@@ -184,6 +195,9 @@ void SetIndividualRuntimeFeatures(
if (command_line.HasSwitch(switches::kEnableUnsafeWebGPU))
WebRuntimeFeatures::EnableWebGPU(true);
+ if (command_line.HasSwitch(switches::kEnableWebGLSwapChain))
+ WebRuntimeFeatures::EnableWebGLSwapChain(true);
+
if (command_line.HasSwitch(switches::kEnableWebVR))
WebRuntimeFeatures::EnableWebVR(true);
@@ -193,6 +207,9 @@ void SetIndividualRuntimeFeatures(
if (base::FeatureList::IsEnabled(features::kWebXrHitTest))
WebRuntimeFeatures::EnableWebXRHitTest(true);
+ if (base::FeatureList::IsEnabled(features::kWebXrPlaneDetection))
+ WebRuntimeFeatures::EnableWebXRPlaneDetection(true);
+
if (command_line.HasSwitch(switches::kDisablePresentationAPI))
WebRuntimeFeatures::EnablePresentationAPI(false);
@@ -228,6 +245,16 @@ void SetIndividualRuntimeFeatures(
base::FeatureList::IsEnabled(blink::features::kBlinkGenPropertyTrees) ||
enable_experimental_web_platform_features);
+ WebRuntimeFeatures::EnableFeatureFromString(
+ "CSSBackdropFilter",
+ base::FeatureList::IsEnabled(blink::features::kCSSBackdropFilter) ||
+ enable_experimental_web_platform_features);
+
+ WebRuntimeFeatures::EnableFeatureFromString(
+ "FastBorderRadius",
+ base::FeatureList::IsEnabled(blink::features::kFastBorderRadius) ||
+ enable_experimental_web_platform_features);
+
WebRuntimeFeatures::EnablePassiveDocumentEventListeners(
base::FeatureList::IsEnabled(features::kPassiveDocumentEventListeners));
@@ -236,10 +263,6 @@ void SetIndividualRuntimeFeatures(
features::kPassiveDocumentWheelEventListeners));
WebRuntimeFeatures::EnableFeatureFromString(
- "FontCacheScaling",
- base::FeatureList::IsEnabled(features::kFontCacheScaling));
-
- WebRuntimeFeatures::EnableFeatureFromString(
"FontSrcLocalMatching",
base::FeatureList::IsEnabled(features::kFontSrcLocalMatching));
@@ -291,9 +314,6 @@ void SetIndividualRuntimeFeatures(
if (base::FeatureList::IsEnabled(features::kCompositorTouchAction))
WebRuntimeFeatures::EnableCompositorTouchAction(true);
- if (base::FeatureList::IsEnabled(features::kCSSFragmentIdentifiers))
- WebRuntimeFeatures::EnableCSSFragmentIdentifiers(true);
-
if (!base::FeatureList::IsEnabled(features::kGenericSensor))
WebRuntimeFeatures::EnableGenericSensor(false);
@@ -343,8 +363,8 @@ void SetIndividualRuntimeFeatures(
if (base::FeatureList::IsEnabled(features::kBuiltInModuleKvStorage))
WebRuntimeFeatures::EnableBuiltInModuleKvStorage(true);
- if (base::FeatureList::IsEnabled(blink::features::kLayoutNG))
- WebRuntimeFeatures::EnableLayoutNG(true);
+ WebRuntimeFeatures::EnableFeatureFromString(
+ "LayoutNG", base::FeatureList::IsEnabled(blink::features::kLayoutNG));
WebRuntimeFeatures::EnableLazyInitializeMediaControls(
base::FeatureList::IsEnabled(features::kLazyInitializeMediaControls));
@@ -359,9 +379,6 @@ void SetIndividualRuntimeFeatures(
WebRuntimeFeatures::EnableAllowActivationDelegationAttr(
base::FeatureList::IsEnabled(features::kAllowActivationDelegationAttr));
- WebRuntimeFeatures::EnableModernMediaControls(
- base::FeatureList::IsEnabled(media::kUseModernMediaControls));
-
WebRuntimeFeatures::EnableScriptStreamingOnPreload(
base::FeatureList::IsEnabled(features::kScriptStreamingOnPreload));
@@ -377,18 +394,27 @@ void SetIndividualRuntimeFeatures(
if (base::FeatureList::IsEnabled(features::kLazyImageVisibleLoadTimeMetrics))
WebRuntimeFeatures::EnableLazyImageVisibleLoadTimeMetrics(true);
- WebRuntimeFeatures::EnableRestrictDeviceSensorEventsToSecureContexts(
- base::FeatureList::IsEnabled(
- blink::features::kRestrictDeviceSensorEventsToSecureContexts));
-
- WebRuntimeFeatures::EnableRestrictLazyFrameLoadingToDataSaver(
+ WebRuntimeFeatures::EnableAutomaticLazyFrameLoading(
+ base::GetFieldTrialParamByFeatureAsBool(
+ features::kLazyFrameLoading, "automatic-lazy-load-frames-enabled",
+ false));
+ WebRuntimeFeatures::EnableRestrictAutomaticLazyFrameLoadingToDataSaver(
base::GetFieldTrialParamByFeatureAsBool(
features::kLazyFrameLoading,
"restrict-lazy-load-frames-to-data-saver-only", false));
- WebRuntimeFeatures::EnableRestrictLazyImageLoadingToDataSaver(
+
+ WebRuntimeFeatures::EnableAutomaticLazyImageLoading(
+ base::GetFieldTrialParamByFeatureAsBool(
+ features::kLazyImageLoading, "automatic-lazy-load-images-enabled",
+ false));
+ WebRuntimeFeatures::EnableRestrictAutomaticLazyImageLoadingToDataSaver(
base::GetFieldTrialParamByFeatureAsBool(
features::kLazyImageLoading,
"restrict-lazy-load-images-to-data-saver-only", false));
+ WebRuntimeFeatures::EnableLazyImageLoadingMetadataFetch(
+ base::GetFieldTrialParamByFeatureAsBool(
+ features::kLazyImageLoading, "enable-lazy-load-images-metadata-fetch",
+ true));
WebRuntimeFeatures::EnablePictureInPicture(
base::FeatureList::IsEnabled(media::kPictureInPicture));
@@ -409,9 +435,6 @@ void SetIndividualRuntimeFeatures(
if (base::FeatureList::IsEnabled(features::kFeaturePolicyForSandbox))
WebRuntimeFeatures::EnableFeaturePolicyForSandbox(true);
- if (base::FeatureList::IsEnabled(features::kPageLifecycle))
- WebRuntimeFeatures::EnablePageLifecycle(true);
-
#if defined(OS_ANDROID)
if (base::android::BuildInfo::GetInstance()->sdk_int() >=
base::android::SDK_VERSION_P) {
@@ -423,8 +446,8 @@ void SetIndividualRuntimeFeatures(
if (command_line.HasSwitch(switches::kEnableAccessibilityObjectModel))
WebRuntimeFeatures::EnableAccessibilityObjectModel(true);
- if (base::FeatureList::IsEnabled(blink::features::kNativeFilesystemAPI))
- WebRuntimeFeatures::EnableFeatureFromString("WritableFiles", true);
+ if (base::FeatureList::IsEnabled(blink::features::kNativeFileSystemAPI))
+ WebRuntimeFeatures::EnableFeatureFromString("NativeFileSystem", true);
if (base::FeatureList::IsEnabled(
blink::features::kForbidSyncXHRInPageDismissal)) {
@@ -489,11 +512,31 @@ void SetIndividualRuntimeFeatures(
if (!base::FeatureList::IsEnabled(features::kIdleDetection))
WebRuntimeFeatures::EnableIdleDetection(false);
+ WebRuntimeFeatures::EnableSkipTouchEventFilter(
+ base::FeatureList::IsEnabled(features::kSkipTouchEventFilter));
+
WebRuntimeFeatures::EnableStaleWhileRevalidate(
base::FeatureList::IsEnabled(features::kStaleWhileRevalidate));
- WebRuntimeFeatures::EnableSkipTouchEventFilter(
- base::FeatureList::IsEnabled(features::kSkipTouchEventFilter));
+ if (!base::FeatureList::IsEnabled(features::kSmsReceiver))
+ WebRuntimeFeatures::EnableSmsReceiver(false);
+
+ WebRuntimeFeatures::EnableDisplayLocking(
+ base::FeatureList::IsEnabled(blink::features::kDisplayLocking));
+
+ WebRuntimeFeatures::EnableFormControlsRefresh(
+ features::IsFormControlsRefreshEnabled());
+
+ if (base::FeatureList::IsEnabled(
+ blink::features::kAudioWorkletRealtimeThread)) {
+ WebRuntimeFeatures::EnableFeatureFromString(
+ "AudioWorkletRealtimeThread", true);
+ }
+
+ if (!base::FeatureList::IsEnabled(
+ features::kPauseExecutionContextOnBackgroundFreeze)) {
+ WebRuntimeFeatures::EnablePauseExecutionContextOnBackgroundFreeze(false);
+ }
}
} // namespace
diff --git a/chromium/content/child/webthemeengine_impl_android.cc b/chromium/content/child/webthemeengine_impl_android.cc
index f4602f53b19..e767d24d474 100644
--- a/chromium/content/child/webthemeengine_impl_android.cc
+++ b/chromium/content/child/webthemeengine_impl_android.cc
@@ -166,7 +166,9 @@ static void GetNativeThemeExtraParams(
}
}
-blink::WebSize WebThemeEngineImpl::GetSize(WebThemeEngine::Part part) {
+WebThemeEngineAndroid::~WebThemeEngineAndroid() = default;
+
+blink::WebSize WebThemeEngineAndroid::GetSize(WebThemeEngine::Part part) {
switch (part) {
case WebThemeEngine::kPartScrollbarHorizontalThumb:
case WebThemeEngine::kPartScrollbarVerticalThumb: {
@@ -184,7 +186,7 @@ blink::WebSize WebThemeEngineImpl::GetSize(WebThemeEngine::Part part) {
}
}
-void WebThemeEngineImpl::GetOverlayScrollbarStyle(ScrollbarStyle* style) {
+void WebThemeEngineAndroid::GetOverlayScrollbarStyle(ScrollbarStyle* style) {
// TODO(bokan): Android scrollbars on non-composited scrollers don't
// currently fade out so the fadeOutDuration and Delay Now that this has
// been added into Blink for other platforms we should plumb that through for
@@ -202,7 +204,7 @@ void WebThemeEngineImpl::GetOverlayScrollbarStyle(ScrollbarStyle* style) {
}
}
-void WebThemeEngineImpl::Paint(
+void WebThemeEngineAndroid::Paint(
cc::PaintCanvas* canvas,
WebThemeEngine::Part part,
WebThemeEngine::State state,
diff --git a/chromium/content/child/webthemeengine_impl_android.h b/chromium/content/child/webthemeengine_impl_android.h
index ede02ba2aea..9fb867bfe16 100644
--- a/chromium/content/child/webthemeengine_impl_android.h
+++ b/chromium/content/child/webthemeengine_impl_android.h
@@ -9,9 +9,10 @@
namespace content {
-class WebThemeEngineImpl : public blink::WebThemeEngine {
+class WebThemeEngineAndroid : public blink::WebThemeEngine {
public:
// WebThemeEngine methods:
+ ~WebThemeEngineAndroid() override;
blink::WebSize GetSize(blink::WebThemeEngine::Part) override;
void GetOverlayScrollbarStyle(
blink::WebThemeEngine::ScrollbarStyle*) override;
diff --git a/chromium/content/child/webthemeengine_impl_default.cc b/chromium/content/child/webthemeengine_impl_default.cc
index ecda4fe4b12..9aba2a58c8f 100644
--- a/chromium/content/child/webthemeengine_impl_default.cc
+++ b/chromium/content/child/webthemeengine_impl_default.cc
@@ -203,7 +203,9 @@ static void GetNativeThemeExtraParams(
}
}
-blink::WebSize WebThemeEngineImpl::GetSize(WebThemeEngine::Part part) {
+WebThemeEngineDefault::~WebThemeEngineDefault() = default;
+
+blink::WebSize WebThemeEngineDefault::GetSize(WebThemeEngine::Part part) {
ui::NativeTheme::ExtraParams extra;
ui::NativeTheme::Part native_theme_part = NativeThemePart(part);
#if defined(OS_WIN)
@@ -228,7 +230,7 @@ blink::WebSize WebThemeEngineImpl::GetSize(WebThemeEngine::Part part) {
native_theme_part, ui::NativeTheme::kNormal, extra);
}
-void WebThemeEngineImpl::Paint(
+void WebThemeEngineDefault::Paint(
cc::PaintCanvas* canvas,
WebThemeEngine::Part part,
WebThemeEngine::State state,
@@ -242,7 +244,7 @@ void WebThemeEngineImpl::Paint(
native_theme_extra_params);
}
-void WebThemeEngineImpl::GetOverlayScrollbarStyle(ScrollbarStyle* style) {
+void WebThemeEngineDefault::GetOverlayScrollbarStyle(ScrollbarStyle* style) {
style->fade_out_delay = ui::kOverlayScrollbarFadeDelay;
style->fade_out_duration = ui::kOverlayScrollbarFadeDuration;
// The other fields in this struct are used only on Android to draw solid
@@ -250,24 +252,24 @@ void WebThemeEngineImpl::GetOverlayScrollbarStyle(ScrollbarStyle* style) {
// NativeTheme so these fields are unused.
}
-bool WebThemeEngineImpl::SupportsNinePatch(Part part) const {
+bool WebThemeEngineDefault::SupportsNinePatch(Part part) const {
return ui::NativeTheme::GetInstanceForWeb()->SupportsNinePatch(
NativeThemePart(part));
}
-blink::WebSize WebThemeEngineImpl::NinePatchCanvasSize(Part part) const {
+blink::WebSize WebThemeEngineDefault::NinePatchCanvasSize(Part part) const {
return ui::NativeTheme::GetInstanceForWeb()->GetNinePatchCanvasSize(
NativeThemePart(part));
}
-blink::WebRect WebThemeEngineImpl::NinePatchAperture(Part part) const {
+blink::WebRect WebThemeEngineDefault::NinePatchAperture(Part part) const {
return ui::NativeTheme::GetInstanceForWeb()->GetNinePatchAperture(
NativeThemePart(part));
}
#if defined(OS_WIN)
// static
-void WebThemeEngineImpl::cacheScrollBarMetrics(
+void WebThemeEngineDefault::cacheScrollBarMetrics(
int32_t vertical_scroll_bar_width,
int32_t horizontal_scroll_bar_height,
int32_t vertical_arrow_bitmap_height,
diff --git a/chromium/content/child/webthemeengine_impl_default.h b/chromium/content/child/webthemeengine_impl_default.h
index ebe4c362e5f..51e0720037d 100644
--- a/chromium/content/child/webthemeengine_impl_default.h
+++ b/chromium/content/child/webthemeengine_impl_default.h
@@ -12,9 +12,10 @@
namespace content {
-class WebThemeEngineImpl : public blink::WebThemeEngine {
+class WebThemeEngineDefault : public blink::WebThemeEngine {
public:
// WebThemeEngine methods:
+ ~WebThemeEngineDefault() override;
blink::WebSize GetSize(blink::WebThemeEngine::Part) override;
void Paint(cc::PaintCanvas* canvas,
blink::WebThemeEngine::Part part,
diff --git a/chromium/content/child/webthemeengine_impl_mac.h b/chromium/content/child/webthemeengine_impl_mac.h
index e63b62f4464..29e31609233 100644
--- a/chromium/content/child/webthemeengine_impl_mac.h
+++ b/chromium/content/child/webthemeengine_impl_mac.h
@@ -9,7 +9,9 @@
namespace content {
-class WebThemeEngineImpl : public blink::WebThemeEngine {
+class WebThemeEngineMac : public blink::WebThemeEngine {
+ public:
+ ~WebThemeEngineMac() override {}
};
} // namespace content
diff --git a/chromium/content/common/BUILD.gn b/chromium/content/common/BUILD.gn
index 775996a26f5..a5a15ca2363 100644
--- a/chromium/content/common/BUILD.gn
+++ b/chromium/content/common/BUILD.gn
@@ -13,6 +13,7 @@ import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
import("features.gni")
if (is_mac) {
import("//build/config/mac/mac_sdk.gni")
+ import("//content/public/app/mac_helpers.gni")
}
# For feature flags internal to content. See content/public/common:features
@@ -42,6 +43,8 @@ source_set("common") {
"android/gin_java_bridge_value.h",
"android/hash_set.cc",
"android/hash_set.h",
+ "android/surface_wrapper.cc",
+ "android/surface_wrapper.h",
"android/sync_compositor_statics.cc",
"android/sync_compositor_statics.h",
"android/use_zoom_for_dsf_policy_android.cc",
@@ -92,7 +95,6 @@ source_set("common") {
"cursors/webcursor_aurax11.cc",
"cursors/webcursor_mac.mm",
"cursors/webcursor_ozone.cc",
- "date_time_suggestion.h",
"dom_storage/dom_storage_map.cc",
"dom_storage/dom_storage_map.h",
"dom_storage/dom_storage_messages.h",
@@ -189,8 +191,6 @@ source_set("common") {
"navigation_gesture.h",
"navigation_params.cc",
"navigation_params.h",
- "navigation_subresource_loader_params.cc",
- "navigation_subresource_loader_params.h",
"net/record_load_histograms.cc",
"net/record_load_histograms.h",
"net/url_request_service_worker_data.cc",
@@ -211,6 +211,8 @@ source_set("common") {
"possibly_associated_interface_ptr.h",
"possibly_associated_interface_ptr_info.h",
"possibly_associated_wrapper_shared_url_loader_factory.h",
+ "prefetched_signed_exchange_info.cc",
+ "prefetched_signed_exchange_info.h",
"process_type.cc",
"render_widget_surface_properties.cc",
"render_widget_surface_properties.h",
@@ -364,7 +366,10 @@ source_set("common") {
}
if (is_mac) {
- deps += [ "//sandbox/mac:seatbelt" ]
+ deps += [
+ ":mac_helpers",
+ "//sandbox/mac:seatbelt",
+ ]
}
if (is_android) {
@@ -480,7 +485,6 @@ mojom("mojo_bindings") {
"input/input_handler.mojom",
"input/input_injector.mojom",
"input/synchronous_compositor.mojom",
- "manifest_observer.mojom",
"media/peer_connection_tracker.mojom",
"media/renderer_audio_input_stream_factory.mojom",
"media/renderer_audio_output_stream_factory.mojom",
@@ -488,23 +492,14 @@ mojom("mojo_bindings") {
"navigation_client.mojom",
"navigation_params.mojom",
"page_state.mojom",
- "push_messaging.mojom",
"render_frame_message_filter.mojom",
"render_frame_metadata.mojom",
"render_message_filter.mojom",
- "render_widget_window_tree_client_factory.mojom",
"renderer.mojom",
"renderer_host.mojom",
"widget.mojom",
]
- if (is_mac) {
- sources += [
- "render_widget_host_ns_view.mojom",
- "sandbox_support_mac.mojom",
- ]
- }
-
enabled_features = []
if (enable_ipc_logging) {
enabled_features += [ "ipc_logging" ]
@@ -530,13 +525,14 @@ mojom("mojo_bindings") {
"//services/viz/public/interfaces",
"//services/ws/public/mojom",
"//skia/public/interfaces",
- "//third_party/blink/public:mojo_bindings",
"//third_party/blink/public/mojom:mojom_core",
+ "//third_party/blink/public/mojom:web_bluetooth_mojo_bindings",
"//third_party/blink/public/mojom:web_feature_mojo_bindings",
"//ui/base/ime/mojo",
"//ui/base/mojo",
"//ui/events/mojo:interfaces",
"//ui/gfx/geometry/mojo",
+ "//ui/gfx/image/mojo:interfaces",
"//ui/gfx/mojo",
"//ui/gfx/range/mojo",
"//ui/latency/mojo:interfaces",
@@ -544,6 +540,15 @@ mojom("mojo_bindings") {
"//url/mojom:url_mojom_origin",
]
+ if (is_mac) {
+ sources += [
+ "render_widget_host_ns_view.mojom",
+ "sandbox_support_mac.mojom",
+ "web_contents_ns_view_bridge.mojom",
+ ]
+ public_deps += [ "//ui/display/mojo:interfaces" ]
+ }
+
overridden_deps = [ "//third_party/blink/public/mojom:mojom_core" ]
component_deps = [ "//third_party/blink/public/common" ]
@@ -552,3 +557,35 @@ mojom("mojo_bindings") {
export_define = "CONTENT_IMPLEMENTATION=1"
export_header = "content/common/content_export.h"
}
+
+if (is_mac) {
+ source_set("mac_helpers") {
+ _lines = [
+ "// This file is generated by " +
+ get_label_info(target_name, "label_no_toolchain"),
+ "",
+ "#ifndef GEN_CONTENT_COMMON_MAC_HELPERS_H_",
+ "#define GEN_CONTENT_COMMON_MAC_HELPERS_H_",
+ "",
+ "namespace content {",
+ "",
+ ]
+ foreach(helper_params, content_mac_helpers) {
+ _lines += [ "const char kMacHelperSuffix_${helper_params[0]}[] = \"${helper_params[2]}\";" ]
+ }
+ _lines += [
+ "",
+ "} // namespace content",
+ "",
+ "#endif // GEN_CONTENT_COMMON_MAC_HELPERS_H_",
+ ]
+
+ _file = "$target_gen_dir/mac_helpers.h"
+
+ write_file(_file, _lines)
+
+ sources = [
+ _file,
+ ]
+ }
+}
diff --git a/chromium/content/common/DEPS b/chromium/content/common/DEPS
index b820802ca51..150a1db1312 100644
--- a/chromium/content/common/DEPS
+++ b/chromium/content/common/DEPS
@@ -23,6 +23,7 @@ include_rules = [
"+third_party/blink/public/mojom",
"+third_party/blink/public/platform/WebAddressSpace.h",
"+third_party/blink/public/platform/web_content_security_policy.h",
+ "+third_party/blink/public/platform/web_cursor_info.h",
"+third_party/blink/public/platform/web_drag_operation.h",
"+third_party/blink/public/platform/web_float_point.h",
"+third_party/blink/public/platform/web_float_rect.h",
@@ -49,7 +50,6 @@ include_rules = [
"+third_party/blink/public/platform/web_touch_event.h",
"+third_party/blink/public/platform/linux/web_fallback_font.h",
"+third_party/blink/public/platform/mac/web_scrollbar_theme.h",
- "+third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h",
"+third_party/blink/public/platform/modules/device_orientation/WebDeviceMotionData.h",
"+third_party/blink/public/platform/modules/device_orientation/WebDeviceOrientationData.h",
"+third_party/blink/public/platform/modules/mediastream/media_devices.mojom.h",
diff --git a/chromium/content/common/android/surface_wrapper.cc b/chromium/content/common/android/surface_wrapper.cc
new file mode 100644
index 00000000000..b7704b7a64c
--- /dev/null
+++ b/chromium/content/common/android/surface_wrapper.cc
@@ -0,0 +1,30 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/android/surface_wrapper.h"
+
+#include "jni/SurfaceWrapper_jni.h"
+
+namespace content {
+
+base::android::ScopedJavaLocalRef<jobject> JNI_SurfaceWrapper_create(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& surface,
+ jboolean canBeUsedWithSurfaceControl) {
+ return Java_SurfaceWrapper_create(env, surface, canBeUsedWithSurfaceControl);
+}
+
+jboolean JNI_SurfaceWrapper_canBeUsedWithSurfaceControl(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& obj) {
+ return Java_SurfaceWrapper_canBeUsedWithSurfaceControl(env, obj);
+}
+
+base::android::ScopedJavaLocalRef<jobject> JNI_SurfaceWrapper_getSurface(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& obj) {
+ return Java_SurfaceWrapper_getSurface(env, obj);
+}
+
+} // namespace content.
diff --git a/chromium/content/common/android/surface_wrapper.h b/chromium/content/common/android/surface_wrapper.h
new file mode 100644
index 00000000000..f5236468ff9
--- /dev/null
+++ b/chromium/content/common/android/surface_wrapper.h
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_ANDROID_SURFACE_WRAPPER_H_
+#define CONTENT_COMMON_ANDROID_SURFACE_WRAPPER_H_
+
+#include "base/android/scoped_java_ref.h"
+
+namespace content {
+
+base::android::ScopedJavaLocalRef<jobject> JNI_SurfaceWrapper_create(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& surface,
+ jboolean canBeUsedWithSurfaceControl);
+
+jboolean JNI_SurfaceWrapper_canBeUsedWithSurfaceControl(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& obj);
+
+base::android::ScopedJavaLocalRef<jobject> JNI_SurfaceWrapper_getSurface(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& obj);
+
+} // namespace content
+
+#endif // CONTENT_COMMON_ANDROID_SURFACE_WRAPPER_H_
diff --git a/chromium/content/common/bluetooth/OWNERS b/chromium/content/common/bluetooth/OWNERS
index a8c3f3d3d47..e41d91ab572 100644
--- a/chromium/content/common/bluetooth/OWNERS
+++ b/chromium/content/common/bluetooth/OWNERS
@@ -5,5 +5,8 @@ file://content/browser/bluetooth/OWNERS
per-file *_struct_traits*.*=set noparent
per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *.typemap=set noparent
+per-file *.typemap=file://ipc/SECURITY_OWNERS
+
# TEAM: web-bluetooth@chromium.org
# COMPONENT: Blink>Bluetooth
diff --git a/chromium/content/common/bluetooth/web_bluetooth_device_id.typemap b/chromium/content/common/bluetooth/web_bluetooth_device_id.typemap
index 59ed7ecc31c..01511724980 100644
--- a/chromium/content/common/bluetooth/web_bluetooth_device_id.typemap
+++ b/chromium/content/common/bluetooth/web_bluetooth_device_id.typemap
@@ -2,8 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-mojom =
- "//third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom"
+mojom = "//third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom"
public_headers = [ "//content/common/bluetooth/web_bluetooth_device_id.h" ]
traits_headers =
[ "//content/common/bluetooth/web_bluetooth_device_id_struct_traits.h" ]
diff --git a/chromium/content/common/bluetooth/web_bluetooth_device_id_struct_traits.h b/chromium/content/common/bluetooth/web_bluetooth_device_id_struct_traits.h
index 1ce512bff0a..71bf2f90d37 100644
--- a/chromium/content/common/bluetooth/web_bluetooth_device_id_struct_traits.h
+++ b/chromium/content/common/bluetooth/web_bluetooth_device_id_struct_traits.h
@@ -8,7 +8,7 @@
#include <string>
#include "content/common/bluetooth/web_bluetooth_device_id.h"
-#include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
namespace mojo {
diff --git a/chromium/content/common/browser_plugin/browser_plugin_messages.h b/chromium/content/common/browser_plugin/browser_plugin_messages.h
index 896c8a7c0e2..d876a1d9f88 100644
--- a/chromium/content/common/browser_plugin/browser_plugin_messages.h
+++ b/chromium/content/common/browser_plugin/browser_plugin_messages.h
@@ -217,13 +217,4 @@ IPC_MESSAGE_CONTROL2(BrowserPluginMsg_SetMouseLock,
int /* browser_plugin_instance_id */,
bool /* enable */)
-#if defined(USE_AURA)
-// Sets the token that is used to embed the guest. |embed_token| is a token
-// that was generated from the window server and is expected to be supplied to
-// EmbedUsingToken().
-IPC_MESSAGE_CONTROL2(BrowserPluginMsg_SetMusEmbedToken,
- int /* browser_plugin_instance_id */,
- base::UnguessableToken /* embed_token */)
-#endif
-
#endif // CONTENT_COMMON_BROWSER_PLUGIN_BROWSER_PLUGIN_MESSAGES_H_
diff --git a/chromium/content/common/child_process_host_impl.cc b/chromium/content/common/child_process_host_impl.cc
index 160dd43f814..ca68cec3d85 100644
--- a/chromium/content/common/child_process_host_impl.cc
+++ b/chromium/content/common/child_process_host_impl.cc
@@ -34,6 +34,9 @@
#if defined(OS_LINUX)
#include "base/linux_util.h"
+#elif defined(OS_MACOSX)
+#include "base/mac/foundation_util.h"
+#include "content/common/mac_helpers.h"
#endif // OS_LINUX
namespace {
@@ -69,6 +72,34 @@ base::FilePath ChildProcessHost::GetChildPath(int flags) {
// executable.
if (child_path.empty())
base::PathService::Get(CHILD_PROCESS_EXE, &child_path);
+
+#if defined(OS_MACOSX)
+ std::string child_base_name = child_path.BaseName().value();
+
+ if (flags != CHILD_NORMAL && base::mac::AmIBundled()) {
+ // This is a specialized helper, with the |child_path| at
+ // ../Framework.framework/Versions/X/Helpers/Chromium Helper.app/Contents/
+ // MacOS/Chromium Helper. Go back up to the "Helpers" directory to select
+ // a different variant.
+ child_path = child_path.DirName().DirName().DirName().DirName();
+
+ if (flags == CHILD_RENDERER) {
+ child_base_name += kMacHelperSuffix_renderer;
+ } else if (flags == CHILD_GPU) {
+ child_base_name += kMacHelperSuffix_gpu;
+ } else if (flags == CHILD_PLUGIN) {
+ child_base_name += kMacHelperSuffix_plugin;
+ } else {
+ NOTREACHED();
+ }
+
+ child_path = child_path.Append(child_base_name + ".app")
+ .Append("Contents")
+ .Append("MacOS")
+ .Append(child_base_name);
+ }
+#endif
+
return child_path;
}
diff --git a/chromium/content/common/common_param_traits_unittest.cc b/chromium/content/common/common_param_traits_unittest.cc
index d1c49e82d62..74c2bad93b7 100644
--- a/chromium/content/common/common_param_traits_unittest.cc
+++ b/chromium/content/common/common_param_traits_unittest.cc
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/values.h"
#include "components/viz/common/surfaces/surface_info.h"
+#include "content/common/content_param_traits.h"
#include "content/common/resource_messages.h"
#include "content/public/common/content_constants.h"
#include "ipc/ipc_message.h"
@@ -301,3 +302,18 @@ TEST(IPCMessageTest, SurfaceInfo) {
ASSERT_EQ(surface_info_in, surface_info_out);
}
+
+TEST(IPCMessageTest, WebCursor) {
+ content::CursorInfo info(blink::WebCursorInfo::kTypeCustom);
+ info.custom_image.allocN32Pixels(32, 32);
+ info.hotspot = gfx::Point(10, 20);
+ info.image_scale_factor = 1.5f;
+ content::WebCursor input(info);
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::ParamTraits<content::WebCursor>::Write(&msg, input);
+
+ content::WebCursor output;
+ base::PickleIterator iter(msg);
+ ASSERT_TRUE(IPC::ParamTraits<content::WebCursor>::Read(&msg, &iter, &output));
+ EXPECT_EQ(output, input);
+}
diff --git a/chromium/content/common/content_param_traits.cc b/chromium/content/common/content_param_traits.cc
index e2e33fa3657..2791cb85858 100644
--- a/chromium/content/common/content_param_traits.cc
+++ b/chromium/content/common/content_param_traits.cc
@@ -14,6 +14,7 @@
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "content/common/frame_message_structs.h"
+#include "content/common/tab_switch_time_recorder.h"
#include "ipc/ipc_mojo_message_helper.h"
#include "ipc/ipc_mojo_param_traits.h"
#include "net/base/ip_endpoint.h"
@@ -22,12 +23,42 @@
#include "third_party/blink/public/common/messaging/transferable_message.h"
#include "third_party/blink/public/mojom/messaging/transferable_message.mojom.h"
#include "ui/accessibility/ax_mode.h"
-#include "ui/base/ui_base_features.h"
#include "ui/events/blink/web_input_event_traits.h"
-// #include "ui/gfx/ipc/geometry/gfx_param_traits.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
namespace IPC {
+void ParamTraits<content::WebCursor>::Write(base::Pickle* m,
+ const param_type& p) {
+ WriteParam(m, p.info().type);
+ if (p.info().type == blink::WebCursorInfo::kTypeCustom) {
+ WriteParam(m, p.info().hotspot);
+ WriteParam(m, p.info().image_scale_factor);
+ WriteParam(m, p.info().custom_image);
+ }
+}
+
+bool ParamTraits<content::WebCursor>::Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r) {
+ content::CursorInfo info;
+ if (!ReadParam(m, iter, &info.type))
+ return false;
+
+ if (info.type == blink::WebCursorInfo::kTypeCustom &&
+ (!ReadParam(m, iter, &info.hotspot) ||
+ !ReadParam(m, iter, &info.image_scale_factor) ||
+ !ReadParam(m, iter, &info.custom_image))) {
+ return false;
+ }
+
+ return r->SetInfo(info);
+}
+
+void ParamTraits<content::WebCursor>::Log(const param_type& p, std::string* l) {
+ l->append("<WebCursor>");
+}
+
void ParamTraits<WebInputEventPointer>::Write(base::Pickle* m,
const param_type& p) {
m->WriteData(reinterpret_cast<const char*>(p), p->size());
@@ -141,14 +172,14 @@ void ParamTraits<blink::PolicyValue>::Log(const param_type& p, std::string* l) {
}
void ParamTraits<ui::AXMode>::Write(base::Pickle* m, const param_type& p) {
- IPC::WriteParam(m, p.mode());
+ WriteParam(m, p.mode());
}
bool ParamTraits<ui::AXMode>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
uint32_t value;
- if (!IPC::ReadParam(m, iter, &value))
+ if (!ReadParam(m, iter, &value))
return false;
*r = ui::AXMode(value);
return true;
@@ -199,8 +230,7 @@ void ParamTraits<scoped_refptr<storage::BlobHandle>>::Log(const param_type& p,
void ParamTraits<content::FrameMsg_ViewChanged_Params>::Write(
base::Pickle* m,
const param_type& p) {
- DCHECK(features::IsMultiProcessMash() ||
- (p.frame_sink_id.has_value() && p.frame_sink_id->is_valid()));
+ DCHECK(p.frame_sink_id.is_valid());
WriteParam(m, p.frame_sink_id);
}
@@ -210,8 +240,7 @@ bool ParamTraits<content::FrameMsg_ViewChanged_Params>::Read(
param_type* r) {
if (!ReadParam(m, iter, &(r->frame_sink_id)))
return false;
- if (!features::IsMultiProcessMash() &&
- (!r->frame_sink_id || !r->frame_sink_id->is_valid())) {
+ if (!r->frame_sink_id.is_valid()) {
NOTREACHED();
return false;
}
@@ -484,6 +513,59 @@ void ParamTraits<viz::SurfaceInfo>::Log(const param_type& p, std::string* l) {
l->append(")");
}
+void ParamTraits<net::SHA256HashValue>::Write(base::Pickle* m,
+ const param_type& p) {
+ m->WriteData(reinterpret_cast<const char*>(p.data), sizeof(p.data));
+}
+
+bool ParamTraits<net::SHA256HashValue>::Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r) {
+ const char* data;
+ int data_length;
+ if (!iter->ReadData(&data, &data_length)) {
+ NOTREACHED();
+ return false;
+ }
+ if (data_length != sizeof(r->data)) {
+ NOTREACHED();
+ return false;
+ }
+ memcpy(r->data, data, sizeof(r->data));
+ return true;
+}
+
+void ParamTraits<net::SHA256HashValue>::Log(const param_type& p,
+ std::string* l) {
+ l->append("<SHA256HashValue>");
+}
+
+void ParamTraits<content::RecordTabSwitchTimeRequest>::Write(
+ base::Pickle* m,
+ const param_type& p) {
+ WriteParam(m, p.tab_switch_start_time);
+ WriteParam(m, p.destination_is_loaded);
+ WriteParam(m, p.destination_is_frozen);
+}
+
+bool ParamTraits<content::RecordTabSwitchTimeRequest>::Read(
+ const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r) {
+ if (!ReadParam(m, iter, &r->tab_switch_start_time) ||
+ !ReadParam(m, iter, &r->destination_is_loaded) ||
+ !ReadParam(m, iter, &r->destination_is_frozen)) {
+ return false;
+ }
+
+ return true;
+}
+
+void ParamTraits<content::RecordTabSwitchTimeRequest>::Log(const param_type& p,
+ std::string* l) {
+ l->append("<content::RecordTabSwitchTimeRequest>");
+}
+
} // namespace IPC
// Generate param traits write methods.
diff --git a/chromium/content/common/content_param_traits.h b/chromium/content/common/content_param_traits.h
index c9b0d877d62..cc59887e298 100644
--- a/chromium/content/common/content_param_traits.h
+++ b/chromium/content/common/content_param_traits.h
@@ -17,6 +17,7 @@
#include "content/common/content_param_traits_macros.h"
#include "content/common/cursors/webcursor.h"
#include "ipc/ipc_mojo_param_traits.h"
+#include "net/base/hash_value.h"
#include "storage/common/blob_storage/blob_handle.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/accessibility/ax_mode.h"
@@ -29,6 +30,7 @@ struct TransferableMessage;
namespace content {
struct FrameMsg_ViewChanged_Params;
+struct RecordTabSwitchTimeRequest;
}
namespace viz {
@@ -42,17 +44,13 @@ class SurfaceInfo;
namespace IPC {
template <>
-struct ParamTraits<content::WebCursor> {
+struct CONTENT_EXPORT ParamTraits<content::WebCursor> {
typedef content::WebCursor param_type;
- static void Write(base::Pickle* m, const param_type& p) { p.Serialize(m); }
+ static void Write(base::Pickle* m, const param_type& p);
static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
- param_type* r) {
- return r->Deserialize(m, iter);
- }
- static void Log(const param_type& p, std::string* l) {
- l->append("<WebCursor>");
- }
+ param_type* r);
+ static void Log(const param_type& p, std::string* l);
};
typedef const blink::WebInputEvent* WebInputEventPointer;
@@ -179,6 +177,26 @@ struct CONTENT_EXPORT ParamTraits<viz::SurfaceInfo> {
static void Log(const param_type& p, std::string* l);
};
+template <>
+struct CONTENT_EXPORT ParamTraits<net::SHA256HashValue> {
+ typedef net::SHA256HashValue param_type;
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct CONTENT_EXPORT ParamTraits<content::RecordTabSwitchTimeRequest> {
+ using param_type = content::RecordTabSwitchTimeRequest;
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
} // namespace IPC
#endif // CONTENT_COMMON_CONTENT_PARAM_TRAITS_H_
diff --git a/chromium/content/common/content_param_traits_macros.h b/chromium/content/common/content_param_traits_macros.h
index 82b2c542284..b3ff82a3853 100644
--- a/chromium/content/common/content_param_traits_macros.h
+++ b/chromium/content/common/content_param_traits_macros.h
@@ -18,6 +18,7 @@
#include "third_party/blink/public/mojom/csp/content_security_policy.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/platform/web_content_security_policy.h"
+#include "third_party/blink/public/platform/web_cursor_info.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/web/web_ime_text_span.h"
#include "ui/gfx/gpu_memory_buffer.h"
@@ -37,6 +38,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::WebContentSecurityPolicySource,
blink::kWebContentSecurityPolicySourceLast)
IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::ContentSecurityPolicyType,
blink::mojom::ContentSecurityPolicyType::kMaxValue)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebCursorInfo::Type,
+ blink::WebCursorInfo::Type::kTypeMaxValue)
IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebInputEvent::Type,
blink::WebInputEvent::kTypeFirst,
blink::WebInputEvent::kTypeLast)
diff --git a/chromium/content/common/content_security_policy/csp_source_list_unittest.cc b/chromium/content/common/content_security_policy/csp_source_list_unittest.cc
index 826bf429062..009e53d0d33 100644
--- a/chromium/content/common/content_security_policy/csp_source_list_unittest.cc
+++ b/chromium/content/common/content_security_policy/csp_source_list_unittest.cc
@@ -4,6 +4,7 @@
#include "content/common/content_security_policy/csp_source_list.h"
#include "content/common/content_security_policy/csp_context.h"
+#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -95,16 +96,16 @@ TEST(CSPSourceList, AllowStarAndSelf) {
TEST(CSPSourceList, AllowSelfWithUnspecifiedPort) {
CSPContext context;
- context.SetSelf(url::Origin::Create(GURL("chrome://print")));
+ context.SetSelf(url::Origin::Create(GetWebUIURL("print")));
CSPSourceList source_list(true, // allow_self
false, // allow_star
false, // allow_redirects
std::vector<CSPSource>()); // source_list
- EXPECT_TRUE(
- Allow(source_list,
- GURL("chrome://print/pdf/index.html?chrome://print/1/0/print.pdf"),
- &context));
+ EXPECT_TRUE(Allow(source_list,
+ GURL(GetWebUIURLString("print/pdf/index.html?") +
+ GetWebUIURLString("print/1/0/print.pdf")),
+ &context));
}
TEST(CSPSourceList, AllowNone) {
diff --git a/chromium/content/common/cursors/OWNERS b/chromium/content/common/cursors/OWNERS
index 24f80504728..180664346a3 100644
--- a/chromium/content/common/cursors/OWNERS
+++ b/chromium/content/common/cursors/OWNERS
@@ -1 +1,2 @@
bsep@chromium.org
+msw@chromium.org
diff --git a/chromium/content/common/cursors/webcursor.cc b/chromium/content/common/cursors/webcursor.cc
index 1ac3bb9b9d3..3d7c97ac174 100644
--- a/chromium/content/common/cursors/webcursor.cc
+++ b/chromium/content/common/cursors/webcursor.cc
@@ -7,37 +7,16 @@
#include <algorithm>
#include "base/logging.h"
-#include "base/pickle.h"
#include "build/build_config.h"
-#include "third_party/blink/public/platform/web_image.h"
-#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
-
-using blink::WebCursorInfo;
-
-constexpr int kMaxSize = 1024;
namespace content {
-namespace {
-
-// Checks for a reasonable value of a |CursorInfo::image_scale_factor|.
-bool IsReasonableScale(float scale) {
- return scale >= 0.01f && scale <= 100.f;
-}
-
-} // namespace
-
WebCursor::~WebCursor() {
CleanupPlatformData();
}
-WebCursor::WebCursor(const CursorInfo& info) : info_(info) {
- DCHECK(IsReasonableScale(info.image_scale_factor)) << info.image_scale_factor;
- DCHECK_LE(info.custom_image.width(), kMaxSize);
- DCHECK_LE(info.custom_image.height(), kMaxSize);
- DCHECK_LE(info.custom_image.width() / info.image_scale_factor, kMaxSize);
- DCHECK_LE(info.custom_image.height() / info.image_scale_factor, kMaxSize);
- ClampHotspot();
+WebCursor::WebCursor(const CursorInfo& info) {
+ SetInfo(info);
}
WebCursor::WebCursor(const WebCursor& other) {
@@ -50,48 +29,30 @@ WebCursor& WebCursor::operator=(const WebCursor& other) {
return *this;
}
-bool WebCursor::Deserialize(const base::Pickle* m, base::PickleIterator* iter) {
- // Leave |this| unmodified unless deserialization is successful.
- int type = 0, hotspot_x = 0, hotspot_y = 0;
- float scale = 1.f;
- SkBitmap bitmap;
- if (!iter->ReadInt(&type))
+bool WebCursor::SetInfo(const CursorInfo& info) {
+ static constexpr int kMaxSize = 1024;
+ if (info.image_scale_factor < 0.01f || info.image_scale_factor > 100.f ||
+ info.custom_image.width() > kMaxSize ||
+ info.custom_image.height() > kMaxSize ||
+ info.custom_image.width() / info.image_scale_factor > kMaxSize ||
+ info.custom_image.height() / info.image_scale_factor > kMaxSize) {
return false;
+ }
- if (type == WebCursorInfo::kTypeCustom) {
- if (!iter->ReadInt(&hotspot_x) || !iter->ReadInt(&hotspot_y) ||
- !iter->ReadFloat(&scale) || !IsReasonableScale(scale)) {
- return false;
- }
-
- if (!IPC::ParamTraits<SkBitmap>::Read(m, iter, &bitmap))
- return false;
+ CleanupPlatformData();
+ info_ = info;
- if (bitmap.width() > kMaxSize || bitmap.height() > kMaxSize ||
- bitmap.width() / scale > kMaxSize ||
- bitmap.height() / scale > kMaxSize) {
- return false;
- }
+ // Clamp the hotspot to the custom image's dimensions.
+ if (info_.type == blink::WebCursorInfo::kTypeCustom) {
+ info_.hotspot.set_x(std::max(
+ 0, std::min(info_.custom_image.width() - 1, info_.hotspot.x())));
+ info_.hotspot.set_y(std::max(
+ 0, std::min(info_.custom_image.height() - 1, info_.hotspot.y())));
}
- info_.type = static_cast<WebCursorInfo::Type>(type);
- info_.custom_image = bitmap;
- info_.hotspot = gfx::Point(hotspot_x, hotspot_y);
- info_.image_scale_factor = scale;
- ClampHotspot();
return true;
}
-void WebCursor::Serialize(base::Pickle* pickle) const {
- pickle->WriteInt(info_.type);
- if (info_.type == WebCursorInfo::kTypeCustom) {
- pickle->WriteInt(info_.hotspot.x());
- pickle->WriteInt(info_.hotspot.y());
- pickle->WriteFloat(info_.image_scale_factor);
- IPC::ParamTraits<SkBitmap>::Write(pickle, info_.custom_image);
- }
-}
-
bool WebCursor::operator==(const WebCursor& other) const {
return info_ == other.info_ &&
#if defined(USE_AURA) || defined(USE_OZONE)
@@ -105,19 +66,8 @@ bool WebCursor::operator!=(const WebCursor& other) const {
}
void WebCursor::CopyAllData(const WebCursor& other) {
- info_ = other.info_;
+ SetInfo(other.info_);
CopyPlatformData(other);
}
-void WebCursor::ClampHotspot() {
- if (info_.type != WebCursorInfo::kTypeCustom)
- return;
-
- // Clamp the hotspot to the custom image's dimensions.
- info_.hotspot.set_x(
- std::max(0, std::min(info_.custom_image.width() - 1, info_.hotspot.x())));
- info_.hotspot.set_y(std::max(
- 0, std::min(info_.custom_image.height() - 1, info_.hotspot.y())));
-}
-
} // namespace content
diff --git a/chromium/content/common/cursors/webcursor.h b/chromium/content/common/cursors/webcursor.h
index 88b9cb2ba4f..16707949847 100644
--- a/chromium/content/common/cursors/webcursor.h
+++ b/chromium/content/common/cursors/webcursor.h
@@ -19,11 +19,6 @@
#include "ui/base/cursor/cursor.h"
#endif
-namespace base {
-class Pickle;
-class PickleIterator;
-}
-
namespace content {
// This class encapsulates a cross-platform description of a cursor. Platform
@@ -40,9 +35,8 @@ class CONTENT_EXPORT WebCursor {
const CursorInfo& info() const { return info_; }
- // Serialization / De-serialization
- bool Deserialize(const base::Pickle* m, base::PickleIterator* iter);
- void Serialize(base::Pickle* pickle) const;
+ // Sets the cursor |info|; returns whether the struct has reasonable values.
+ bool SetInfo(const CursorInfo& info);
// Equality operator; performs bitmap content comparison as needed.
bool operator==(const WebCursor& other) const;
@@ -62,8 +56,6 @@ class CONTENT_EXPORT WebCursor {
float* scale);
#endif
- void set_info_for_testing(const CursorInfo& info) { info_ = info; }
-
private:
// Returns true if this cursor's platform data matches that of |other|.
bool IsPlatformDataEqual(const WebCursor& other) const;
@@ -77,9 +69,6 @@ class CONTENT_EXPORT WebCursor {
// Platform specific cleanup.
void CleanupPlatformData();
- // Clamp the hotspot to the custom image's bounds, if this is a custom cursor.
- void ClampHotspot();
-
float GetCursorScaleFactor(SkBitmap* bitmap);
// The basic cursor info.
diff --git a/chromium/content/common/cursors/webcursor_aurawin.cc b/chromium/content/common/cursors/webcursor_aurawin.cc
index b25bfab56ac..6d0d1446e35 100644
--- a/chromium/content/common/cursors/webcursor_aurawin.cc
+++ b/chromium/content/common/cursors/webcursor_aurawin.cc
@@ -18,8 +18,7 @@ ui::PlatformCursor WebCursor::GetPlatformCursor(const ui::Cursor& cursor) {
if (platform_cursor_)
return platform_cursor_;
- DCHECK_EQ(kN32_SkColorType, info_.custom_image.colorType());
- platform_cursor_ = IconUtil::CreateCursorFromSkBitmap(info_.custom_image,
+ platform_cursor_ = IconUtil::CreateCursorFromSkBitmap(cursor.GetBitmap(),
cursor.GetHotspot())
.release();
return platform_cursor_;
diff --git a/chromium/content/common/cursors/webcursor_mac.mm b/chromium/content/common/cursors/webcursor_mac.mm
index f8100115324..ef1b2807327 100644
--- a/chromium/content/common/cursors/webcursor_mac.mm
+++ b/chromium/content/common/cursors/webcursor_mac.mm
@@ -272,12 +272,8 @@ bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const {
return true;
}
-void WebCursor::CleanupPlatformData() {
- return;
-}
+void WebCursor::CleanupPlatformData() {}
-void WebCursor::CopyPlatformData(const WebCursor& other) {
- return;
-}
+void WebCursor::CopyPlatformData(const WebCursor& other) {}
} // namespace content
diff --git a/chromium/content/common/cursors/webcursor_ozone.cc b/chromium/content/common/cursors/webcursor_ozone.cc
index 1456be2ca9d..f1bcf9a8c0d 100644
--- a/chromium/content/common/cursors/webcursor_ozone.cc
+++ b/chromium/content/common/cursors/webcursor_ozone.cc
@@ -9,15 +9,11 @@
#include "third_party/blink/public/platform/web_cursor_info.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/cursor_util.h"
-#include "ui/base/ui_base_features.h"
#include "ui/ozone/public/cursor_factory_ozone.h"
namespace content {
ui::PlatformCursor WebCursor::GetPlatformCursor(const ui::Cursor& cursor) {
- if (features::IsUsingWindowService())
- return nullptr;
-
if (!platform_cursor_) {
platform_cursor_ = ui::CursorFactoryOzone::GetInstance()->CreateImageCursor(
cursor.GetBitmap(), cursor.GetHotspot(), cursor.device_scale_factor());
diff --git a/chromium/content/common/cursors/webcursor_unittest.cc b/chromium/content/common/cursors/webcursor_unittest.cc
index eb51327e8af..0c48c9fadad 100644
--- a/chromium/content/common/cursors/webcursor_unittest.cc
+++ b/chromium/content/common/cursors/webcursor_unittest.cc
@@ -4,7 +4,6 @@
#include <stddef.h>
-#include "base/pickle.h"
#include "build/build_config.h"
#include "content/common/cursors/webcursor.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -65,68 +64,6 @@ TEST(WebCursorTest, CopyConstructorCustom) {
EXPECT_EQ(cursor, copy);
}
-TEST(WebCursorTest, SerializationDefault) {
- WebCursor cursor;
- base::Pickle pickle;
- cursor.Serialize(&pickle);
-
- WebCursor copy;
- base::PickleIterator iter(pickle);
- ASSERT_TRUE(copy.Deserialize(&pickle, &iter));
- EXPECT_EQ(cursor, copy);
-}
-
-TEST(WebCursorTest, SerializationCustom) {
- CursorInfo info(blink::WebCursorInfo::kTypeCustom);
- info.custom_image = CreateTestBitmap(32, 32);
- info.hotspot = gfx::Point(10, 20);
- info.image_scale_factor = 1.5f;
- WebCursor cursor(info);
- base::Pickle pickle;
- cursor.Serialize(&pickle);
-
- WebCursor copy;
- base::PickleIterator iter(pickle);
- ASSERT_TRUE(copy.Deserialize(&pickle, &iter));
- EXPECT_EQ(cursor, copy);
-}
-
-TEST(WebCursorTest, DeserializeBadMessage) {
- WebCursor cursor((CursorInfo(blink::WebCursorInfo::kTypeHand)));
- WebCursor unmodified_cursor(cursor);
- WebCursor invalid_cursor;
-
- // Serialize a cursor with a small scale; deserialization should fail.
- CursorInfo small_scale_info(blink::WebCursorInfo::kTypeCustom);
- small_scale_info.image_scale_factor = 0.001f;
- invalid_cursor.set_info_for_testing(small_scale_info);
- base::Pickle small_scale_pickle;
- invalid_cursor.Serialize(&small_scale_pickle);
- base::PickleIterator iter = base::PickleIterator(small_scale_pickle);
- EXPECT_FALSE(cursor.Deserialize(&small_scale_pickle, &iter));
- EXPECT_EQ(unmodified_cursor, cursor);
-
- // Serialize a cursor with a big scale; deserialization should fail.
- CursorInfo big_scale_info(blink::WebCursorInfo::kTypeCustom);
- big_scale_info.image_scale_factor = 1000.f;
- invalid_cursor.set_info_for_testing(big_scale_info);
- base::Pickle big_scale_pickle;
- invalid_cursor.Serialize(&big_scale_pickle);
- iter = base::PickleIterator(big_scale_pickle);
- EXPECT_FALSE(cursor.Deserialize(&big_scale_pickle, &iter));
- EXPECT_EQ(unmodified_cursor, cursor);
-
- // Serialize a cursor with a big image; deserialization should fail.
- CursorInfo big_image_info(blink::WebCursorInfo::kTypeCustom);
- big_image_info.custom_image = CreateTestBitmap(1025, 3);
- invalid_cursor.set_info_for_testing(big_image_info);
- base::Pickle big_image_pickle;
- invalid_cursor.Serialize(&big_image_pickle);
- iter = base::PickleIterator(big_image_pickle);
- EXPECT_FALSE(cursor.Deserialize(&big_image_pickle, &iter));
- EXPECT_EQ(unmodified_cursor, cursor);
-}
-
TEST(WebCursorTest, ClampHotspot) {
// Initialize a cursor with an invalid hotspot; it should be clamped.
CursorInfo info(blink::WebCursorInfo::kTypeCustom);
@@ -134,16 +71,51 @@ TEST(WebCursorTest, ClampHotspot) {
info.custom_image = CreateTestBitmap(5, 7);
WebCursor cursor(info);
EXPECT_EQ(gfx::Point(4, 6), cursor.info().hotspot);
-
- // Serialize a cursor with an invalid hotspot; it should be clamped.
- cursor.set_info_for_testing(info);
- base::Pickle pickle;
- cursor.Serialize(&pickle);
- base::PickleIterator iter = base::PickleIterator(pickle);
- EXPECT_TRUE(cursor.Deserialize(&pickle, &iter));
+ // SetInfo should also clamp the hotspot.
+ EXPECT_TRUE(cursor.SetInfo(info));
EXPECT_EQ(gfx::Point(4, 6), cursor.info().hotspot);
}
+TEST(WebCursorTest, SetInfo) {
+ WebCursor cursor;
+ EXPECT_TRUE(cursor.SetInfo(CursorInfo()));
+ EXPECT_TRUE(cursor.SetInfo(CursorInfo(blink::WebCursorInfo::kTypeHand)));
+ EXPECT_TRUE(cursor.SetInfo(CursorInfo(blink::WebCursorInfo::kTypeCustom)));
+
+ CursorInfo info(blink::WebCursorInfo::kTypeCustom);
+ info.custom_image = CreateTestBitmap(32, 32);
+ info.hotspot = gfx::Point(10, 20);
+ info.image_scale_factor = 1.5f;
+ EXPECT_TRUE(cursor.SetInfo(info));
+
+ // SetInfo should return false when the scale factor is too small.
+ info.image_scale_factor = 0.001f;
+ EXPECT_FALSE(cursor.SetInfo(info));
+
+ // SetInfo should return false when the scale factor is too large.
+ info.image_scale_factor = 1000.f;
+ EXPECT_FALSE(cursor.SetInfo(info));
+
+ // SetInfo should return false when the image width is too large.
+ info.image_scale_factor = 1.f;
+ info.custom_image = CreateTestBitmap(1025, 3);
+ EXPECT_FALSE(cursor.SetInfo(info));
+
+ // SetInfo should return false when the image height is too large.
+ info.custom_image = CreateTestBitmap(3, 1025);
+ EXPECT_FALSE(cursor.SetInfo(info));
+
+ // SetInfo should return false when the scaled image width is too large.
+ info.image_scale_factor = 0.02f;
+ info.custom_image = CreateTestBitmap(50, 5);
+ EXPECT_FALSE(cursor.SetInfo(info));
+
+ // SetInfo should return false when the scaled image height is too large.
+ info.image_scale_factor = 0.1f;
+ info.custom_image = CreateTestBitmap(5, 200);
+ EXPECT_FALSE(cursor.SetInfo(info));
+}
+
#if defined(USE_AURA)
TEST(WebCursorTest, CursorScaleFactor) {
CursorInfo info;
diff --git a/chromium/content/common/date_time_suggestion.h b/chromium/content/common/date_time_suggestion.h
deleted file mode 100644
index ce35430ca81..00000000000
--- a/chromium/content/common/date_time_suggestion.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_DATE_TIME_SUGGESTION_H_
-#define CONTENT_COMMON_DATE_TIME_SUGGESTION_H_
-
-#include <vector>
-
-#include "base/strings/string16.h"
-#include "content/common/content_export.h"
-#include "third_party/skia/include/core/SkColor.h"
-
-namespace content {
-
-// Container for information about datalist suggestion for the date/time input
-// control. Keep in sync with DateTimeSuggestion.java
-struct CONTENT_EXPORT DateTimeSuggestion {
- DateTimeSuggestion() {}
-
- // The date/time value represented as a double.
- double value;
- // The localized value to be shown to the user.
- base::string16 localized_value;
- // The label for the suggestion.
- base::string16 label;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_DATE_TIME_SUGGESTION_H_
diff --git a/chromium/content/common/fetch/fetch_request_type_converters.cc b/chromium/content/common/fetch/fetch_request_type_converters.cc
index 5ec5e598a0e..100f515915a 100644
--- a/chromium/content/common/fetch/fetch_request_type_converters.cc
+++ b/chromium/content/common/fetch/fetch_request_type_converters.cc
@@ -40,7 +40,6 @@ blink::mojom::FetchAPIRequestPtr TypeConverter<
output->redirect_mode = input.fetch_redirect_mode;
output->request_context_type = static_cast<blink::mojom::RequestContextType>(
input.fetch_request_context_type);
- output->frame_type = input.fetch_frame_type;
output->is_reload = ui::PageTransitionCoreTypeIs(
static_cast<ui::PageTransition>(input.transition_type),
ui::PAGE_TRANSITION_RELOAD);
diff --git a/chromium/content/common/font_list.h b/chromium/content/common/font_list.h
index 3922275d623..d671e973382 100644
--- a/chromium/content/common/font_list.h
+++ b/chromium/content/common/font_list.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/sequenced_task_runner.h"
+#include "content/common/content_export.h"
namespace base {
class ListValue;
@@ -18,7 +19,7 @@ namespace content {
// GetFontList_SlowBlocking() must only be called from the SequencedTaskRunner
// returned by this function because it is non-threadsafe on Linux for versions
// of Pango predating 2013.
-scoped_refptr<base::SequencedTaskRunner> GetFontListTaskRunner();
+CONTENT_EXPORT scoped_refptr<base::SequencedTaskRunner> GetFontListTaskRunner();
// Retrieves the fonts available on the current platform and returns them.
// The caller will own the returned pointer. Each entry will be a list of
@@ -29,7 +30,7 @@ scoped_refptr<base::SequencedTaskRunner> GetFontListTaskRunner();
// GetFontListTaskRunner(). Most callers will want to use the GetFontListAsync
// function in content/browser/font_list_async.h which does an asynchronous
// call.
-std::unique_ptr<base::ListValue> GetFontList_SlowBlocking();
+CONTENT_EXPORT std::unique_ptr<base::ListValue> GetFontList_SlowBlocking();
} // namespace content
diff --git a/chromium/content/common/font_list_unittest.cc b/chromium/content/common/font_list_unittest.cc
new file mode 100644
index 00000000000..7f6267834ed
--- /dev/null
+++ b/chromium/content/common/font_list_unittest.cc
@@ -0,0 +1,77 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/font_list.h"
+
+#include "base/bind.h"
+#include "base/i18n/rtl.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/string_piece.h"
+#include "base/task/post_task.h"
+#include "base/task_runner_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+#if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+bool HasFontWithName(const base::ListValue& list,
+ base::StringPiece expected_font_id,
+ base::StringPiece expected_display_name) {
+ for (const auto& font : list.GetList()) {
+ const auto& font_names = font.GetList();
+ std::string font_id = font_names[0].GetString();
+ std::string display_name = font_names[1].GetString();
+ if (font_id == expected_font_id && display_name == expected_display_name)
+ return true;
+ }
+
+ return false;
+}
+#endif // !defined(OS_ANDROID) && !defined(OS_FUCHSI
+
+} // namespace
+
+#if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+// GetFontList is not implemented on Android and Fuchsia.
+TEST(FontList, GetFontList) {
+ base::test::ScopedTaskEnvironment scoped_task_environment;
+
+ content::GetFontListTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce([] {
+ std::unique_ptr<base::ListValue> fonts =
+ content::GetFontList_SlowBlocking();
+ ASSERT_TRUE(fonts);
+
+#if defined(OS_WIN)
+ EXPECT_TRUE(HasFontWithName(*fonts, "MS Gothic", "MS Gothic"));
+ EXPECT_TRUE(HasFontWithName(*fonts, "Segoe UI", "Segoe UI"));
+ EXPECT_TRUE(HasFontWithName(*fonts, "Verdana", "Verdana"));
+#elif defined(OS_LINUX)
+ EXPECT_TRUE(HasFontWithName(*fonts, "Arimo", "Arimo"));
+#else
+ EXPECT_TRUE(HasFontWithName(*fonts, "Arial", "Arial"));
+#endif
+ }));
+ scoped_task_environment.RunUntilIdle();
+}
+#endif // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+
+#if defined(OS_WIN)
+TEST(FontList, GetFontListLocalized) {
+ base::i18n::SetICUDefaultLocale("ja-JP");
+ std::unique_ptr<base::ListValue> ja_fonts =
+ content::GetFontList_SlowBlocking();
+ ASSERT_TRUE(ja_fonts);
+ EXPECT_TRUE(HasFontWithName(*ja_fonts, "MS Gothic", "MS ゴシック"));
+
+ base::i18n::SetICUDefaultLocale("ko-KR");
+ std::unique_ptr<base::ListValue> ko_fonts =
+ content::GetFontList_SlowBlocking();
+ ASSERT_TRUE(ko_fonts);
+ EXPECT_TRUE(HasFontWithName(*ko_fonts, "Malgun Gothic", "맑은 고딕"));
+}
+#endif // defined(OS_WIN)
diff --git a/chromium/content/common/font_list_win.cc b/chromium/content/common/font_list_win.cc
index a05a3bc8112..7b00be911f1 100644
--- a/chromium/content/common/font_list_win.cc
+++ b/chromium/content/common/font_list_win.cc
@@ -4,53 +4,67 @@
#include "content/common/font_list.h"
+#include <dwrite.h>
#include <windows.h>
-#include <string.h>
-
-#include <set>
-#include <utility>
+#include <wrl/client.h>
+#include "base/i18n/rtl.h"
#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
+#include "ui/gfx/win/direct_write.h"
namespace content {
-static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW* logical_font,
- NEWTEXTMETRICEXW* physical_font,
- DWORD font_type,
- LPARAM lparam) {
- std::set<base::string16>* font_names =
- reinterpret_cast<std::set<base::string16>*>(lparam);
- if (font_names) {
- const LOGFONTW& lf = logical_font->elfLogFont;
- if (lf.lfFaceName[0] && lf.lfFaceName[0] != '@') {
- base::string16 face_name(lf.lfFaceName);
- font_names->insert(face_name);
- }
- }
- return 1;
-}
-
std::unique_ptr<base::ListValue> GetFontList_SlowBlocking() {
- std::set<base::string16> font_names;
+ TRACE_EVENT0("fonts", "GetFontList_SlowBlocking");
+
+ std::unique_ptr<base::ListValue> font_list(new base::ListValue);
- LOGFONTW logfont;
- memset(&logfont, 0, sizeof(logfont));
- logfont.lfCharSet = DEFAULT_CHARSET;
+ Microsoft::WRL::ComPtr<IDWriteFactory> factory;
+ gfx::win::CreateDWriteFactory(&factory);
+ if (!factory)
+ return font_list;
- HDC hdc = ::GetDC(NULL);
- ::EnumFontFamiliesExW(hdc, &logfont, (FONTENUMPROCW)&EnumFontFamExProc,
- (LPARAM)&font_names, 0);
- ::ReleaseDC(NULL, hdc);
+ Microsoft::WRL::ComPtr<IDWriteFontCollection> collection;
+ if (FAILED(factory->GetSystemFontCollection(&collection)))
+ return font_list;
+
+ // Retrieve the localized font family name. If there is no localized name,
+ // used the native name instead.
+ std::string locale = base::i18n::GetConfiguredLocale();
+
+ const UINT32 family_count = collection->GetFontFamilyCount();
+ for (UINT32 family_index = 0; family_index < family_count; ++family_index) {
+ Microsoft::WRL::ComPtr<IDWriteFontFamily> font_family;
+ Microsoft::WRL::ComPtr<IDWriteLocalizedStrings> family_names;
+ if (FAILED(collection->GetFontFamily(family_index, &font_family)) ||
+ FAILED(font_family->GetFamilyNames(&family_names))) {
+ continue;
+ }
+
+ // Retrieve the native font family name. Try the "en-us" locale and if it's
+ // not present, used the first available localized name.
+ base::Optional<std::string> native_name =
+ gfx::win::RetrieveLocalizedString(family_names.Get(), "en-us");
+ if (!native_name) {
+ native_name = gfx::win::RetrieveLocalizedString(family_names.Get(), "");
+ if (!native_name)
+ continue;
+ }
+
+ base::Optional<std::string> localized_name =
+ gfx::win::RetrieveLocalizedString(family_names.Get(), locale);
+ if (!localized_name)
+ localized_name = native_name;
- std::unique_ptr<base::ListValue> font_list(new base::ListValue);
- std::set<base::string16>::iterator iter;
- for (iter = font_names.begin(); iter != font_names.end(); ++iter) {
auto font_item = std::make_unique<base::ListValue>();
- font_item->AppendString(*iter);
- font_item->AppendString(*iter);
+ font_item->AppendString(native_name.value());
+ font_item->AppendString(localized_name.value());
font_list->Append(std::move(font_item));
}
+
return font_list;
}
diff --git a/chromium/content/common/frame.mojom b/chromium/content/common/frame.mojom
index 1b1f8704d3f..577fd09ef05 100644
--- a/chromium/content/common/frame.mojom
+++ b/chromium/content/common/frame.mojom
@@ -21,6 +21,7 @@ import "services/service_manager/public/mojom/interface_provider.mojom";
import "services/viz/public/interfaces/compositing/surface_id.mojom";
import "third_party/blink/public/mojom/blob/blob_url_store.mojom";
import "third_party/blink/public/mojom/commit_result/commit_result.mojom";
+import "third_party/blink/public/mojom/devtools/console_message.mojom";
import "third_party/blink/public/mojom/feature_policy/feature_policy.mojom";
import "third_party/blink/public/mojom/frame/lifecycle.mojom";
import "third_party/blink/public/mojom/frame/navigation_initiator.mojom";
@@ -223,10 +224,11 @@ interface FrameNavigationControl {
mojo_base.mojom.String16 target_origin,
blink.mojom.TransferableMessage message);
- // Forwards message to the portal's main frame.
- ForwardMessageToPortalHost(blink.mojom.TransferableMessage message,
- url.mojom.Origin source_origin,
- url.mojom.Origin? target_origin);
+ // Forwards a message from a portal's host to the main frame in the portal's
+ // guest contents.
+ ForwardMessageFromHost(blink.mojom.TransferableMessage message,
+ url.mojom.Origin source_origin,
+ url.mojom.Origin? target_origin);
// Called on the main frame of a page embedded in a Portal when it is
// activated. The frame has the option to adopt the previous page as a portal
@@ -237,6 +239,7 @@ interface FrameNavigationControl {
// current frame.
OnPortalActivated(mojo_base.mojom.UnguessableToken portal_token,
associated blink.mojom.Portal portal,
+ associated blink.mojom.PortalClient& portal_client,
blink.mojom.TransferableMessage data) => (bool was_adopted);
};
@@ -346,18 +349,22 @@ interface FrameHost {
=> (CreateNewWindowStatus status, CreateNewWindowReply? reply);
// Sent by the renderer process to request the creation of a new portal.
- // |portal| is the interface to be used for the Portal object. Returns
- // |proxy_routing_id|, which is the routing id of the RenderFrameProxy and
- // |portal_token|, which is the unique identifier for the portal.
- [Sync] CreatePortal(associated blink.mojom.Portal& portal)
+ // |portal| is the pipe to be used for the Portal object, |client| is the pipe
+ // used to communicate back with the caller. Returns |proxy_routing_id|, which
+ // is the routing id of the RenderFrameProxy and |portal_token|, which is the
+ // unique identifier for the portal.
+ [Sync] CreatePortal(associated blink.mojom.Portal& portal,
+ associated blink.mojom.PortalClient client)
=> (int32 proxy_routing_id,
- mojo_base.mojom.UnguessableToken portal_token);
+ mojo_base.mojom.UnguessableToken portal_token,
+ mojo_base.mojom.UnguessableToken devtools_frame_token);
// Requests that this frame adopts the portal identified by |portal_token|.
// Returns |proxy_routing_id|, which is the routing id of the portal's
// RenderFrameProxy.
[Sync] AdoptPortal(mojo_base.mojom.UnguessableToken portal_token)
- => (int32 proxy_routing_id);
+ => (int32 proxy_routing_id,
+ mojo_base.mojom.UnguessableToken devtools_frame_token);
// Creates and returns a KeepAliveHandle.
IssueKeepAliveHandle(KeepAliveHandle& keep_alive_handle);
@@ -480,4 +487,37 @@ interface FrameHost {
// of the individual bits.
// TODO(altimin): Move into a separate scheduling interface.
UpdateActiveSchedulerTrackedFeatures(uint64 features_mask);
+
+ // Blink and JavaScript error messages to log to the console or debugger UI.
+ DidAddMessageToConsole(
+ blink.mojom.ConsoleMessageLevel log_level,
+ mojo_base.mojom.BigString16 msg,
+ int32 line_number,
+ mojo_base.mojom.String16 source_id);
+
+ // Sent when the renderer fails a provisional load with an error.
+ //
+ // |url| is the URL that the error is reported for.
+ //
+ // |error_code| is a net::Error code as reported in the
+ // DidFailProvisionalLoad callback.
+ //
+ // |error_description| is an error message generated from the error_code.
+ // This can be an empty string if we were unable to find a meaningful
+ // description.
+ //
+ // |showing_repost_interstitial| is true if the failure is the result of
+ // navigating to a POST again and we're going to show the POST interstitial.
+ // TODO(https://crbug.com/963806): Delete this method.
+ DidFailProvisionalLoadWithError(
+ url.mojom.Url url,
+ int32 error_code,
+ mojo_base.mojom.String16 error_description,
+ bool showing_repost_interstitial);
+
+ // Sent when the renderer fails to load with an error.
+ DidFailLoadWithError(
+ url.mojom.Url url,
+ int32 error_code,
+ mojo_base.mojom.String16 error_description);
};
diff --git a/chromium/content/common/frame_message_structs.h b/chromium/content/common/frame_message_structs.h
index 981f17e39ed..951dec23099 100644
--- a/chromium/content/common/frame_message_structs.h
+++ b/chromium/content/common/frame_message_structs.h
@@ -5,7 +5,6 @@
#ifndef CONTENT_COMMON_FRAME_MESSAGE_STRUCTS_H_
#define CONTENT_COMMON_FRAME_MESSAGE_STRUCTS_H_
-#include "base/optional.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "content/common/content_export.h"
@@ -15,8 +14,7 @@ struct CONTENT_EXPORT FrameMsg_ViewChanged_Params {
FrameMsg_ViewChanged_Params();
~FrameMsg_ViewChanged_Params();
- // |frame_sink_id| is not used when mus is hosting viz.
- base::Optional<viz::FrameSinkId> frame_sink_id;
+ viz::FrameSinkId frame_sink_id;
};
} // namespace content
diff --git a/chromium/content/common/frame_messages.h b/chromium/content/common/frame_messages.h
index 91e10a61934..e5bcd550ade 100644
--- a/chromium/content/common/frame_messages.h
+++ b/chromium/content/common/frame_messages.h
@@ -75,6 +75,7 @@
#include "third_party/blink/public/web/web_media_player_action.h"
#include "third_party/blink/public/web/web_tree_scope_type.h"
#include "third_party/blink/public/web/web_triggering_event_info.h"
+#include "ui/events/types/scroll_types.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
@@ -150,9 +151,10 @@ IPC_ENUM_TRAITS_MAX_VALUE(content::WasActivatedOption,
IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebScrollDirection,
blink::kFirstScrollDirection,
blink::kLastScrollDirection)
-IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebScrollGranularity,
- blink::kFirstScrollGranularity,
- blink::kLastScrollGranularity)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(
+ ui::input_types::ScrollGranularity,
+ ui::input_types::ScrollGranularity::kFirstScrollGranularity,
+ ui::input_types::ScrollGranularity::kMaxValue)
IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::FeaturePolicyDisposition,
blink::mojom::FeaturePolicyDisposition::kMaxValue)
IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::FrameVisibility,
@@ -337,19 +339,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::ServerTimingInfo)
IPC_STRUCT_TRAITS_MEMBER(description)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_BEGIN(FrameHostMsg_DidFailProvisionalLoadWithError_Params)
- // Error code as reported in the DidFailProvisionalLoad callback.
- IPC_STRUCT_MEMBER(int, error_code)
- // An error message generated from the error_code. This can be an empty
- // string if we were unable to find a meaningful description.
- IPC_STRUCT_MEMBER(base::string16, error_description)
- // The URL that the error is reported for.
- IPC_STRUCT_MEMBER(GURL, url)
- // True if the failure is the result of navigating to a POST again
- // and we're going to show the POST interstitial.
- IPC_STRUCT_MEMBER(bool, showing_repost_interstitial)
-IPC_STRUCT_END()
-
IPC_STRUCT_TRAITS_BEGIN(content::FrameNavigateParams)
IPC_STRUCT_TRAITS_MEMBER(nav_entry_id)
IPC_STRUCT_TRAITS_MEMBER(item_sequence_number)
@@ -369,6 +358,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::ScreenInfo)
IPC_STRUCT_TRAITS_MEMBER(depth)
IPC_STRUCT_TRAITS_MEMBER(depth_per_component)
IPC_STRUCT_TRAITS_MEMBER(is_monochrome)
+ IPC_STRUCT_TRAITS_MEMBER(display_frequency)
IPC_STRUCT_TRAITS_MEMBER(rect)
IPC_STRUCT_TRAITS_MEMBER(available_rect)
IPC_STRUCT_TRAITS_MEMBER(orientation_type)
@@ -480,6 +470,14 @@ IPC_STRUCT_TRAITS_BEGIN(content::InitiatorCSPInfo)
IPC_STRUCT_TRAITS_MEMBER(initiator_self_source)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(content::PrefetchedSignedExchangeInfo)
+ IPC_STRUCT_TRAITS_MEMBER(outer_url)
+ IPC_STRUCT_TRAITS_MEMBER(header_integrity)
+ IPC_STRUCT_TRAITS_MEMBER(inner_url)
+ IPC_STRUCT_TRAITS_MEMBER(inner_response)
+ IPC_STRUCT_TRAITS_MEMBER(loader_factory_handle)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(content::CommonNavigationParams)
IPC_STRUCT_TRAITS_MEMBER(url)
IPC_STRUCT_TRAITS_MEMBER(initiator_origin)
@@ -498,9 +496,11 @@ IPC_STRUCT_TRAITS_BEGIN(content::CommonNavigationParams)
IPC_STRUCT_TRAITS_MEMBER(has_user_gesture)
IPC_STRUCT_TRAITS_MEMBER(started_from_context_menu)
IPC_STRUCT_TRAITS_MEMBER(initiator_csp_info)
+ IPC_STRUCT_TRAITS_MEMBER(initiator_origin_trial_features)
IPC_STRUCT_TRAITS_MEMBER(origin_policy)
IPC_STRUCT_TRAITS_MEMBER(href_translate)
IPC_STRUCT_TRAITS_MEMBER(input_start)
+ IPC_STRUCT_TRAITS_MEMBER(is_history_navigation_in_new_child_frame)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::NavigationTiming)
@@ -521,7 +521,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::CommitNavigationParams)
IPC_STRUCT_TRAITS_MEMBER(can_load_local_resources)
IPC_STRUCT_TRAITS_MEMBER(page_state)
IPC_STRUCT_TRAITS_MEMBER(nav_entry_id)
- IPC_STRUCT_TRAITS_MEMBER(is_history_navigation_in_new_child)
IPC_STRUCT_TRAITS_MEMBER(subframe_unique_names)
IPC_STRUCT_TRAITS_MEMBER(intended_as_new_entry)
IPC_STRUCT_TRAITS_MEMBER(pending_history_list_offset)
@@ -534,6 +533,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::CommitNavigationParams)
IPC_STRUCT_TRAITS_MEMBER(appcache_host_id)
IPC_STRUCT_TRAITS_MEMBER(was_activated)
IPC_STRUCT_TRAITS_MEMBER(navigation_token)
+ IPC_STRUCT_TRAITS_MEMBER(prefetched_signed_exchanges)
#if defined(OS_ANDROID)
IPC_STRUCT_TRAITS_MEMBER(data_url_as_string)
#endif
@@ -578,7 +578,6 @@ IPC_STRUCT_BEGIN(FrameHostMsg_OpenURL_Params)
IPC_STRUCT_MEMBER(WindowOpenDisposition, disposition)
IPC_STRUCT_MEMBER(bool, should_replace_current_entry)
IPC_STRUCT_MEMBER(bool, user_gesture)
- IPC_STRUCT_MEMBER(bool, is_history_navigation_in_new_child)
IPC_STRUCT_MEMBER(blink::WebTriggeringEventInfo, triggering_event_info)
IPC_STRUCT_MEMBER(mojo::MessagePipeHandle, blob_url_token)
IPC_STRUCT_MEMBER(std::string, href_translate)
@@ -846,9 +845,10 @@ IPC_MESSAGE_ROUTED0(FrameMsg_DidStartLoading)
IPC_MESSAGE_ROUTED0(FrameMsg_DidStopLoading)
// Add message to the frame console.
-IPC_MESSAGE_ROUTED2(FrameMsg_AddMessageToConsole,
+IPC_MESSAGE_ROUTED3(FrameMsg_AddMessageToConsole,
blink::mojom::ConsoleMessageLevel /* level */,
- std::string /* message */)
+ std::string /* message */,
+ bool /* discard_duplicates */)
// Tells the renderer to reload the frame, optionally bypassing the cache while
// doing so.
@@ -1085,7 +1085,7 @@ IPC_MESSAGE_ROUTED2(FrameMsg_ScrollRectToVisible,
// a logical scroll.
IPC_MESSAGE_ROUTED2(FrameMsg_BubbleLogicalScroll,
blink::WebScrollDirection /* direction */,
- blink::WebScrollGranularity /* granularity */)
+ ui::input_types::ScrollGranularity /* granularity */)
// Tells the renderer to perform the given action on the media player location
// at the given point in the view coordinate space.
@@ -1101,14 +1101,6 @@ IPC_MESSAGE_ROUTED0(FrameMsg_RenderFallbackContent)
// -----------------------------------------------------------------------------
// Messages sent from the renderer to the browser.
-// Blink and JavaScript error messages to log to the console
-// or debugger UI.
-IPC_MESSAGE_ROUTED4(FrameHostMsg_DidAddMessageToConsole,
- int32_t, /* log level */
- base::string16, /* msg */
- int32_t, /* line number */
- base::string16 /* source id */)
-
// Sent by the renderer when a child frame is created in the renderer.
//
// Each of these messages will have a corresponding FrameHostMsg_Detach message
@@ -1125,26 +1117,12 @@ IPC_SYNC_MESSAGE_CONTROL1_1(FrameHostMsg_CreateChildFrame,
// detached from the DOM.
IPC_MESSAGE_ROUTED0(FrameHostMsg_Detach)
-// Indicates the renderer process is gone. This actually is sent by the
-// browser process to itself, but keeps the interface cleaner.
-IPC_MESSAGE_ROUTED2(FrameHostMsg_RenderProcessGone,
- int, /* this really is base::TerminationStatus */
- int /* exit_code */)
-
// Sent by the renderer when the frame becomes focused.
IPC_MESSAGE_ROUTED0(FrameHostMsg_FrameFocused)
-// Sent when the renderer fails a provisional load with an error.
-IPC_MESSAGE_ROUTED1(FrameHostMsg_DidFailProvisionalLoadWithError,
- FrameHostMsg_DidFailProvisionalLoadWithError_Params)
-
// Notifies the browser that a document has been loaded.
IPC_MESSAGE_ROUTED0(FrameHostMsg_DidFinishDocumentLoad)
-IPC_MESSAGE_ROUTED3(FrameHostMsg_DidFailLoadWithError,
- GURL /* validated_url */,
- int /* error_code */,
- base::string16 /* error_description */)
// Sent when the renderer is done loading a page.
IPC_MESSAGE_ROUTED0(FrameHostMsg_DidStopLoading)
@@ -1633,7 +1611,7 @@ IPC_MESSAGE_ROUTED2(FrameHostMsg_ScrollRectToVisibleInParentFrame,
// process.
IPC_MESSAGE_ROUTED2(FrameHostMsg_BubbleLogicalScrollInParentFrame,
blink::WebScrollDirection /* direction */,
- blink::WebScrollGranularity /* granularity */)
+ ui::input_types::ScrollGranularity /* granularity */)
// Sent to notify that a frame called |window.focus()|.
IPC_MESSAGE_ROUTED0(FrameHostMsg_FrameDidCallFocus)
@@ -1659,6 +1637,13 @@ IPC_MESSAGE_ROUTED2(FrameHostMsg_GoToEntryAtOffset,
int /* offset (from current) of history item to get */,
bool /* has_user_gesture */)
+// Sent to the browser process to transfer the user activation state from the
+// source frame to the frame sending this IPC. The browser will update the user
+// activation state of the frames in the frame tree in the non-source and
+// non-target renderer processes.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_TransferUserActivationFrom,
+ int /* source_routing_id */)
+
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
// Message to show/hide a popup menu using native controls.
diff --git a/chromium/content/common/input/OWNERS b/chromium/content/common/input/OWNERS
index 8f20012b153..b2d4db867b1 100644
--- a/chromium/content/common/input/OWNERS
+++ b/chromium/content/common/input/OWNERS
@@ -1,5 +1,6 @@
dtapuska@chromium.org
tdresser@chromium.org
+bokan@chromium.org
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/input/input_handler.mojom b/chromium/content/common/input/input_handler.mojom
index bfc92da488b..8ef794ec579 100644
--- a/chromium/content/common/input/input_handler.mojom
+++ b/chromium/content/common/input/input_handler.mojom
@@ -81,7 +81,7 @@ struct ScrollUpdate {
struct ScrollData {
float delta_x;
float delta_y;
- ScrollUnits delta_units;
+ ScrollGranularity delta_units;
bool target_viewport;
InertialPhaseState inertial_phase;
bool synthetic;
diff --git a/chromium/content/common/input_messages.h b/chromium/content/common/input_messages.h
index 83565c068a1..d27d9123927 100644
--- a/chromium/content/common/input_messages.h
+++ b/chromium/content/common/input_messages.h
@@ -74,11 +74,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::WebGestureDevice,
blink::WebGestureDevice::kMaxValue)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebInputEvent::DispatchType,
blink::WebInputEvent::DispatchType::kLastDispatchType)
-IPC_ENUM_TRAITS_MAX_VALUE(blink::WebGestureEvent::ScrollUnits,
- blink::WebGestureEvent::ScrollUnits::kLastScrollUnit)
-IPC_ENUM_TRAITS_MAX_VALUE(
- blink::WebGestureEvent::InertialPhaseState,
- blink::WebGestureEvent::InertialPhaseState::kLastPhase)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebGestureEvent::InertialPhaseState,
+ blink::WebGestureEvent::InertialPhaseState::kMaxValue)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebTouchPoint::State,
blink::WebTouchPoint::State::kStateMax)
IPC_ENUM_TRAITS_MAX_VALUE(
diff --git a/chromium/content/common/manifest_observer.mojom b/chromium/content/common/manifest_observer.mojom
deleted file mode 100644
index ad8cb039beb..00000000000
--- a/chromium/content/common/manifest_observer.mojom
+++ /dev/null
@@ -1,11 +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.
-
-module content.mojom;
-
-import "url/mojom/url.mojom";
-
-interface ManifestUrlChangeObserver {
- ManifestUrlChanged(url.mojom.Url? manifest_url);
-};
diff --git a/chromium/content/common/media/media_player_delegate_messages.h b/chromium/content/common/media/media_player_delegate_messages.h
index 706adc974eb..e9219e9fb9b 100644
--- a/chromium/content/common/media/media_player_delegate_messages.h
+++ b/chromium/content/common/media/media_player_delegate_messages.h
@@ -13,7 +13,6 @@
#include <stdint.h>
-#include "components/viz/common/surfaces/surface_id.h"
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
#include "media/base/media_content_type.h"
@@ -61,9 +60,6 @@ IPC_MESSAGE_ROUTED2(MediaPlayerDelegateMsg_BecamePersistentVideo,
int /* delegate_id, distinguishes instances */,
double /* is_persistent */)
-IPC_MESSAGE_ROUTED1(MediaPlayerDelegateMsg_EndPictureInPictureMode,
- int /* delegate_id, distinguishes instances */)
-
// ----------------------------------------------------------------------------
// Messages from the renderer notifying the browser of playback state changes.
// ----------------------------------------------------------------------------
diff --git a/chromium/content/common/mime_sniffing_url_loader.cc b/chromium/content/common/mime_sniffing_url_loader.cc
index 7e267bd8e48..0a92ed23e89 100644
--- a/chromium/content/common/mime_sniffing_url_loader.cc
+++ b/chromium/content/common/mime_sniffing_url_loader.cc
@@ -90,9 +90,8 @@ void MimeSniffingURLLoader::OnUploadProgress(
std::move(ack_callback));
}
-void MimeSniffingURLLoader::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
- destination_url_loader_client_->OnReceiveCachedMetadata(data);
+void MimeSniffingURLLoader::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
+ destination_url_loader_client_->OnReceiveCachedMetadata(std::move(data));
}
void MimeSniffingURLLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
diff --git a/chromium/content/common/mime_sniffing_url_loader.h b/chromium/content/common/mime_sniffing_url_loader.h
index 44cea2fc85f..eb05ba71a93 100644
--- a/chromium/content/common/mime_sniffing_url_loader.h
+++ b/chromium/content/common/mime_sniffing_url_loader.h
@@ -88,7 +88,7 @@ class CONTENT_EXPORT MimeSniffingURLLoader
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
diff --git a/chromium/content/common/native_types.mojom b/chromium/content/common/native_types.mojom
index f87b8aa50e0..a08d65bb9de 100644
--- a/chromium/content/common/native_types.mojom
+++ b/chromium/content/common/native_types.mojom
@@ -68,7 +68,7 @@ enum Cancelability;
enum GestureDevice;
[Native]
-enum ScrollUnits;
+enum ScrollGranularity;
[Native]
enum InertialPhaseState;
diff --git a/chromium/content/common/native_types.typemap b/chromium/content/common/native_types.typemap
index 9150ca2cf3a..f82e022ae3e 100644
--- a/chromium/content/common/native_types.typemap
+++ b/chromium/content/common/native_types.typemap
@@ -79,7 +79,6 @@ type_mappings = [
"content.mojom.DidOverscrollParams=ui::DidOverscrollParams",
"content.mojom.PointerType=blink::WebPointerProperties::PointerType",
"content.mojom.VisualProperties=content::VisualProperties",
- "content.mojom.ScrollUnits=blink::WebGestureEvent::ScrollUnits",
"content.mojom.SyntheticSmoothDrag=content::SyntheticSmoothDragGestureParams",
"content.mojom.SyntheticSmoothScroll=content::SyntheticSmoothScrollGestureParams",
"content.mojom.SyntheticPinch=content::SyntheticPinchGestureParams",
@@ -91,4 +90,5 @@ type_mappings = [
"content.mojom.WebCursor=content::WebCursor",
"content.mojom.WebPopupType=blink::WebPopupType",
"content.mojom.WebPreferences=content::WebPreferences",
+ "content.mojom.ScrollGranularity=ui::input_types::ScrollGranularity",
]
diff --git a/chromium/content/common/navigation_params.cc b/chromium/content/common/navigation_params.cc
index ef3ec052786..068e0bdadb6 100644
--- a/chromium/content/common/navigation_params.cc
+++ b/chromium/content/common/navigation_params.cc
@@ -5,7 +5,6 @@
#include "content/common/navigation_params.h"
#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/url_constants.h"
@@ -15,20 +14,6 @@
namespace content {
-namespace {
-
-void LogPerPolicyApplied(NavigationDownloadType type) {
- UMA_HISTOGRAM_ENUMERATION("Navigation.DownloadPolicy.LogPerPolicyApplied",
- type);
-}
-
-void LogArbitraryPolicyPerDownload(NavigationDownloadType type) {
- UMA_HISTOGRAM_ENUMERATION(
- "Navigation.DownloadPolicy.LogArbitraryPolicyPerDownload", type);
-}
-
-} // namespace
-
SourceLocation::SourceLocation() = default;
SourceLocation::SourceLocation(const std::string& url,
@@ -50,67 +35,6 @@ InitiatorCSPInfo::InitiatorCSPInfo(const InitiatorCSPInfo& other) = default;
InitiatorCSPInfo::~InitiatorCSPInfo() = default;
-NavigationDownloadPolicy::NavigationDownloadPolicy() = default;
-NavigationDownloadPolicy::~NavigationDownloadPolicy() = default;
-NavigationDownloadPolicy::NavigationDownloadPolicy(
- const NavigationDownloadPolicy&) = default;
-
-void NavigationDownloadPolicy::SetAllowed(NavigationDownloadType type) {
- DCHECK(type != NavigationDownloadType::kDefaultAllow);
- observed_types.set(static_cast<size_t>(type));
-}
-
-void NavigationDownloadPolicy::SetDisallowed(NavigationDownloadType type) {
- DCHECK(type != NavigationDownloadType::kDefaultAllow);
- observed_types.set(static_cast<size_t>(type));
- disallowed_types.set(static_cast<size_t>(type));
-}
-
-bool NavigationDownloadPolicy::IsType(NavigationDownloadType type) const {
- DCHECK(type != NavigationDownloadType::kDefaultAllow);
- return observed_types.test(static_cast<size_t>(type));
-}
-
-ResourceInterceptPolicy NavigationDownloadPolicy::GetResourceInterceptPolicy()
- const {
- if (disallowed_types.test(
- static_cast<size_t>(NavigationDownloadType::kSandboxNoGesture)) ||
- disallowed_types.test(
- static_cast<size_t>(NavigationDownloadType::kAdFrameNoGesture)) ||
- disallowed_types.test(
- static_cast<size_t>(NavigationDownloadType::kAdFrameGesture))) {
- return ResourceInterceptPolicy::kAllowPluginOnly;
- }
- return disallowed_types.any() ? ResourceInterceptPolicy::kAllowNone
- : ResourceInterceptPolicy::kAllowAll;
-}
-
-bool NavigationDownloadPolicy::IsDownloadAllowed() const {
- return disallowed_types.none();
-}
-
-void NavigationDownloadPolicy::RecordHistogram() const {
- if (observed_types.none()) {
- LogPerPolicyApplied(NavigationDownloadType::kDefaultAllow);
- LogArbitraryPolicyPerDownload(NavigationDownloadType::kDefaultAllow);
- return;
- }
-
- bool first_type_seen = false;
- for (size_t i = 0; i < observed_types.size(); ++i) {
- if (observed_types.test(i)) {
- NavigationDownloadType policy = static_cast<NavigationDownloadType>(i);
- DCHECK(policy != NavigationDownloadType::kDefaultAllow);
- LogPerPolicyApplied(policy);
- if (!first_type_seen) {
- LogArbitraryPolicyPerDownload(policy);
- first_type_seen = true;
- }
- }
- }
- DCHECK(first_type_seen);
-}
-
CommonNavigationParams::CommonNavigationParams() = default;
CommonNavigationParams::CommonNavigationParams(
@@ -131,7 +55,9 @@ CommonNavigationParams::CommonNavigationParams(
bool started_from_context_menu,
bool has_user_gesture,
const InitiatorCSPInfo& initiator_csp_info,
+ const std::vector<int>& initiator_origin_trial_features,
const std::string& href_translate,
+ bool is_history_navigation_in_new_child_frame,
base::TimeTicks input_start)
: url(url),
initiator_origin(initiator_origin),
@@ -150,7 +76,10 @@ CommonNavigationParams::CommonNavigationParams(
started_from_context_menu(started_from_context_menu),
has_user_gesture(has_user_gesture),
initiator_csp_info(initiator_csp_info),
+ initiator_origin_trial_features(initiator_origin_trial_features),
href_translate(href_translate),
+ is_history_navigation_in_new_child_frame(
+ is_history_navigation_in_new_child_frame),
input_start(input_start) {
// |method != "POST"| should imply absence of |post_data|.
if (method != "POST" && post_data) {
@@ -176,7 +105,6 @@ CommitNavigationParams::CommitNavigationParams(
bool can_load_local_resources,
const PageState& page_state,
int nav_entry_id,
- bool is_history_navigation_in_new_child,
std::map<std::string, bool> subframe_unique_names,
bool intended_as_new_entry,
int pending_history_list_offset,
@@ -192,7 +120,6 @@ CommitNavigationParams::CommitNavigationParams(
can_load_local_resources(can_load_local_resources),
page_state(page_state),
nav_entry_id(nav_entry_id),
- is_history_navigation_in_new_child(is_history_navigation_in_new_child),
subframe_unique_names(subframe_unique_names),
intended_as_new_entry(intended_as_new_entry),
pending_history_list_offset(pending_history_list_offset),
diff --git a/chromium/content/common/navigation_params.h b/chromium/content/common/navigation_params.h
index 727f5cc15d1..f413d8e140a 100644
--- a/chromium/content/common/navigation_params.h
+++ b/chromium/content/common/navigation_params.h
@@ -7,9 +7,9 @@
#include <stdint.h>
-#include <bitset>
#include <map>
#include <string>
+#include <vector>
#include "base/memory/ref_counted.h"
#include "base/optional.h"
@@ -20,11 +20,12 @@
#include "content/common/content_security_policy/content_security_policy.h"
#include "content/common/content_security_policy/csp_disposition_enum.h"
#include "content/common/frame_message_enums.h"
+#include "content/common/prefetched_signed_exchange_info.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/common/navigation_policy.h"
#include "content/public/common/page_state.h"
#include "content/public/common/previews_state.h"
#include "content/public/common/referrer.h"
-#include "content/public/common/resource_intercept_policy.h"
#include "content/public/common/was_activated_option.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/resource_request_body.h"
@@ -81,76 +82,6 @@ struct CONTENT_EXPORT InitiatorCSPInfo {
base::Optional<CSPSource> initiator_self_source;
};
-// Navigation type that affects the download decision and relevant metrics to be
-// reported at download-discovery time.
-//
-// This enum backs a histogram. Please keep enums.xml up to date with any
-// changes, and new entries should be appended at the end. Never re-arrange /
-// re-use values.
-enum class NavigationDownloadType {
- // An entry reserved just for histogram. The client code is not expected to
- // set or query this type in a policy.
- kDefaultAllow = 0,
-
- kViewSource = 1,
- kInterstitial = 2,
-
- // The navigation was initiated on a x-origin opener.
- kOpenerCrossOrigin = 5,
-
- // The navigation was initiated from or occurred in an iframe with
- // |WebSandboxFlags::kDownloads| flag set and without user activation.
- kSandboxNoGesture = 7,
-
- // The navigation was initiated from or occurred in an ad frame without user
- // activation.
- kAdFrameNoGesture = 8,
-
- // The navigation was initiated from or occurred in an ad frame with user
- // activation.
- kAdFrameGesture = 9,
-
- kMaxValue = kAdFrameGesture
-};
-
-// Stores the navigation types that may be of interest to the download-related
-// metrics to be reported at download-discovery time. Also controls how
-// navigations behave when they turn into downloads. By default, navigation is
-// allowed to become a download.
-struct CONTENT_EXPORT NavigationDownloadPolicy {
- NavigationDownloadPolicy();
- ~NavigationDownloadPolicy();
- NavigationDownloadPolicy(const NavigationDownloadPolicy&);
-
- // Stores |type| to |observed_types|.
- void SetAllowed(NavigationDownloadType type);
-
- // Stores |type| to both |observed_types| and |disallowed_types|.
- void SetDisallowed(NavigationDownloadType type);
-
- // Returns if |observed_types| contains |type|.
- bool IsType(NavigationDownloadType type) const;
-
- // Get the ResourceInterceptPolicy derived from |disallowed_types|.
- ResourceInterceptPolicy GetResourceInterceptPolicy() const;
-
- // Returns if download is allowed based on |disallowed_types|.
- bool IsDownloadAllowed() const;
-
- // Record the download policy to histograms from |observed_types|.
- void RecordHistogram() const;
-
- // A bitset of navigation types observed that may be of interest to the
- // download-related metrics to be reported at download-discovery time.
- std::bitset<static_cast<size_t>(NavigationDownloadType::kMaxValue) + 1>
- observed_types;
-
- // A bitset of navigation types observed where if the navigation turns into
- // a download, the download should be dropped.
- std::bitset<static_cast<size_t>(NavigationDownloadType::kMaxValue) + 1>
- disallowed_types;
-};
-
// Used by all navigation IPCs.
struct CONTENT_EXPORT CommonNavigationParams {
CommonNavigationParams();
@@ -172,7 +103,9 @@ struct CONTENT_EXPORT CommonNavigationParams {
bool started_from_context_menu,
bool has_user_gesture,
const InitiatorCSPInfo& initiator_csp_info,
+ const std::vector<int>& initiator_origin_trial_features,
const std::string& href_translate,
+ bool is_history_navigation_in_new_child_frame,
base::TimeTicks input_start = base::TimeTicks());
CommonNavigationParams(const CommonNavigationParams& other);
~CommonNavigationParams();
@@ -247,6 +180,13 @@ struct CONTENT_EXPORT CommonNavigationParams {
// We require a copy of the relevant CSP to perform navigation checks.
InitiatorCSPInfo initiator_csp_info;
+ // The origin trial features activated in the initiator that should be applied
+ // in the document being navigated to. The int values are blink
+ // OriginTrialFeature enum values. OriginTrialFeature enum is not visible
+ // outside of blink (and doesn't need to be) so these values are casted to int
+ // as they are passed through content across navigations.
+ std::vector<int> initiator_origin_trial_features;
+
// The current origin policy for this request's origin.
// (Empty if none applies.)
std::string origin_policy;
@@ -255,6 +195,13 @@ struct CONTENT_EXPORT CommonNavigationParams {
// from a link that had that attribute set.
std::string href_translate;
+ // Whether this is a history navigation in a newly created child frame, in
+ // which case the browser process is instructing the renderer process to load
+ // a URL from a session history item. Defaults to false.
+ // TODO(ahemery): Move this to BeginNavigationParams once we default to
+ // IsPerNavigationMojoInterface().
+ bool is_history_navigation_in_new_child_frame = false;
+
// The time the input event leading to the navigation occurred. This will
// not always be set; it depends on the creator of the CommonNavigationParams
// setting it.
@@ -284,7 +231,6 @@ struct CONTENT_EXPORT CommitNavigationParams {
bool can_load_local_resources,
const PageState& page_state,
int nav_entry_id,
- bool is_history_navigation_in_new_child,
std::map<std::string, bool> subframe_unique_names,
bool intended_as_new_entry,
int pending_history_list_offset,
@@ -336,11 +282,6 @@ struct CONTENT_EXPORT CommitNavigationParams {
// the resulting FrameHostMsg_DidCommitProvisionalLoad_Params.
int nav_entry_id = 0;
- // Whether this is a history navigation in a newly created child frame, in
- // which case the browser process is instructing the renderer process to load
- // a URL from a session history item. Defaults to false.
- bool is_history_navigation_in_new_child = false;
-
// If this is a history navigation, this contains a map of frame unique names
// to |is_about_blank| for immediate children of the frame being navigated for
// which there are history items. The renderer process only needs to check
@@ -385,7 +326,7 @@ struct CONTENT_EXPORT CommitNavigationParams {
NavigationTiming navigation_timing;
// The AppCache host id to be used to identify this navigation.
- int appcache_host_id = blink::mojom::kAppCacheNoHostId;
+ base::Optional<base::UnguessableToken> appcache_host_id;
// Set to |kYes| if a navigation is following the rules of user activation
// propagation. This is different from |has_user_gesture|
@@ -403,6 +344,10 @@ struct CONTENT_EXPORT CommitNavigationParams {
// same-document browser-initiated navigations are properly handled as well.
base::UnguessableToken navigation_token;
+ // Prefetched signed exchanges. Used when SignedExchangeSubresourcePrefetch
+ // feature is enabled.
+ std::vector<PrefetchedSignedExchangeInfo> prefetched_signed_exchanges;
+
#if defined(OS_ANDROID)
// The real content of the data: URL. Only used in Android WebView for
// implementing LoadDataWithBaseUrl API method to circumvent the restriction
diff --git a/chromium/content/common/navigation_params.mojom b/chromium/content/common/navigation_params.mojom
index 634e3b7af7e..a8d80279240 100644
--- a/chromium/content/common/navigation_params.mojom
+++ b/chromium/content/common/navigation_params.mojom
@@ -41,6 +41,9 @@ struct BeginNavigationParams {
// Whether or not the navigation has been initiated by a form submission.
bool is_form_submission;
+ // Whether or not the navigation has been initiated by a link click.
+ bool was_initiated_by_link_click;
+
// See WebSearchableFormData for a description of these.
url.mojom.Url searchable_form_url;
string searchable_form_encoding;
diff --git a/chromium/content/common/prefetched_signed_exchange_info.cc b/chromium/content/common/prefetched_signed_exchange_info.cc
new file mode 100644
index 00000000000..2f6fdcae64e
--- /dev/null
+++ b/chromium/content/common/prefetched_signed_exchange_info.cc
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/prefetched_signed_exchange_info.h"
+
+namespace content {
+
+PrefetchedSignedExchangeInfo::PrefetchedSignedExchangeInfo() = default;
+PrefetchedSignedExchangeInfo::PrefetchedSignedExchangeInfo(
+ const PrefetchedSignedExchangeInfo&) = default;
+PrefetchedSignedExchangeInfo::PrefetchedSignedExchangeInfo(
+ const GURL& outer_url,
+ const net::SHA256HashValue& header_integrity,
+ const GURL& inner_url,
+ const network::ResourceResponseHead& inner_response,
+ mojo::MessagePipeHandle loader_factory_handle)
+ : outer_url(outer_url),
+ header_integrity(header_integrity),
+ inner_url(inner_url),
+ inner_response(inner_response),
+ loader_factory_handle(loader_factory_handle) {}
+PrefetchedSignedExchangeInfo::~PrefetchedSignedExchangeInfo() = default;
+
+} // namespace content
diff --git a/chromium/content/common/prefetched_signed_exchange_info.h b/chromium/content/common/prefetched_signed_exchange_info.h
new file mode 100644
index 00000000000..3555c09e716
--- /dev/null
+++ b/chromium/content/common/prefetched_signed_exchange_info.h
@@ -0,0 +1,40 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_PREFETCHED_SIGNED_EXCHANGE_INFO_H_
+#define CONTENT_COMMON_PREFETCHED_SIGNED_EXCHANGE_INFO_H_
+
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "net/base/hash_value.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// Used for SignedExchangeSubresourcePrefetch.
+// This struct keeps the information about a prefetched signed exchange. It is
+// used in CommitNavigationParams to be passed from the browser process to the
+// renderer process in CommitNavigation IPC.
+struct CONTENT_EXPORT PrefetchedSignedExchangeInfo {
+ PrefetchedSignedExchangeInfo();
+ PrefetchedSignedExchangeInfo(const PrefetchedSignedExchangeInfo&);
+ PrefetchedSignedExchangeInfo(
+ const GURL& outer_url,
+ const net::SHA256HashValue& header_integrity,
+ const GURL& inner_url,
+ const network::ResourceResponseHead& inner_response,
+ mojo::MessagePipeHandle loader_factory_handle);
+ ~PrefetchedSignedExchangeInfo();
+
+ GURL outer_url;
+ net::SHA256HashValue header_integrity;
+ GURL inner_url;
+ network::ResourceResponseHead inner_response;
+ mojo::MessagePipeHandle loader_factory_handle;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_PREFETCHED_SIGNED_EXCHANGE_INFO_H_
diff --git a/chromium/content/common/push_messaging.mojom b/chromium/content/common/push_messaging.mojom
deleted file mode 100644
index 7966268f95e..00000000000
--- a/chromium/content/common/push_messaging.mojom
+++ /dev/null
@@ -1,53 +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.
-
-module content.mojom;
-
-import "content/public/common/push_messaging_status.mojom";
-import "url/mojom/url.mojom";
-
-// TODO(heke): The type-mapping struct and enums are duplicately defined. Need
-// to remove/replace those defined in content or blink namespace.
-
-struct PushSubscriptionOptions {
- bool user_visible_only;
- string sender_info;
-};
-
-enum PushErrorType {
- ABORT = 0,
- NETWORK = 1,
- NONE = 2,
- NOT_ALLOWED = 3,
- NOT_FOUND = 4,
- NOT_SUPPORTED = 5,
- INVALID_STATE = 6,
-};
-
-interface PushMessaging {
- Subscribe(int32 render_frame_id,
- int64 service_worker_registration_id,
- PushSubscriptionOptions options,
- bool user_gesture)
- => (PushRegistrationStatus status,
- url.mojom.Url? endpoint,
- PushSubscriptionOptions? options,
- array<uint8>? p256dh,
- array<uint8>? auth);
-
- // We use the value of |error_type| as a flag. If |error_type| == NONE, it
- // means no error and returns |did_unsubscribe|. Else, it means there is an
- // error and returns |error_type| and |error_message|.
- Unsubscribe(int64 service_worker_registration_id)
- => (PushErrorType error_type,
- bool did_unsubscribe,
- string? error_message);
-
- GetSubscription(int64 service_worker_registration_id)
- => (PushGetRegistrationStatus status,
- url.mojom.Url? endpoint,
- PushSubscriptionOptions? options,
- array<uint8>? p256dh,
- array<uint8>? auth);
-};
diff --git a/chromium/content/common/push_messaging.typemap b/chromium/content/common/push_messaging.typemap
deleted file mode 100644
index 62eaf37df81..00000000000
--- a/chromium/content/common/push_messaging.typemap
+++ /dev/null
@@ -1,23 +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.
-
-mojom = "//content/common/push_messaging.mojom"
-public_headers = [
- "//content/public/common/push_subscription_options.h",
- "//third_party/blink/public/platform/modules/push_messaging/web_push_error.h",
-]
-traits_headers = [ "//content/common/push_messaging_param_traits.h" ]
-sources = [
- "//content/common/push_messaging_param_traits.cc",
-]
-deps = [
- "//content:export",
-]
-public_deps = [
- "//third_party/blink/public:blink_headers",
-]
-type_mappings = [
- "content.mojom.PushErrorType=blink::WebPushError::ErrorType",
- "content.mojom.PushSubscriptionOptions=content::PushSubscriptionOptions",
-]
diff --git a/chromium/content/common/push_messaging_param_traits.cc b/chromium/content/common/push_messaging_param_traits.cc
deleted file mode 100644
index c28c61778dd..00000000000
--- a/chromium/content/common/push_messaging_param_traits.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 "content/common/push_messaging_param_traits.h"
-
-#include "content/public/common/push_messaging_status.mojom.h"
-
-namespace mojo {
-
-// PushErrorType
-static_assert(blink::WebPushError::ErrorType::kErrorTypeAbort ==
- static_cast<blink::WebPushError::ErrorType>(
- content::mojom::PushErrorType::ABORT),
- "PushErrorType enums must match, ABORT");
-
-static_assert(blink::WebPushError::ErrorType::kErrorTypeNetwork ==
- static_cast<blink::WebPushError::ErrorType>(
- content::mojom::PushErrorType::NETWORK),
- "PushErrorType enums must match, NETWORK");
-
-static_assert(blink::WebPushError::ErrorType::kErrorTypeNone ==
- static_cast<blink::WebPushError::ErrorType>(
- content::mojom::PushErrorType::NONE),
- "PushErrorType enums must match, NONE");
-
-static_assert(blink::WebPushError::ErrorType::kErrorTypeNotAllowed ==
- static_cast<blink::WebPushError::ErrorType>(
- content::mojom::PushErrorType::NOT_ALLOWED),
- "PushErrorType enums must match, NOT_ALLOWED");
-
-static_assert(blink::WebPushError::ErrorType::kErrorTypeNotFound ==
- static_cast<blink::WebPushError::ErrorType>(
- content::mojom::PushErrorType::NOT_FOUND),
- "PushErrorType enums must match, NOT_FOUND");
-
-static_assert(blink::WebPushError::ErrorType::kErrorTypeNotSupported ==
- static_cast<blink::WebPushError::ErrorType>(
- content::mojom::PushErrorType::NOT_SUPPORTED),
- "PushErrorType enums must match, NOT_SUPPORTED");
-
-static_assert(blink::WebPushError::ErrorType::kErrorTypeInvalidState ==
- static_cast<blink::WebPushError::ErrorType>(
- content::mojom::PushErrorType::INVALID_STATE),
- "PushErrorType enums must match, INVALID_STATE");
-
-static_assert(blink::WebPushError::ErrorType::kErrorTypeLast ==
- static_cast<blink::WebPushError::ErrorType>(
- content::mojom::PushErrorType::kMaxValue),
- "PushErrorType enums must match, kMaxValue");
-
-// static
-bool StructTraits<content::mojom::PushSubscriptionOptionsDataView,
- content::PushSubscriptionOptions>::
- Read(content::mojom::PushSubscriptionOptionsDataView data,
- content::PushSubscriptionOptions* out) {
- out->user_visible_only = data.user_visible_only();
- if (!data.ReadSenderInfo(&out->sender_info)) {
- return false;
- }
- return true;
-}
-
-// static
-content::mojom::PushErrorType
-EnumTraits<content::mojom::PushErrorType, blink::WebPushError::ErrorType>::
- ToMojom(blink::WebPushError::ErrorType input) {
- if (input >= blink::WebPushError::ErrorType::kErrorTypeAbort &&
- input <= blink::WebPushError::ErrorType::kErrorTypeInvalidState) {
- return static_cast<content::mojom::PushErrorType>(input);
- }
-
- NOTREACHED();
- return content::mojom::PushErrorType::ABORT;
-}
-
-// static
-bool EnumTraits<content::mojom::PushErrorType, blink::WebPushError::ErrorType>::
- FromMojom(content::mojom::PushErrorType input,
- blink::WebPushError::ErrorType* output) {
- if (input >= content::mojom::PushErrorType::ABORT &&
- input <= content::mojom::PushErrorType::INVALID_STATE) {
- *output = static_cast<blink::WebPushError::ErrorType>(input);
- return true;
- }
-
- NOTREACHED();
- return false;
-}
-
-} // namespace mojo
diff --git a/chromium/content/common/push_messaging_param_traits.h b/chromium/content/common/push_messaging_param_traits.h
deleted file mode 100644
index dcf5b0c72f9..00000000000
--- a/chromium/content/common/push_messaging_param_traits.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_COMMON_PUSH_MESSAGING_PARAM_TRAITS_H_
-#define CONTENT_COMMON_PUSH_MESSAGING_PARAM_TRAITS_H_
-
-#include <stddef.h>
-
-#include "content/common/push_messaging.mojom.h"
-#include "content/public/common/push_messaging_status.mojom.h"
-#include "mojo/public/cpp/bindings/struct_traits.h"
-
-namespace mojo {
-
-template <>
-struct StructTraits<content::mojom::PushSubscriptionOptionsDataView,
- content::PushSubscriptionOptions> {
- static bool user_visible_only(const content::PushSubscriptionOptions& r) {
- return r.user_visible_only;
- }
- static const std::string& sender_info(
- const content::PushSubscriptionOptions& r) {
- return r.sender_info;
- }
- static bool Read(content::mojom::PushSubscriptionOptionsDataView data,
- content::PushSubscriptionOptions* out);
-};
-
-template <>
-struct EnumTraits<content::mojom::PushErrorType,
- blink::WebPushError::ErrorType> {
- static content::mojom::PushErrorType ToMojom(
- blink::WebPushError::ErrorType input);
- static bool FromMojom(content::mojom::PushErrorType input,
- blink::WebPushError::ErrorType* output);
-};
-
-} // namespace mojo
-
-#endif // CONTENT_COMMON_PUSH_MESSAGING_PARAM_TRAITS_H_
diff --git a/chromium/content/common/render_frame_metadata.mojom b/chromium/content/common/render_frame_metadata.mojom
index f1302d7d626..6b841ddd398 100644
--- a/chromium/content/common/render_frame_metadata.mojom
+++ b/chromium/content/common/render_frame_metadata.mojom
@@ -85,17 +85,26 @@ struct RenderFrameMetadata {
bool has_transparent_background;
};
-// This interface is provided by the renderer. It can optionally enable
-// notifications for all frame submissions.
+// This interface is provided by the renderer. It impacts the frequency with
+// which a fully populated RenderFrameMetadata object (above) is delivered to
+// the RenderFrameMetadataObserverClient.
interface RenderFrameMetadataObserver {
- // When |enabled| is set to true, this will notify the associated client of
- // all frame submissions.
+ // When |enabled| is set to true, this will send RenderFrameMetadata to
+ // the RenderFrameMetadataObserverClient for any frame in which the root
+ // scroll changes. Used only on Android for accessibility cases.
+ [EnableIf=is_android]
+ ReportAllRootScrollsForAccessibility(bool enabled);
+ // When |enabled| is set to true, this will send RenderFrameMetadata to
+ // the RenderFrameMetadataObserverClient for all frames. Only used for
+ // tests.
ReportAllFrameSubmissionsForTesting(bool enabled);
};
-// This interface is provided by the browser. It is notified of all changes to
+// This interface is provided by the browser. It is notified of changes to
// RenderFrameMetadata. It can be notified of all frame submissions, via
-// RenderFrameMetadataObserver::ReportAllFrameSubmissionsForTesting.
+// RenderFrameMetadataObserver::ReportAllFrameSubmissionsForTesting, or of
+// additional frames with root scroll offset changes via
+// RenderFrameMetadataObserver::ReportAllRootScrollsForAccessibility.
interface RenderFrameMetadataObserverClient {
// Notified when RenderFrameMetadata has changed.
OnRenderFrameMetadataChanged(uint32 frame_token, RenderFrameMetadata metadata);
diff --git a/chromium/content/common/render_widget_window_tree_client_factory.mojom b/chromium/content/common/render_widget_window_tree_client_factory.mojom
deleted file mode 100644
index 7a92ea9cb05..00000000000
--- a/chromium/content/common/render_widget_window_tree_client_factory.mojom
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module content.mojom;
-
-import "mojo/public/mojom/base/unguessable_token.mojom";
-import "services/ws/public/mojom/window_tree.mojom";
-
-interface RenderWidgetWindowTreeClient {
- // Asks the renderer to create a Window for the frame with the routing id
- // |routing_id| and embeds the WindowTreeClient that was previously supplied
- // to ScheduleEmbed().
- Embed(uint32 frame_routing_id, mojo_base.mojom.UnguessableToken token);
-
- // Called when a render frame has been destroyed. This is sent via mojom
- // to handle to ensure there aren't race conditions because of message order
- // delivery.
- DestroyFrame(uint32 frame_routing_id);
-};
-
-interface RenderWidgetWindowTreeClientFactory {
- CreateWindowTreeClientForRenderWidget(
- uint32 render_widget_host_routing_id,
- ws.mojom.WindowTreeClient& window_tree_client,
- RenderWidgetWindowTreeClient& render_widget_window_tree_client_request);
-};
diff --git a/chromium/content/common/sandbox_init_mac.cc b/chromium/content/common/sandbox_init_mac.cc
index 398a345470f..64e125805be 100644
--- a/chromium/content/common/sandbox_init_mac.cc
+++ b/chromium/content/common/sandbox_init_mac.cc
@@ -34,7 +34,7 @@ base::OnceClosure MaybeWrapWithGPUSandboxHook(
if (sandbox_type != service_manager::SANDBOX_TYPE_GPU)
return original;
- return base::Bind(
+ return base::BindOnce(
[](base::OnceClosure arg) {
// We need to gather GPUInfo and compute GpuFeatureInfo here, so we can
// decide if initializing core profile or compatibility profile GL,
@@ -72,7 +72,7 @@ base::OnceClosure MaybeWrapWithGPUSandboxHook(
if (!arg.is_null())
std::move(arg).Run();
},
- base::Passed(std::move(original)));
+ std::move(original));
}
// Fill in |sandbox_type| based on the command line. Returns false if the
diff --git a/chromium/content/common/service_manager/OWNERS b/chromium/content/common/service_manager/OWNERS
index 361b230c7c3..c05943e3277 100644
--- a/chromium/content/common/service_manager/OWNERS
+++ b/chromium/content/common/service_manager/OWNERS
@@ -1,4 +1,3 @@
-ben@chromium.org
rockot@google.com
per-file *_messages*.h=set noparent
diff --git a/chromium/content/common/service_manager/child_connection.cc b/chromium/content/common/service_manager/child_connection.cc
index 6f643029986..b359c59b7fb 100644
--- a/chromium/content/common/service_manager/child_connection.cc
+++ b/chromium/content/common/service_manager/child_connection.cc
@@ -14,6 +14,7 @@
#include "base/strings/string_number_conversions.h"
#include "content/common/child.mojom.h"
#include "content/public/common/service_manager_connection.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/identity.h"
@@ -87,27 +88,26 @@ class ChildConnection::IOThreadContext
void InitializeOnIOThread(
const service_manager::Identity& child_identity,
mojo::ScopedMessagePipeHandle service_pipe) {
- service_manager::mojom::ServicePtr service;
- service.Bind(mojo::InterfacePtrInfo<service_manager::mojom::Service>(
- std::move(service_pipe), 0u));
- auto pid_receiver_request = mojo::MakeRequest(&pid_receiver_);
-
+ auto metadata_receiver = remote_metadata_.BindNewPipeAndPassReceiver();
if (connector_) {
- connector_->RegisterServiceInstance(child_identity, std::move(service),
- std::move(pid_receiver_request));
+ connector_->RegisterServiceInstance(
+ child_identity,
+ mojo::PendingRemote<service_manager::mojom::Service>(
+ std::move(service_pipe), 0),
+ std::move(metadata_receiver));
connector_->BindInterface(child_identity, &child_);
}
}
void ShutDownOnIOThread() {
connector_.reset();
- pid_receiver_.reset();
+ remote_metadata_.reset();
}
void SetProcessOnIOThread(base::Process process) {
- DCHECK(pid_receiver_.is_bound());
- pid_receiver_->SetPID(process.Pid());
- pid_receiver_.reset();
+ DCHECK(remote_metadata_);
+ remote_metadata_->SetPID(process.Pid());
+ remote_metadata_.reset();
process_ = std::move(process);
}
@@ -119,7 +119,7 @@ class ChildConnection::IOThreadContext
service_manager::Identity child_identity_;
// ServiceManagerConnection in the child monitors the lifetime of this pipe.
mojom::ChildPtr child_;
- service_manager::mojom::PIDReceiverPtr pid_receiver_;
+ mojo::Remote<service_manager::mojom::ProcessMetadata> remote_metadata_;
// Hold onto the process, and thus its process handle, so that the pid will
// remain valid.
base::Process process_;
diff --git a/chromium/content/common/service_manager/service_manager_connection_impl.cc b/chromium/content/common/service_manager/service_manager_connection_impl.cc
index 494afe3ccb2..64240624495 100644
--- a/chromium/content/common/service_manager/service_manager_connection_impl.cc
+++ b/chromium/content/common/service_manager/service_manager_connection_impl.cc
@@ -250,7 +250,8 @@ class ServiceManagerConnectionImpl::IOThreadContext
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override {
DCHECK(io_thread_checker_.CalledOnValidThread());
- if (source_info.identity.name() == mojom::kBrowserServiceName &&
+ if ((source_info.identity.name() == mojom::kBrowserServiceName ||
+ source_info.identity.name() == mojom::kSystemServiceName) &&
interface_name == mojom::Child::Name_) {
DCHECK(!child_binding_.is_bound());
child_binding_.Bind(mojom::ChildRequest(std::move(interface_pipe)));
diff --git a/chromium/content/common/service_manager/service_manager_connection_impl_unittest.cc b/chromium/content/common/service_manager/service_manager_connection_impl_unittest.cc
index f5e49fb5fff..f037b6b2e97 100644
--- a/chromium/content/common/service_manager/service_manager_connection_impl_unittest.cc
+++ b/chromium/content/common/service_manager/service_manager_connection_impl_unittest.cc
@@ -9,10 +9,10 @@
#include "base/test/bind_test_util.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/service_manager/public/cpp/constants.h"
#include "services/service_manager/public/cpp/identity.h"
#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/mojom/service_factory.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -37,22 +37,15 @@ TEST(ServiceManagerConnectionImplTest, ServiceLaunchThreading) {
[&event](service_manager::mojom::ServiceRequest) {
event.Signal();
}));
-
connection.Start();
- service_manager::BindSourceInfo source_info(
- service_manager::Identity(service_manager::mojom::kServiceName,
- service_manager::kSystemInstanceGroup,
- base::Token{}, base::Token::CreateRandom()),
- service_manager::CapabilitySet());
- service_manager::mojom::ServiceFactoryPtr factory;
- service->OnBindInterface(
- source_info, service_manager::mojom::ServiceFactory::Name_,
- mojo::MakeRequest(&factory).PassMessagePipe(), base::DoNothing());
- service_manager::mojom::ServicePtr created_service;
- service_manager::mojom::PIDReceiverPtr pid_receiver;
- mojo::MakeRequest(&pid_receiver);
- factory->CreateService(mojo::MakeRequest(&created_service), kTestServiceName,
- std::move(pid_receiver));
+
+ mojo::PendingRemote<service_manager::mojom::Service> packaged_service;
+ mojo::PendingRemote<service_manager::mojom::ProcessMetadata> metadata;
+ ignore_result(metadata.InitWithNewPipeAndPassReceiver());
+ service->CreatePackagedServiceInstance(
+ service_manager::Identity(kTestServiceName, base::Token::CreateRandom(),
+ base::Token(), base::Token::CreateRandom()),
+ packaged_service.InitWithNewPipeAndPassReceiver(), std::move(metadata));
event.Wait();
}
diff --git a/chromium/content/common/service_worker/service_worker_loader_helpers.cc b/chromium/content/common/service_worker/service_worker_loader_helpers.cc
index 892d1abb6a4..d5fa140dda4 100644
--- a/chromium/content/common/service_worker/service_worker_loader_helpers.cc
+++ b/chromium/content/common/service_worker/service_worker_loader_helpers.cc
@@ -65,8 +65,8 @@ void ServiceWorkerLoaderHelpers::SaveResponseHeaders(
}
buf.append("\r\n");
- out_head->headers = new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(buf.c_str(), buf.size()));
+ out_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(buf));
// Populate |out_head|'s MIME type with the value from the HTTP response
// headers.
diff --git a/chromium/content/common/service_worker/service_worker_types.h b/chromium/content/common/service_worker/service_worker_types.h
index a279ed18f38..4ea6959e402 100644
--- a/chromium/content/common/service_worker/service_worker_types.h
+++ b/chromium/content/common/service_worker/service_worker_types.h
@@ -16,8 +16,8 @@
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/public/common/referrer.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
+#include "third_party/blink/public/mojom/loader/request_context_frame_type.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_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
diff --git a/chromium/content/common/service_worker/service_worker_utils.cc b/chromium/content/common/service_worker/service_worker_utils.cc
index 1624d667385..d54e374b9c0 100644
--- a/chromium/content/common/service_worker/service_worker_utils.cc
+++ b/chromium/content/common/service_worker/service_worker_utils.cc
@@ -194,6 +194,16 @@ bool ServiceWorkerUtils::ShouldBypassCacheDueToUpdateViaCache(
return false;
}
+bool ServiceWorkerUtils::ShouldValidateBrowserCacheForScript(
+ bool is_main_script,
+ bool force_bypass_cache,
+ blink::mojom::ServiceWorkerUpdateViaCache cache_mode,
+ base::TimeDelta time_since_last_check) {
+ return (ShouldBypassCacheDueToUpdateViaCache(is_main_script, cache_mode) ||
+ time_since_last_check > kServiceWorkerScriptMaxCacheAge ||
+ force_bypass_cache);
+}
+
// static
blink::mojom::FetchCacheMode ServiceWorkerUtils::GetCacheModeFromLoadFlags(
int load_flags) {
@@ -309,15 +319,26 @@ const char* ServiceWorkerUtils::FetchResponseSourceToSuffix(
return ".Unknown";
}
-void ServiceWorkerUtils::SendHttpResponseInfoToClient(
+ServiceWorkerUtils::ResourceResponseHeadAndMetadata::
+ ResourceResponseHeadAndMetadata(network::ResourceResponseHead head,
+ std::vector<uint8_t> metadata)
+ : head(std::move(head)), metadata(std::move(metadata)) {}
+
+ServiceWorkerUtils::ResourceResponseHeadAndMetadata::
+ ResourceResponseHeadAndMetadata(ResourceResponseHeadAndMetadata&& other) =
+ default;
+
+ServiceWorkerUtils::ResourceResponseHeadAndMetadata::
+ ~ResourceResponseHeadAndMetadata() = default;
+
+ServiceWorkerUtils::ResourceResponseHeadAndMetadata
+ServiceWorkerUtils::CreateResourceResponseHeadAndMetadata(
const net::HttpResponseInfo* http_info,
uint32_t options,
base::TimeTicks request_start_time,
base::TimeTicks response_start_time,
- int response_data_size,
- network::mojom::URLLoaderClientProxy* client_proxy) {
+ int response_data_size) {
DCHECK(http_info);
- DCHECK(client_proxy);
network::ResourceResponseHead head;
head.request_start = request_start_time;
@@ -338,14 +359,13 @@ void ServiceWorkerUtils::SendHttpResponseInfoToClient(
if (options & network::mojom::kURLLoadOptionSendSSLInfoWithResponse)
head.ssl_info = http_info->ssl_info;
- client_proxy->OnReceiveResponse(head);
-
+ std::vector<uint8_t> metadata;
if (http_info->metadata) {
const uint8_t* data =
reinterpret_cast<const uint8_t*>(http_info->metadata->data());
- client_proxy->OnReceiveCachedMetadata(
- std::vector<uint8_t>(data, data + http_info->metadata->size()));
+ metadata = {data, data + http_info->metadata->size()};
}
+ return {std::move(head), std::move(metadata)};
}
bool LongestScopeMatcher::MatchLongest(const GURL& scope) {
diff --git a/chromium/content/common/service_worker/service_worker_utils.h b/chromium/content/common/service_worker/service_worker_utils.h
index ad50f75fa20..cb103548ddc 100644
--- a/chromium/content/common/service_worker/service_worker_utils.h
+++ b/chromium/content/common/service_worker/service_worker_utils.h
@@ -69,6 +69,12 @@ class ServiceWorkerUtils {
bool is_main_script,
blink::mojom::ServiceWorkerUpdateViaCache cache_mode);
+ static bool ShouldValidateBrowserCacheForScript(
+ bool is_main_script,
+ bool force_bypass_cache,
+ blink::mojom::ServiceWorkerUpdateViaCache cache_mode,
+ base::TimeDelta time_since_last_check);
+
// Converts an enum defined in net/base/load_flags.h to
// blink::mojom::FetchCacheMode.
CONTENT_EXPORT static blink::mojom::FetchCacheMode GetCacheModeFromLoadFlags(
@@ -83,13 +89,24 @@ class ServiceWorkerUtils {
CONTENT_EXPORT static const char* FetchResponseSourceToSuffix(
network::mojom::FetchResponseSource source);
- CONTENT_EXPORT static void SendHttpResponseInfoToClient(
- const net::HttpResponseInfo* http_info,
- uint32_t options,
- base::TimeTicks request_start_time,
- base::TimeTicks response_start_time,
- int response_data_size,
- network::mojom::URLLoaderClientProxy* client_proxy);
+ struct CONTENT_EXPORT ResourceResponseHeadAndMetadata {
+ ResourceResponseHeadAndMetadata(network::ResourceResponseHead head,
+ std::vector<uint8_t> metadata);
+ ResourceResponseHeadAndMetadata(ResourceResponseHeadAndMetadata&& other);
+ ResourceResponseHeadAndMetadata(
+ const ResourceResponseHeadAndMetadata& other) = delete;
+ ~ResourceResponseHeadAndMetadata();
+
+ network::ResourceResponseHead head;
+ std::vector<uint8_t> metadata;
+ };
+
+ CONTENT_EXPORT static ResourceResponseHeadAndMetadata
+ CreateResourceResponseHeadAndMetadata(const net::HttpResponseInfo* http_info,
+ uint32_t options,
+ base::TimeTicks request_start_time,
+ base::TimeTicks response_start_time,
+ int response_data_size);
private:
static bool IsPathRestrictionSatisfiedInternal(
diff --git a/chromium/content/common/swapped_out_messages.cc b/chromium/content/common/swapped_out_messages.cc
index a17bd780ed7..24e0f0f016d 100644
--- a/chromium/content/common/swapped_out_messages.cc
+++ b/chromium/content/common/swapped_out_messages.cc
@@ -18,10 +18,8 @@ bool SwappedOutMessages::CanSendWhileSwappedOut(const IPC::Message* msg) {
// consistent in case we later return to the same renderer.
switch (msg->type()) {
// Handled by RenderViewHost.
- case FrameHostMsg_RenderProcessGone::ID:
case ViewHostMsg_ClosePage_ACK::ID:
case ViewHostMsg_Focus::ID:
- case ViewHostMsg_OpenDateTimeDialog::ID:
case ViewHostMsg_ShowFullscreenWidget::ID:
case ViewHostMsg_ShowWidget::ID:
case ViewHostMsg_UpdateTargetURL::ID:
diff --git a/chromium/content/common/tab_switch_time_recorder.cc b/chromium/content/common/tab_switch_time_recorder.cc
index c404d4d5bdf..d188865d2a8 100644
--- a/chromium/content/common/tab_switch_time_recorder.cc
+++ b/chromium/content/common/tab_switch_time_recorder.cc
@@ -8,61 +8,146 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
#include "ui/gfx/presentation_feedback.h"
namespace content {
+namespace {
+
+// Used to generate unique "TabSwitching::Latency" event ids. Note: The address
+// of TabSwitchTimeRecorder can't be used as an id because a single
+// TabSwitchTimeRecorder can generate multiple overlapping events.
+int g_num_trace_events_in_process = 0;
+
+const char* GetHistogramSuffix(bool has_saved_frames,
+ const RecordTabSwitchTimeRequest& start_state) {
+ if (has_saved_frames)
+ return "WithSavedFrames";
+
+ if (start_state.destination_is_loaded) {
+ if (start_state.destination_is_frozen) {
+ return "NoSavedFrames_Loaded_Frozen";
+ } else {
+ return "NoSavedFrames_Loaded_NotFrozen";
+ }
+ } else {
+ return "NoSavedFrames_NotLoaded";
+ }
+}
+
+} // namespace
+
+RecordTabSwitchTimeRequest::RecordTabSwitchTimeRequest(
+ base::TimeTicks tab_switch_start_time,
+ bool destination_is_loaded,
+ bool destination_is_frozen)
+ : tab_switch_start_time(tab_switch_start_time),
+ destination_is_loaded(destination_is_loaded),
+ destination_is_frozen(destination_is_frozen) {}
+
TabSwitchTimeRecorder::TabSwitchTimeRecorder() : weak_ptr_factory_(this) {}
TabSwitchTimeRecorder::~TabSwitchTimeRecorder() {}
base::OnceCallback<void(const gfx::PresentationFeedback&)>
-TabSwitchTimeRecorder::BeginTimeRecording(
- const base::TimeTicks tab_switch_start_time,
+TabSwitchTimeRecorder::TabWasShown(
bool has_saved_frames,
- const base::TimeTicks render_widget_visibility_request_timestamp) {
- TRACE_EVENT_ASYNC_BEGIN0("latency", "TabSwitching::Latency",
- TRACE_ID_LOCAL(this));
-
- // Reset all previously generated callbacks to enforce matching
- // BeginTimeRecording and DidPresentFrame calls. The reason to do this is
- // because sometimes, we could generate the callback on a tab switch, but no
- // frame submission occurs, potentially causing wrong metric to be uploaded on
- // the next tab switch. See crbug.com/936858 for more detail.
- weak_ptr_factory_.InvalidateWeakPtrs();
- if (tab_switch_start_time.is_null())
- return base::DoNothing();
- else
- return base::BindOnce(&TabSwitchTimeRecorder::DidPresentFrame, GetWeakPtr(),
- has_saved_frames, tab_switch_start_time,
- render_widget_visibility_request_timestamp);
+ const RecordTabSwitchTimeRequest& start_state,
+ base::TimeTicks render_widget_visibility_request_timestamp) {
+ DCHECK(!start_state.tab_switch_start_time.is_null());
+ DCHECK(!render_widget_visibility_request_timestamp.is_null());
+ DCHECK(!tab_switch_start_state_);
+ DCHECK(render_widget_visibility_request_timestamp_.is_null());
+
+ has_saved_frames_ = has_saved_frames;
+ tab_switch_start_state_ = start_state;
+ render_widget_visibility_request_timestamp_ =
+ render_widget_visibility_request_timestamp;
+
+ // |tab_switch_start_state_| is only reset by RecordHistogramsAndTraceEvents
+ // once the metrics have been emitted.
+ return base::BindOnce(&TabSwitchTimeRecorder::RecordHistogramsAndTraceEvents,
+ weak_ptr_factory_.GetWeakPtr(),
+ false /* is_incomplete */);
}
-void TabSwitchTimeRecorder::DidPresentFrame(
- bool has_saved_frames,
- base::TimeTicks tab_switch_start_time,
- base::TimeTicks render_widget_visibility_request_timestamp,
+void TabSwitchTimeRecorder::TabWasHidden() {
+ if (tab_switch_start_state_) {
+ RecordHistogramsAndTraceEvents(true /* is_incomplete */,
+ gfx::PresentationFeedback::Failure());
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ }
+}
+
+void TabSwitchTimeRecorder::RecordHistogramsAndTraceEvents(
+ bool is_incomplete,
const gfx::PresentationFeedback& feedback) {
- const auto delta = feedback.timestamp - tab_switch_start_time;
+ DCHECK(tab_switch_start_state_);
+ DCHECK(!render_widget_visibility_request_timestamp_.is_null());
- if (has_saved_frames) {
- UMA_HISTOGRAM_TIMES("Browser.Tabs.TotalSwitchDuration.WithSavedFrames",
- delta);
- } else {
- UMA_HISTOGRAM_TIMES("Browser.Tabs.TotalSwitchDuration.NoSavedFrames",
- delta);
- }
+ auto tab_switch_result = TabSwitchResult::kSuccess;
+ if (is_incomplete)
+ tab_switch_result = TabSwitchResult::kIncomplete;
+ else if (feedback.flags & gfx::PresentationFeedback::kFailure)
+ tab_switch_result = TabSwitchResult::kPresentationFailure;
+
+ const auto tab_switch_duration =
+ feedback.timestamp - tab_switch_start_state_->tab_switch_start_time;
+
+ // Record trace events.
+ TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(
+ "latency", "TabSwitching::Latency",
+ TRACE_ID_LOCAL(g_num_trace_events_in_process),
+ tab_switch_start_state_->tab_switch_start_time);
+ TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP2(
+ "latency", "TabSwitching::Latency",
+ TRACE_ID_LOCAL(g_num_trace_events_in_process), feedback.timestamp,
+ "result", tab_switch_result, "latency",
+ tab_switch_duration.InMillisecondsF());
+ ++g_num_trace_events_in_process;
- if (!render_widget_visibility_request_timestamp.is_null()) {
- TRACE_EVENT_ASYNC_END1("latency", "TabSwitching::Latency",
- TRACE_ID_LOCAL(this), "latency",
- delta.InMillisecondsF());
- UMA_HISTOGRAM_TIMES(
- "MPArch.RWH_TabSwitchPaintDuration",
- feedback.timestamp - render_widget_visibility_request_timestamp);
+ // Record result histogram.
+ base::UmaHistogramEnumeration(
+ std::string("Browser.Tabs.TabSwitchResult.") +
+ GetHistogramSuffix(has_saved_frames_,
+ tab_switch_start_state_.value()),
+ tab_switch_result);
+
+ // Record latency histogram.
+ switch (tab_switch_result) {
+ case TabSwitchResult::kSuccess: {
+ base::UmaHistogramTimes(
+ std::string("Browser.Tabs.TotalSwitchDuration.") +
+ GetHistogramSuffix(has_saved_frames_,
+ tab_switch_start_state_.value()),
+ tab_switch_duration);
+ break;
+ }
+ case TabSwitchResult::kIncomplete: {
+ base::UmaHistogramTimes(
+ std::string("Browser.Tabs.TotalIncompleteSwitchDuration.") +
+ GetHistogramSuffix(has_saved_frames_,
+ tab_switch_start_state_.value()),
+ tab_switch_duration);
+ break;
+ }
+ case TabSwitchResult::kPresentationFailure: {
+ break;
+ }
}
+
+ // Record legacy latency histogram.
+ UMA_HISTOGRAM_TIMES(
+ "MPArch.RWH_TabSwitchPaintDuration",
+ feedback.timestamp - render_widget_visibility_request_timestamp_);
+
+ // Reset tab switch information.
+ has_saved_frames_ = false;
+ tab_switch_start_state_.reset();
+ render_widget_visibility_request_timestamp_ = base::TimeTicks();
}
} // namespace content
diff --git a/chromium/content/common/tab_switch_time_recorder.h b/chromium/content/common/tab_switch_time_recorder.h
index e5cf3a11802..f8dc11e2f27 100644
--- a/chromium/content/common/tab_switch_time_recorder.h
+++ b/chromium/content/common/tab_switch_time_recorder.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
@@ -16,34 +17,68 @@ struct PresentationFeedback;
namespace content {
+struct CONTENT_EXPORT RecordTabSwitchTimeRequest {
+ RecordTabSwitchTimeRequest() = default;
+ ~RecordTabSwitchTimeRequest() = default;
+
+ RecordTabSwitchTimeRequest(base::TimeTicks tab_switch_start_time,
+ bool destination_is_loaded,
+ bool destination_is_frozen);
+
+ // The time at which the tab switch has been initiated.
+ base::TimeTicks tab_switch_start_time = base::TimeTicks();
+ // Indicates if the destination tab is loaded when initiating the tab switch.
+ bool destination_is_loaded = false;
+ // Indicates if the destination tab is frozen when initiating the tab switch.
+ bool destination_is_frozen = false;
+};
+
// Generates UMA metric to track the duration of tab switching from when the
// active tab is changed until the frame presentation time. The metric will be
// separated into two whether the tab switch has saved frames or not.
class CONTENT_EXPORT TabSwitchTimeRecorder {
public:
+ // Matches the TabSwitchResult enum in enums.xml.
+ enum class TabSwitchResult {
+ // A frame was successfully presented after a tab switch.
+ kSuccess = 0,
+ // Tab was hidden before a frame was presented after a tab switch.
+ kIncomplete = 1,
+ // Compositor reported a failure after a tab switch.
+ kPresentationFailure = 2,
+ kMaxValue = kPresentationFailure,
+ };
+
TabSwitchTimeRecorder();
~TabSwitchTimeRecorder();
- // Begin recording time, ends when DidPresentFrame is called. Returns a
- // matching callback to end the time recording that will call DidPresentFrame.
- base::OnceCallback<void(const gfx::PresentationFeedback&)> BeginTimeRecording(
- const base::TimeTicks tab_switch_start_time,
+ // Invoked when the tab associated with this recorder is shown. Returns a
+ // callback to invoke the next time a frame is presented for this tab.
+ base::OnceCallback<void(const gfx::PresentationFeedback&)> TabWasShown(
bool has_saved_frames,
- const base::TimeTicks render_widget_visibility_request_timestamp =
- base::TimeTicks());
+ const RecordTabSwitchTimeRequest& start_state,
+ base::TimeTicks render_widget_visibility_request_timestamp);
+
+ // Indicates that the tab associated with this recorder was hidden. If no
+ // frame was presented since the last tab switch, failure is reported to UMA.
+ void TabWasHidden();
private:
- // End the time recording, and upload the result to histogram if it has a
- // correct matching BeginTimeRecording preceding this call.
- void DidPresentFrame(
- bool has_saved_frame,
- base::TimeTicks tab_switch_start_time,
- base::TimeTicks render_widget_visibility_request_timestamp,
+ // Records histograms and trace events for the current tab switch.
+ void RecordHistogramsAndTraceEvents(
+ bool is_incomplete,
const gfx::PresentationFeedback& feedback);
- base::WeakPtr<TabSwitchTimeRecorder> GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
+ // Whether there was a saved frame for the last tab switch.
+ bool has_saved_frames_;
+
+ // The information about the last tab switch request, or nullopt if there is
+ // no incomplete tab switch.
+ base::Optional<RecordTabSwitchTimeRequest> tab_switch_start_state_;
+
+ // The render widget visibility request timestamp for the last tab switch, or
+ // null if there is no incomplete tab switch.
+ base::TimeTicks render_widget_visibility_request_timestamp_;
base::WeakPtrFactory<TabSwitchTimeRecorder> weak_ptr_factory_;
diff --git a/chromium/content/common/tab_switch_time_recorder_unittest.cc b/chromium/content/common/tab_switch_time_recorder_unittest.cc
index 8f03ebacf85..00020226c80 100644
--- a/chromium/content/common/tab_switch_time_recorder_unittest.cc
+++ b/chromium/content/common/tab_switch_time_recorder_unittest.cc
@@ -5,100 +5,336 @@
#include <utility>
#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_task_environment.h"
#include "content/common/tab_switch_time_recorder.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/presentation_feedback.h"
namespace content {
-class TabSwitchTimeRecorderTest : public testing::Test {
- public:
- ~TabSwitchTimeRecorderTest() override {}
+constexpr char kDurationWithSavedFramesHistogram[] =
+ "Browser.Tabs.TotalSwitchDuration.WithSavedFrames";
+constexpr char kDurationNoSavedFramesHistogram[] =
+ "Browser.Tabs.TotalSwitchDuration.NoSavedFrames_Loaded_NotFrozen";
+constexpr char kDurationNoSavedFramesFrozenHistogram[] =
+ "Browser.Tabs.TotalSwitchDuration.NoSavedFrames_Loaded_Frozen";
+constexpr char kDurationNoSavedFramesUnloadedHistogram[] =
+ "Browser.Tabs.TotalSwitchDuration.NoSavedFrames_NotLoaded";
+constexpr char kIncompleteDurationWithSavedFramesHistogram[] =
+ "Browser.Tabs.TotalIncompleteSwitchDuration.WithSavedFrames";
+constexpr char kIncompleteDurationNoSavedFramesHistogram[] =
+ "Browser.Tabs.TotalIncompleteSwitchDuration.NoSavedFrames_Loaded_NotFrozen";
+constexpr char kResultWithSavedFramesHistogram[] =
+ "Browser.Tabs.TabSwitchResult.WithSavedFrames";
+constexpr char kResultNoSavedFramesHistogram[] =
+ "Browser.Tabs.TabSwitchResult.NoSavedFrames_Loaded_NotFrozen";
+constexpr char kResultNoSavedFramesFrozenHistogram[] =
+ "Browser.Tabs.TabSwitchResult.NoSavedFrames_Loaded_Frozen";
+constexpr char kResultNoSavedFramesUnloadedHistogram[] =
+ "Browser.Tabs.TabSwitchResult.NoSavedFrames_NotLoaded";
+constexpr base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(42);
+constexpr base::TimeDelta kOtherDuration =
+ base::TimeDelta::FromMilliseconds(4242);
+class TabSwitchTimeRecorderTest : public testing::Test {
+ protected:
void SetUp() override {
- EXPECT_EQ(
- histogram_tester
- .GetAllSamples("Browser.Tabs.TotalSwitchDuration.WithSavedFrames")
- .size(),
- 0ULL);
- EXPECT_EQ(
- histogram_tester
- .GetAllSamples("Browser.Tabs.TotalSwitchDuration.NoSavedFrames")
- .size(),
- 0ULL);
+ // Start with non-zero time.
+ scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(123));
+
+ ExpectTotalSamples(kDurationWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kDurationNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kDurationNoSavedFramesFrozenHistogram, 0);
+ ExpectTotalSamples(kDurationNoSavedFramesUnloadedHistogram, 0);
}
- protected:
- size_t GetHistogramSampleSize(bool has_saved_frames) {
- if (has_saved_frames) {
- return histogram_tester
- .GetAllSamples("Browser.Tabs.TotalSwitchDuration.WithSavedFrames")
- .size();
- } else {
- return histogram_tester
- .GetAllSamples("Browser.Tabs.TotalSwitchDuration.NoSavedFrames")
- .size();
- }
+ void ExpectTotalSamples(const char* histogram_name, int expected_count) {
+ EXPECT_EQ(static_cast<int>(
+ histogram_tester_.GetAllSamples(histogram_name).size()),
+ expected_count);
+ }
+
+ void ExpectTimeBucketCount(const char* histogram_name,
+ base::TimeDelta value,
+ int count) {
+ histogram_tester_.ExpectTimeBucketCount(histogram_name, value, count);
}
+ void ExpectResultBucketCount(const char* histogram_name,
+ TabSwitchTimeRecorder::TabSwitchResult value,
+ int count) {
+ histogram_tester_.ExpectBucketCount(histogram_name, value, count);
+ }
+
+ base::test::ScopedTaskEnvironment scoped_task_environment_{
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+ base::test::ScopedTaskEnvironment::NowSource::MAIN_THREAD_MOCK_TIME};
TabSwitchTimeRecorder tab_switch_time_recorder_;
- base::HistogramTester histogram_tester;
+ base::HistogramTester histogram_tester_;
};
// Time is properly recorded to histogram when we have saved frames and if we
-// have a proper matching BeginTimeRecording and callback execution.
+// have a proper matching TabWasShown and callback execution.
TEST_F(TabSwitchTimeRecorderTest, TimeIsRecordedWithSavedFrames) {
const auto start = base::TimeTicks::Now();
- auto callback = tab_switch_time_recorder_.BeginTimeRecording(
- start, true /* has_saved_frames */);
- const auto end = base::TimeTicks::Now();
+ auto callback = tab_switch_time_recorder_.TabWasShown(
+ true /* has_saved_frames */,
+ {start, /* destination_is_loaded */ true,
+ /* destination_is_frozen */ false},
+ start);
+ const auto end = start + kDuration;
auto presentation_feedback = gfx::PresentationFeedback(
end, end - start, gfx::PresentationFeedback::Flags::kHWCompletion);
std::move(callback).Run(presentation_feedback);
- EXPECT_EQ(GetHistogramSampleSize(true /* has_saved_frames */), 1ULL);
- EXPECT_EQ(GetHistogramSampleSize(false /* has_saved_frames */), 0ULL);
+
+ ExpectTotalSamples(kDurationWithSavedFramesHistogram, 1);
+ ExpectTimeBucketCount(kDurationWithSavedFramesHistogram, kDuration, 1);
+ ExpectTotalSamples(kResultWithSavedFramesHistogram, 1);
+ ExpectResultBucketCount(kResultWithSavedFramesHistogram,
+ TabSwitchTimeRecorder::TabSwitchResult::kSuccess, 1);
+ ExpectTotalSamples(kIncompleteDurationWithSavedFramesHistogram, 0);
+
+ ExpectTotalSamples(kResultNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kIncompleteDurationNoSavedFramesHistogram, 0);
}
// Time is properly recorded to histogram when we have no saved frame and if we
-// have a proper matching BeginTimeRecording and callback execution.
+// have a proper matching TabWasShown and callback execution.
TEST_F(TabSwitchTimeRecorderTest, TimeIsRecordedNoSavedFrame) {
const auto start = base::TimeTicks::Now();
- auto callback = tab_switch_time_recorder_.BeginTimeRecording(
- start, false /* has_saved_frames */);
- const auto end = base::TimeTicks::Now();
+ auto callback = tab_switch_time_recorder_.TabWasShown(
+ false /* has_saved_frames */,
+ {start, /* destination_is_loaded */ true,
+ /* destination_is_frozen */ false},
+ start);
+ const auto end = start + kDuration;
auto presentation_feedback = gfx::PresentationFeedback(
end, end - start, gfx::PresentationFeedback::Flags::kHWCompletion);
std::move(callback).Run(presentation_feedback);
- EXPECT_EQ(GetHistogramSampleSize(true /* has_saved_frames */), 0ULL);
- EXPECT_EQ(GetHistogramSampleSize(false /* has_saved_frames */), 1ULL);
+
+ ExpectTotalSamples(kDurationWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kIncompleteDurationWithSavedFramesHistogram, 0);
+
+ ExpectTotalSamples(kDurationNoSavedFramesHistogram, 1);
+ ExpectTimeBucketCount(kDurationNoSavedFramesHistogram, kDuration, 1);
+ ExpectTotalSamples(kDurationNoSavedFramesFrozenHistogram, 0);
+ ExpectTotalSamples(kDurationNoSavedFramesUnloadedHistogram, 0);
+ ExpectTotalSamples(kResultNoSavedFramesHistogram, 1);
+ ExpectResultBucketCount(kResultNoSavedFramesHistogram,
+ TabSwitchTimeRecorder::TabSwitchResult::kSuccess, 1);
+ ExpectTotalSamples(kResultNoSavedFramesFrozenHistogram, 0);
+ ExpectTotalSamples(kResultNoSavedFramesUnloadedHistogram, 0);
+ ExpectTotalSamples(kIncompleteDurationNoSavedFramesHistogram, 0);
+}
+
+// Same as TimeIsRecordedNoSavedFrame but with the destination frame frozen.
+TEST_F(TabSwitchTimeRecorderTest, TimeIsRecordedNoSavedFrameAndFrozen) {
+ const auto start = base::TimeTicks::Now();
+ auto callback = tab_switch_time_recorder_.TabWasShown(
+ false /* has_saved_frames */,
+ {start, /* destination_is_loaded */ true,
+ /* destination_is_frozen */ true},
+ start);
+ const auto end = start + kDuration;
+ auto presentation_feedback = gfx::PresentationFeedback(
+ end, end - start, gfx::PresentationFeedback::Flags::kHWCompletion);
+ std::move(callback).Run(presentation_feedback);
+
+ ExpectTotalSamples(kDurationWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kIncompleteDurationWithSavedFramesHistogram, 0);
+
+ ExpectTotalSamples(kDurationNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kDurationNoSavedFramesFrozenHistogram, 1);
+ ExpectTimeBucketCount(kDurationNoSavedFramesFrozenHistogram, kDuration, 1);
+ ExpectTotalSamples(kDurationNoSavedFramesUnloadedHistogram, 0);
+ ExpectTotalSamples(kResultNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultNoSavedFramesFrozenHistogram, 1);
+ ExpectResultBucketCount(kResultNoSavedFramesFrozenHistogram,
+ TabSwitchTimeRecorder::TabSwitchResult::kSuccess, 1);
+ ExpectTotalSamples(kResultNoSavedFramesUnloadedHistogram, 0);
+ ExpectTotalSamples(kIncompleteDurationNoSavedFramesHistogram, 0);
+}
+
+// Same as TimeIsRecordedNoSavedFrame but with the destination frame unloaded.
+TEST_F(TabSwitchTimeRecorderTest, TimeIsRecordedNoSavedFrameUnloaded) {
+ const auto start = base::TimeTicks::Now();
+ auto callback = tab_switch_time_recorder_.TabWasShown(
+ false /* has_saved_frames */,
+ {start, /* destination_is_loaded */ false,
+ /* destination_is_frozen */ false},
+ start);
+ const auto end = start + kDuration;
+ auto presentation_feedback = gfx::PresentationFeedback(
+ end, end - start, gfx::PresentationFeedback::Flags::kHWCompletion);
+ std::move(callback).Run(presentation_feedback);
+
+ ExpectTotalSamples(kDurationWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kIncompleteDurationWithSavedFramesHistogram, 0);
+
+ ExpectTotalSamples(kDurationNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kDurationNoSavedFramesFrozenHistogram, 0);
+ ExpectTotalSamples(kDurationNoSavedFramesUnloadedHistogram, 1);
+ ExpectTimeBucketCount(kDurationNoSavedFramesUnloadedHistogram, kDuration, 1);
+ ExpectTotalSamples(kResultNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultNoSavedFramesFrozenHistogram, 0);
+ ExpectTotalSamples(kResultNoSavedFramesUnloadedHistogram, 1);
+ ExpectResultBucketCount(kResultNoSavedFramesUnloadedHistogram,
+ TabSwitchTimeRecorder::TabSwitchResult::kSuccess, 1);
+ ExpectTotalSamples(kIncompleteDurationNoSavedFramesHistogram, 0);
}
-// Two consecutive calls to BeginTimeRecording will invalidate the first
-// returned callback.
-TEST_F(TabSwitchTimeRecorderTest, InvalidateCallback) {
+// A failure should be reported if gfx::PresentationFeedback contains the
+// kFailure flag.
+TEST_F(TabSwitchTimeRecorderTest, PresentationFailureWithSavedFrames) {
+ const auto start = base::TimeTicks::Now();
+ auto callback = tab_switch_time_recorder_.TabWasShown(
+ true /* has_saved_frames */,
+ {start, /* destination_is_loaded */ true,
+ /* destination_is_frozen */ false},
+ start);
+ std::move(callback).Run(gfx::PresentationFeedback::Failure());
+
+ ExpectTotalSamples(kDurationWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultWithSavedFramesHistogram, 1);
+ ExpectResultBucketCount(
+ kResultWithSavedFramesHistogram,
+ TabSwitchTimeRecorder::TabSwitchResult::kPresentationFailure, 1);
+ ExpectTotalSamples(kIncompleteDurationWithSavedFramesHistogram, 0);
+
+ ExpectTotalSamples(kDurationNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kIncompleteDurationNoSavedFramesHistogram, 0);
+}
+
+// A failure should be reported if gfx::PresentationFeedback contains the
+// kFailure flag.
+TEST_F(TabSwitchTimeRecorderTest, PresentationFailureNoSavedFrames) {
+ const auto start = base::TimeTicks::Now();
+ auto callback = tab_switch_time_recorder_.TabWasShown(
+ false /* has_saved_frames */,
+ {start, /* destination_is_loaded */ true,
+ /* destination_is_frozen */ false},
+ start);
+ std::move(callback).Run(gfx::PresentationFeedback::Failure());
+
+ ExpectTotalSamples(kDurationWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kIncompleteDurationWithSavedFramesHistogram, 0);
+
+ ExpectTotalSamples(kDurationNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultNoSavedFramesHistogram, 1);
+ ExpectResultBucketCount(
+ kResultNoSavedFramesHistogram,
+ TabSwitchTimeRecorder::TabSwitchResult::kPresentationFailure, 1);
+ ExpectTotalSamples(kIncompleteDurationNoSavedFramesHistogram, 0);
+}
+
+// An incomplete tab switch is reported when no frame is shown before a tab is
+// hidden.
+TEST_F(TabSwitchTimeRecorderTest, HideBeforePresentFrameWithSavedFrames) {
+ const auto start1 = base::TimeTicks::Now();
+ auto callback1 = tab_switch_time_recorder_.TabWasShown(
+ true /* has_saved_frames */,
+ {start1, /* destination_is_loaded */ true,
+ /* destination_is_frozen */ false},
+ start1);
+
+ scoped_task_environment_.FastForwardBy(kDuration);
+ tab_switch_time_recorder_.TabWasHidden();
+
+ ExpectTotalSamples(kDurationWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultWithSavedFramesHistogram, 1);
+ ExpectResultBucketCount(kResultWithSavedFramesHistogram,
+ TabSwitchTimeRecorder::TabSwitchResult::kIncomplete,
+ 1);
+ ExpectTotalSamples(kIncompleteDurationWithSavedFramesHistogram, 1);
+ ExpectTimeBucketCount(kIncompleteDurationWithSavedFramesHistogram, kDuration,
+ 1);
+
+ ExpectTotalSamples(kDurationNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kIncompleteDurationNoSavedFramesHistogram, 0);
+
+ const auto start2 = base::TimeTicks::Now();
+ auto callback2 = tab_switch_time_recorder_.TabWasShown(
+ true /* has_saved_frames */,
+ {start2, /* destination_is_loaded */ true,
+ /* destination_is_frozen */ false},
+ start2);
+ const auto end2 = start2 + kOtherDuration;
+ auto presentation_feedback = gfx::PresentationFeedback(
+ end2, end2 - start2, gfx::PresentationFeedback::Flags::kHWCompletion);
+ std::move(callback2).Run(presentation_feedback);
+
+ ExpectTotalSamples(kDurationWithSavedFramesHistogram, 1);
+ ExpectTimeBucketCount(kDurationWithSavedFramesHistogram, kOtherDuration, 1);
+ ExpectTotalSamples(kResultWithSavedFramesHistogram, 2);
+ ExpectResultBucketCount(kResultWithSavedFramesHistogram,
+ TabSwitchTimeRecorder::TabSwitchResult::kIncomplete,
+ 1);
+ ExpectResultBucketCount(kResultWithSavedFramesHistogram,
+ TabSwitchTimeRecorder::TabSwitchResult::kSuccess, 1);
+ ExpectTotalSamples(kIncompleteDurationWithSavedFramesHistogram, 1);
+
+ ExpectTotalSamples(kDurationNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kIncompleteDurationNoSavedFramesHistogram, 0);
+}
+
+// An incomplete tab switch is reported when no frame is shown before a tab is
+// hidden.
+TEST_F(TabSwitchTimeRecorderTest, HideBeforePresentFrameNoSavedFrames) {
const auto start1 = base::TimeTicks::Now();
- auto callback1 = tab_switch_time_recorder_.BeginTimeRecording(
- start1, false /* has_saved_frames */);
+ auto callback1 = tab_switch_time_recorder_.TabWasShown(
+ false /* has_saved_frames */,
+ {start1, /* destination_is_loaded */ true,
+ /* destination_is_frozen */ false},
+ start1);
+
+ scoped_task_environment_.FastForwardBy(kDuration);
+ tab_switch_time_recorder_.TabWasHidden();
+
+ ExpectTotalSamples(kDurationWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kIncompleteDurationWithSavedFramesHistogram, 0);
+
+ ExpectTotalSamples(kDurationNoSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultNoSavedFramesHistogram, 1);
+ ExpectResultBucketCount(kResultNoSavedFramesHistogram,
+ TabSwitchTimeRecorder::TabSwitchResult::kIncomplete,
+ 1);
+ ExpectTotalSamples(kIncompleteDurationNoSavedFramesHistogram, 1);
+ ExpectTimeBucketCount(kIncompleteDurationNoSavedFramesHistogram, kDuration,
+ 1);
const auto start2 = base::TimeTicks::Now();
- auto callback2 = tab_switch_time_recorder_.BeginTimeRecording(
- start2, false /* has_saved_frames */);
-
- // callback1 should be invalid. Running it should not upload anything to
- // histogram.
- const auto end = base::TimeTicks::Now();
- auto presentation_feedback1 = gfx::PresentationFeedback(
- end, end - start1, gfx::PresentationFeedback::Flags::kHWCompletion);
- std::move(callback1).Run(presentation_feedback1);
- EXPECT_EQ(GetHistogramSampleSize(true /* has_saved_frames */), 0ULL);
- EXPECT_EQ(GetHistogramSampleSize(false /* has_saved_frames */), 0ULL);
-
- // callback2 should still be valid.
- auto presentation_feedback2 = gfx::PresentationFeedback(
- end, end - start2, gfx::PresentationFeedback::Flags::kHWCompletion);
- std::move(callback2).Run(presentation_feedback2);
- EXPECT_EQ(GetHistogramSampleSize(true /* has_saved_frames */), 0ULL);
- EXPECT_EQ(GetHistogramSampleSize(false /* has_saved_frames */), 1ULL);
+ auto callback2 = tab_switch_time_recorder_.TabWasShown(
+ false /* has_saved_frames */,
+ {start2, /* destination_is_loaded */ true,
+ /* destination_is_frozen */ false},
+ start2);
+ const auto end2 = start2 + kOtherDuration;
+
+ auto presentation_feedback = gfx::PresentationFeedback(
+ end2, end2 - start2, gfx::PresentationFeedback::Flags::kHWCompletion);
+ std::move(callback2).Run(presentation_feedback);
+
+ ExpectTotalSamples(kDurationWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kResultWithSavedFramesHistogram, 0);
+ ExpectTotalSamples(kIncompleteDurationWithSavedFramesHistogram, 0);
+
+ ExpectTotalSamples(kDurationNoSavedFramesHistogram, 1);
+ ExpectTimeBucketCount(kDurationNoSavedFramesHistogram, kOtherDuration, 1);
+ ExpectTotalSamples(kResultNoSavedFramesHistogram, 2);
+ ExpectResultBucketCount(kResultNoSavedFramesHistogram,
+ TabSwitchTimeRecorder::TabSwitchResult::kIncomplete,
+ 1);
+ ExpectResultBucketCount(kResultNoSavedFramesHistogram,
+ TabSwitchTimeRecorder::TabSwitchResult::kSuccess, 1);
+ ExpectTotalSamples(kIncompleteDurationNoSavedFramesHistogram, 1);
}
} // namespace content
diff --git a/chromium/content/common/text_input_state.cc b/chromium/content/common/text_input_state.cc
index f6044bfd26d..ac326840fd1 100644
--- a/chromium/content/common/text_input_state.cc
+++ b/chromium/content/common/text_input_state.cc
@@ -9,6 +9,7 @@ namespace content {
TextInputState::TextInputState()
: type(ui::TEXT_INPUT_TYPE_NONE),
mode(ui::TEXT_INPUT_MODE_DEFAULT),
+ action(ui::TextInputAction::kDefault),
flags(0),
selection_start(0),
selection_end(0),
diff --git a/chromium/content/common/text_input_state.h b/chromium/content/common/text_input_state.h
index 454529e2748..f2a1523c0d8 100644
--- a/chromium/content/common/text_input_state.h
+++ b/chromium/content/common/text_input_state.h
@@ -7,6 +7,7 @@
#include "base/strings/string16.h"
#include "content/common/content_export.h"
+#include "ui/base/ime/text_input_action.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
@@ -25,6 +26,9 @@ struct CONTENT_EXPORT TextInputState {
// The mode of input field.
ui::TextInputMode mode;
+ // The action of the input field.
+ ui::TextInputAction action;
+
// The flags of input field (autocorrect, autocomplete, etc.)
int flags;
diff --git a/chromium/content/common/throttling_url_loader.cc b/chromium/content/common/throttling_url_loader.cc
index aca8fa04648..a2c6e144514 100644
--- a/chromium/content/common/throttling_url_loader.cc
+++ b/chromium/content/common/throttling_url_loader.cc
@@ -10,6 +10,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
+#include "net/url_request/redirect_util.h"
#include "services/network/public/cpp/features.h"
namespace content {
@@ -275,7 +276,13 @@ void ThrottlingURLLoader::SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) {
if (!url_loader_) {
if (!loader_completed_) {
- DCHECK_EQ(DEFERRED_START, deferred_stage_);
+ // Only check |deferred_stage_| if this resource has not been redirected
+ // by a throttle.
+ if (throttle_will_start_redirect_url_.is_empty() &&
+ throttle_will_redirect_redirect_url_.is_empty()) {
+ DCHECK_EQ(DEFERRED_START, deferred_stage_);
+ }
+
priority_info_ =
std::make_unique<PriorityInfo>(priority, intra_priority_value);
}
@@ -325,17 +332,14 @@ void ThrottlingURLLoader::Start(
DCHECK(throttle_will_start_redirect_url_.is_empty())
<< "ThrottlingURLLoader doesn't support multiple throttles "
"changing the URL.";
- // Only do this sanity check if the schemes are both http[s], as this
- // generated-redirect functionality is also used by
- // registerProtocolHandler to map non-web to web schemes and that is
- // safe.
if (original_url.SchemeIsHTTPOrHTTPS() &&
- url_request->url.SchemeIsHTTPOrHTTPS()) {
- CHECK_EQ(original_url.GetOrigin(), url_request->url.GetOrigin())
- << "ThrottlingURLLoader doesn't support a throttle making a "
- << "cross-origin redirect.";
+ !url_request->url.SchemeIsHTTPOrHTTPS() &&
+ !throttle->makes_unsafe_redirect()) {
+ NOTREACHED() << "A URLLoaderThrottle can't redirect from http(s) to "
+ << "a non http(s) scheme.";
+ } else {
+ throttle_will_start_redirect_url_ = url_request->url;
}
- throttle_will_start_redirect_url_ = url_request->url;
// Restore the original URL so that all throttles see the same original
// URL.
url_request->url = original_url;
@@ -343,11 +347,6 @@ void ThrottlingURLLoader::Start(
if (!HandleThrottleResult(throttle, throttle_deferred, &deferred))
return;
}
-
- // If a throttle had changed the URL, set it in the ResourceRequest struct
- // so that it is the URL that's requested.
- if (!throttle_will_start_redirect_url_.is_empty())
- url_request->url = throttle_will_start_redirect_url_;
}
start_info_ =
@@ -362,13 +361,35 @@ void ThrottlingURLLoader::Start(
void ThrottlingURLLoader::StartNow() {
DCHECK(start_info_);
if (!throttle_will_start_redirect_url_.is_empty()) {
- net::RedirectInfo redirect_info;
- redirect_info.status_code = net::HTTP_TEMPORARY_REDIRECT;
- redirect_info.new_method = start_info_->url_request.method;
- redirect_info.new_url = throttle_will_start_redirect_url_;
- redirect_info.new_site_for_cookies = throttle_will_start_redirect_url_;
- redirect_info.new_top_frame_origin =
- url::Origin::Create(throttle_will_start_redirect_url_);
+ auto first_party_url_policy =
+ start_info_->url_request.update_first_party_url_on_redirect
+ ? net::URLRequest::FirstPartyURLPolicy::
+ UPDATE_FIRST_PARTY_URL_ON_REDIRECT
+ : net::URLRequest::FirstPartyURLPolicy::
+ NEVER_CHANGE_FIRST_PARTY_URL;
+
+ net::RedirectInfo redirect_info = net::RedirectInfo::ComputeRedirectInfo(
+ start_info_->url_request.method, start_info_->url_request.url,
+ start_info_->url_request.site_for_cookies,
+ start_info_->url_request.top_frame_origin, first_party_url_policy,
+ start_info_->url_request.referrer_policy,
+ start_info_->url_request.referrer.spec(),
+ // Use status code 307 to preserve the method, so POST requests work.
+ net::HTTP_TEMPORARY_REDIRECT, throttle_will_start_redirect_url_,
+ base::nullopt, false, false, false);
+
+ bool should_clear_upload = false;
+ net::RedirectUtil::UpdateHttpRequest(
+ start_info_->url_request.url, start_info_->url_request.method,
+ redirect_info, base::nullopt, base::nullopt,
+ &start_info_->url_request.headers, &should_clear_upload);
+
+ if (should_clear_upload)
+ start_info_->url_request.request_body = nullptr;
+
+ // Set the new URL in the ResourceRequest struct so that it is the URL
+ // that's requested.
+ start_info_->url_request.url = throttle_will_start_redirect_url_;
network::ResourceResponseHead response_head;
std::string header_string = base::StringPrintf(
@@ -376,9 +397,8 @@ void ThrottlingURLLoader::StartNow() {
"Location: %s\n",
net::HTTP_TEMPORARY_REDIRECT,
throttle_will_start_redirect_url_.spec().c_str());
- response_head.headers =
- new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
- header_string.c_str(), header_string.length()));
+ response_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(header_string));
response_head.encoded_data_length = header_string.size();
OnReceiveRedirect(redirect_info, response_head);
return;
@@ -530,17 +550,6 @@ void ThrottlingURLLoader::OnReceiveRedirect(
DCHECK(throttle_will_redirect_redirect_url_.is_empty())
<< "ThrottlingURLLoader doesn't support multiple throttles "
"changing the URL.";
- // Only do this sanity check if the schemes are both http[s], as this
- // generated-redirect functionality is also used by
- // registerProtocolHandler to map non-web to web schemes and that is
- // safe.
- if (redirect_info_copy.new_url.SchemeIsHTTPOrHTTPS() &&
- redirect_info.new_url.SchemeIsHTTPOrHTTPS()) {
- CHECK_EQ(redirect_info_copy.new_url.GetOrigin(),
- redirect_info.new_url.GetOrigin())
- << "ThrottlingURLLoader doesn't support a throttle making a "
- << "cross-origin redirect.";
- }
throttle_will_redirect_redirect_url_ = redirect_info_copy.new_url;
} else {
CHECK_EQ(redirect_info_copy.new_url, redirect_info.new_url)
@@ -596,12 +605,11 @@ void ThrottlingURLLoader::OnUploadProgress(
std::move(ack_callback));
}
-void ThrottlingURLLoader::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
+void ThrottlingURLLoader::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
DCHECK(!loader_completed_);
- forwarding_client_->OnReceiveCachedMetadata(data);
+ forwarding_client_->OnReceiveCachedMetadata(std::move(data));
}
void ThrottlingURLLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
diff --git a/chromium/content/common/throttling_url_loader.h b/chromium/content/common/throttling_url_loader.h
index da72525594d..3e4e3304afb 100644
--- a/chromium/content/common/throttling_url_loader.h
+++ b/chromium/content/common/throttling_url_loader.h
@@ -124,7 +124,7 @@ class CONTENT_EXPORT ThrottlingURLLoader
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
diff --git a/chromium/content/common/throttling_url_loader_unittest.cc b/chromium/content/common/throttling_url_loader_unittest.cc
index 3a589e4c683..1d4834cf28e 100644
--- a/chromium/content/common/throttling_url_loader_unittest.cc
+++ b/chromium/content/common/throttling_url_loader_unittest.cc
@@ -198,7 +198,7 @@ class TestURLLoaderClient : public network::mojom::URLLoaderClient {
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override {}
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override {}
void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override {}
diff --git a/chromium/content/common/typemaps.gni b/chromium/content/common/typemaps.gni
index 5476d2d8ab4..920be0777dc 100644
--- a/chromium/content/common/typemaps.gni
+++ b/chromium/content/common/typemaps.gni
@@ -9,7 +9,6 @@ typemaps = [
"//content/common/native_types.typemap",
"//content/common/native_types_mac.typemap",
"//content/common/navigation_params.typemap",
- "//content/common/push_messaging.typemap",
"//content/common/render_frame_metadata.typemap",
"//content/common/web_preferences.typemap",
]
diff --git a/chromium/content/common/user_agent.cc b/chromium/content/common/user_agent.cc
index abff162284e..f37818ed824 100644
--- a/chromium/content/common/user_agent.cc
+++ b/chromium/content/common/user_agent.cc
@@ -134,6 +134,14 @@ std::string BuildOSCpuInfo(bool include_android_build_number) {
return os_cpu;
}
+base::StringPiece GetFrozenUserAgent(bool mobile) {
+#if defined(OS_ANDROID)
+ return mobile ? frozen_user_agent_strings::kAndroidMobile
+ : frozen_user_agent_strings::kAndroid;
+#endif
+ return frozen_user_agent_strings::kDesktop;
+}
+
std::string BuildUserAgentFromProduct(const std::string& product) {
std::string os_info;
base::StringAppendF(&os_info, "%s%s", GetUserAgentPlatform().c_str(),
diff --git a/chromium/content/common/view_messages.h b/chromium/content/common/view_messages.h
index 7a83198a3de..7ca006c87b7 100644
--- a/chromium/content/common/view_messages.h
+++ b/chromium/content/common/view_messages.h
@@ -25,7 +25,6 @@
#include "components/viz/common/resources/shared_bitmap.h"
#include "content/common/content_export.h"
#include "content/common/content_param_traits.h"
-#include "content/common/date_time_suggestion.h"
#include "content/common/frame_replication_state.h"
#include "content/common/navigation_gesture.h"
#include "content/public/common/common_param_traits.h"
@@ -45,7 +44,6 @@
#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
#include "third_party/blink/public/web/web_plugin_action.h"
#include "third_party/blink/public/web/web_text_direction.h"
-#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/point.h"
@@ -104,33 +102,8 @@ IPC_STRUCT_TRAITS_BEGIN(content::MenuItem)
IPC_STRUCT_TRAITS_MEMBER(submenu)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(content::DateTimeSuggestion)
- IPC_STRUCT_TRAITS_MEMBER(value)
- IPC_STRUCT_TRAITS_MEMBER(localized_value)
- IPC_STRUCT_TRAITS_MEMBER(label)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_BEGIN(ViewHostMsg_DateTimeDialogValue_Params)
- IPC_STRUCT_MEMBER(ui::TextInputType, dialog_type)
- IPC_STRUCT_MEMBER(double, dialog_value)
- IPC_STRUCT_MEMBER(double, minimum)
- IPC_STRUCT_MEMBER(double, maximum)
- IPC_STRUCT_MEMBER(double, step)
- IPC_STRUCT_MEMBER(std::vector<content::DateTimeSuggestion>, suggestions)
-IPC_STRUCT_END()
-
// Messages sent from the browser to the renderer.
-#if defined(OS_ANDROID)
-// Tells the renderer to cancel an opened date/time dialog.
-IPC_MESSAGE_ROUTED0(ViewMsg_CancelDateTimeDialog)
-
-// Replaces a date time input field.
-IPC_MESSAGE_ROUTED1(ViewMsg_ReplaceDateTime,
- double /* dialog_value */)
-
-#endif
-
// Make the RenderWidget background transparent or opaque.
IPC_MESSAGE_ROUTED1(ViewMsg_SetBackgroundOpaque, bool /* opaque */)
@@ -296,10 +269,6 @@ IPC_MESSAGE_ROUTED3(ViewHostMsg_RequestPpapiBrokerPermission,
IPC_MESSAGE_ROUTED1(ViewHostMsg_TakeFocus,
bool /* reverse */)
-// Required for opening a date/time dialog
-IPC_MESSAGE_ROUTED1(ViewHostMsg_OpenDateTimeDialog,
- ViewHostMsg_DateTimeDialogValue_Params /* value */)
-
// Sent when the renderer changes its page scale factor.
IPC_MESSAGE_ROUTED1(ViewHostMsg_PageScaleFactorChanged,
float /* page_scale_factor */)
diff --git a/chromium/content/public/common/web_contents_ns_view_bridge.mojom b/chromium/content/common/web_contents_ns_view_bridge.mojom
index d4190a8a08d..d4190a8a08d 100644
--- a/chromium/content/public/common/web_contents_ns_view_bridge.mojom
+++ b/chromium/content/common/web_contents_ns_view_bridge.mojom
diff --git a/chromium/content/common/widget_messages.h b/chromium/content/common/widget_messages.h
index fcda7cedcad..cc6559df63a 100644
--- a/chromium/content/common/widget_messages.h
+++ b/chromium/content/common/widget_messages.h
@@ -7,10 +7,12 @@
// IPC messages for controlling painting and input events.
+#include "base/optional.h"
#include "base/time/time.h"
#include "cc/input/touch_action.h"
#include "content/common/content_param_traits.h"
#include "content/common/cursors/webcursor.h"
+#include "content/common/tab_switch_time_recorder.h"
#include "content/common/text_input_state.h"
#include "content/common/visual_properties.h"
#include "content/public/common/common_param_traits.h"
@@ -22,6 +24,8 @@
#include "third_party/blink/public/platform/web_intrinsic_sizing_info.h"
#include "third_party/blink/public/web/web_device_emulation_params.h"
#include "third_party/blink/public/web/web_text_direction.h"
+#include "ui/base/ime/text_input_action.h"
+#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
@@ -109,11 +113,13 @@ IPC_STRUCT_BEGIN(WidgetHostMsg_SelectionBounds_Params)
IPC_STRUCT_END()
// Traits for TextInputState.
+IPC_ENUM_TRAITS_MAX_VALUE(ui::TextInputAction, ui::TextInputAction::kMaxValue)
IPC_ENUM_TRAITS_MAX_VALUE(ui::TextInputMode, ui::TEXT_INPUT_MODE_MAX)
IPC_STRUCT_TRAITS_BEGIN(content::TextInputState)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(mode)
+ IPC_STRUCT_TRAITS_MEMBER(action)
IPC_STRUCT_TRAITS_MEMBER(flags)
IPC_STRUCT_TRAITS_MEMBER(value)
IPC_STRUCT_TRAITS_MEMBER(selection_start)
@@ -157,10 +163,13 @@ IPC_MESSAGE_ROUTED0(WidgetMsg_DisableDeviceEmulation)
IPC_MESSAGE_ROUTED0(WidgetMsg_WasHidden)
// Tells the render view that it is no longer hidden (see WasHidden).
-IPC_MESSAGE_ROUTED3(WidgetMsg_WasShown,
- base::TimeTicks /* show_request_timestamp */,
- bool /* was_evicted */,
- base::TimeTicks /* tab_switch_start_time */)
+IPC_MESSAGE_ROUTED3(
+ WidgetMsg_WasShown,
+ base::TimeTicks /* show_request_timestamp */,
+ bool /* was_evicted */,
+ base::Optional<
+ content::
+ RecordTabSwitchTimeRequest> /* record_tab_switch_time_request */)
// Activate/deactivate the RenderWidget (i.e., set its controls' tint
// accordingly, etc.).
diff --git a/chromium/content/content_resources.grd b/chromium/content/content_resources.grd
index 1a7f095a642..979eb9af407 100644
--- a/chromium/content/content_resources.grd
+++ b/chromium/content/content_resources.grd
@@ -5,6 +5,10 @@
<output filename="grit/content_resources.h" type="rc_header">
<emit emit_type='prepend'></emit>
</output>
+ <output filename="grit/content_resources_map.h"
+ type="resource_map_header" />
+ <output filename="grit/content_resources_map.cc"
+ type="resource_map_source" />
<output filename="content_resources.pak" type="data_package" />
</outputs>
<translations />
@@ -26,9 +30,11 @@
<include name="IDR_INDEXED_DB_INTERNALS_CSS" file="browser/resources/indexed_db/indexeddb_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
<include name="IDR_MEDIA_INTERNALS_HTML" file="browser/resources/media/media_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_MEDIA_INTERNALS_JS" file="browser/resources/media/media_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
- <include name="IDR_NETWORK_ERROR_LISTING_HTML" file="browser/resources/net/network_errors_listing.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
+ <include name="IDR_NETWORK_ERROR_LISTING_HTML" file="browser/resources/net/network_errors_listing.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_NETWORK_ERROR_LISTING_JS" file="browser/resources/net/network_errors_listing.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_NETWORK_ERROR_LISTING_CSS" file="browser/resources/net/network_errors_listing.css" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_ORIGIN_MOJO_HTML" file="${root_gen_dir}/url/mojom/origin.mojom.html" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_ORIGIN_MOJO_JS" file="${root_gen_dir}/url/mojom/origin.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_PROCESS_INTERNALS_HTML" file="browser/resources/process/process_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_PROCESS_INTERNALS_MOJO_JS" file="${root_gen_dir}/content/browser/process_internals/process_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_PROCESS_INTERNALS_CSS" file="browser/resources/process/process_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
@@ -36,6 +42,9 @@
<include name="IDR_SERVICE_WORKER_INTERNALS_HTML" file="browser/resources/service_worker/serviceworker_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_SERVICE_WORKER_INTERNALS_JS" file="browser/resources/service_worker/serviceworker_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
<include name="IDR_SERVICE_WORKER_INTERNALS_CSS" file="browser/resources/service_worker/serviceworker_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_UNGUESSABLE_TOKEN_MOJO_HTML" file="${root_gen_dir}/mojo/public/mojom/base/unguessable_token.mojom.html" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_UNGUESSABLE_TOKEN_MOJO_JS" file="${root_gen_dir}/mojo/public/mojom/base/unguessable_token.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_URL_MOJO_HTML" file="${root_gen_dir}/url/mojom/url.mojom.html" use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_URL_MOJO_JS" file="${root_gen_dir}/url/mojom/url.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_WEBRTC_INTERNALS_HTML" file="browser/resources/media/webrtc_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_WEBRTC_INTERNALS_JS" file="browser/resources/media/webrtc_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
diff --git a/chromium/content/gpu/DEPS b/chromium/content/gpu/DEPS
index 48cb1852111..452be50f3a5 100644
--- a/chromium/content/gpu/DEPS
+++ b/chromium/content/gpu/DEPS
@@ -9,7 +9,6 @@ include_rules = [
"+services/shape_detection",
"+services/viz/privileged/interfaces",
"+services/viz/service",
- "+services/ws/common",
"+sandbox",
"+skia",
]
diff --git a/chromium/content/gpu/gpu_child_thread.cc b/chromium/content/gpu/gpu_child_thread.cc
index 55499d9de9f..1cde925a36b 100644
--- a/chromium/content/gpu/gpu_child_thread.cc
+++ b/chromium/content/gpu/gpu_child_thread.cc
@@ -384,12 +384,12 @@ std::unique_ptr<media::AndroidOverlay> GpuChildThread::CreateAndroidOverlay(
media::mojom::AndroidOverlayProviderPtr overlay_provider;
if (main_task_runner->RunsTasksInCurrentSequence()) {
ChildThread::Get()->GetConnector()->BindInterface(
- content::mojom::kBrowserServiceName, &overlay_provider);
+ content::mojom::kSystemServiceName, &overlay_provider);
} else {
// Create a connector on this sequence and bind it on the main thread.
service_manager::mojom::ConnectorRequest request;
auto connector = service_manager::Connector::Create(&request);
- connector->BindInterface(content::mojom::kBrowserServiceName,
+ connector->BindInterface(content::mojom::kSystemServiceName,
&overlay_provider);
auto bind_connector_request =
[](service_manager::mojom::ConnectorRequest request) {
diff --git a/chromium/content/gpu/gpu_main.cc b/chromium/content/gpu/gpu_main.cc
index a838f0ccfe1..f0d320c6772 100644
--- a/chromium/content/gpu/gpu_main.cc
+++ b/chromium/content/gpu/gpu_main.cc
@@ -10,13 +10,13 @@
#include "base/bind.h"
#include "base/lazy_instance.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
+#include "base/task/single_thread_task_executor.h"
#include "base/threading/platform_thread.h"
#include "base/timer/hi_res_timer_manager.h"
#include "base/trace_event/trace_event.h"
@@ -240,17 +240,19 @@ int GpuMain(const MainFunctionParams& parameters) {
// this.
// TODO(ericrk): Revisit this once we assess its impact on crbug.com/662802
// and crbug.com/609252.
- std::unique_ptr<base::MessageLoop> main_message_loop;
+ std::unique_ptr<base::SingleThreadTaskExecutor> main_thread_task_executor;
std::unique_ptr<ui::PlatformEventSource> event_source;
if (command_line.HasSwitch(switches::kHeadless)) {
- main_message_loop.reset(
- new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT));
+ main_thread_task_executor =
+ std::make_unique<base::SingleThreadTaskExecutor>(
+ base::MessagePump::Type::DEFAULT);
} else {
#if defined(OS_WIN)
// The GpuMain thread should not be pumping Windows messages because no UI
// is expected to run on this thread.
- main_message_loop.reset(
- new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT));
+ main_thread_task_executor =
+ std::make_unique<base::SingleThreadTaskExecutor>(
+ base::MessagePump::Type::DEFAULT);
#elif defined(USE_X11)
// Depending on how Chrome is running there are multiple threads that can
// make Xlib function calls. Call XInitThreads() here to be safe, even if
@@ -262,12 +264,14 @@ int GpuMain(const MainFunctionParams& parameters) {
ui::SetDefaultX11ErrorHandlers();
if (!gfx::GetXDisplay())
return RESULT_CODE_GPU_DEAD_ON_ARRIVAL;
- main_message_loop.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI));
+ main_thread_task_executor =
+ std::make_unique<base::SingleThreadTaskExecutor>(
+ base::MessagePump::Type::UI);
event_source = ui::PlatformEventSource::CreateDefault();
#elif defined(USE_OZONE)
- // The MessageLoop type required depends on the Ozone platform selected at
+ // The MessagePump type required depends on the Ozone platform selected at
// runtime.
- main_message_loop.reset(new base::MessageLoop(
+ main_thread_task_executor.reset(new base::SingleThreadTaskExecutor(
ui::OzonePlatform::EnsureInstance()->GetMessageLoopTypeForGpu()));
#elif defined(OS_LINUX)
#error "Unsupported Linux platform."
@@ -275,14 +279,16 @@ int GpuMain(const MainFunctionParams& parameters) {
// Cross-process CoreAnimation requires a CFRunLoop to function at all, and
// requires a NSRunLoop to not starve under heavy load. See:
// https://crbug.com/312462#c51 and https://crbug.com/783298
- std::unique_ptr<base::MessagePump> pump(new base::MessagePumpNSRunLoop());
- main_message_loop.reset(new base::MessageLoop(std::move(pump)));
+ main_thread_task_executor =
+ std::make_unique<base::SingleThreadTaskExecutor>(
+ base::MessagePump::Type::NS_RUNLOOP);
// Tell LaunchServices to continue without a connection to the daemon.
_LSSetApplicationLaunchServicesServerConnectionStatus(0, nullptr);
#else
- main_message_loop.reset(
- new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT));
+ main_thread_task_executor =
+ std::make_unique<base::SingleThreadTaskExecutor>(
+ base::MessagePump::Type::DEFAULT);
#endif
}
diff --git a/chromium/content/gpu/gpu_sandbox_hook_linux.cc b/chromium/content/gpu/gpu_sandbox_hook_linux.cc
index 6f4ef48f905..e3d4e137532 100644
--- a/chromium/content/gpu/gpu_sandbox_hook_linux.cc
+++ b/chromium/content/gpu/gpu_sandbox_hook_linux.cc
@@ -137,6 +137,16 @@ void AddArmMaliGpuWhitelist(std::vector<BrokerFilePermission>* permissions) {
permissions->push_back(BrokerFilePermission::ReadWrite(kMali0Path));
permissions->push_back(BrokerFilePermission::ReadWrite(kDevImageProc0Path));
+
+ // Non-privileged render nodes for format enumeration.
+ // https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#render-nodes
+ base::FileEnumerator enumerator(
+ base::FilePath(FILE_PATH_LITERAL("/dev/dri/")), false /* recursive */,
+ base::FileEnumerator::FILES, FILE_PATH_LITERAL("renderD*"));
+ for (base::FilePath name = enumerator.Next(); !name.empty();
+ name = enumerator.Next()) {
+ permissions->push_back(BrokerFilePermission::ReadWrite(name.value()));
+ }
}
void AddImgPvrGpuWhitelist(std::vector<BrokerFilePermission>* permissions) {
diff --git a/chromium/content/ppapi_plugin/ppapi_broker_main.cc b/chromium/content/ppapi_plugin/ppapi_broker_main.cc
index 54abb280940..860e6e6bf54 100644
--- a/chromium/content/ppapi_plugin/ppapi_broker_main.cc
+++ b/chromium/content/ppapi_plugin/ppapi_broker_main.cc
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/task/single_thread_task_executor.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "content/child/child_process.h"
@@ -21,7 +21,7 @@ int PpapiBrokerMain(const MainFunctionParams& parameters) {
if (command_line.HasSwitch(switches::kPpapiStartupDialog))
WaitForDebugger("PpapiBroker");
- base::MessageLoop main_message_loop;
+ base::SingleThreadTaskExecutor main_thread_task_executor;
base::PlatformThread::SetName("CrPPAPIBrokerMain");
base::trace_event::TraceLog::GetInstance()->set_process_name(
"PPAPI Broker Process");
diff --git a/chromium/content/ppapi_plugin/ppapi_plugin_main.cc b/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
index 4ae11d2d11f..9b5204b9c57 100644
--- a/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
+++ b/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
@@ -8,10 +8,10 @@
#include "base/debug/debugger.h"
#include "base/files/file_path.h"
#include "base/i18n/rtl.h"
-#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "base/task/single_thread_task_executor.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "content/child/child_process.h"
@@ -110,7 +110,7 @@ int PpapiPluginMain(const MainFunctionParams& parameters) {
setenv("HOME", homedir.value().c_str(), 1);
#endif
- base::MessageLoop main_message_loop;
+ base::SingleThreadTaskExecutor main_thread_task_executor;
base::PlatformThread::SetName("CrPPAPIMain");
base::trace_event::TraceLog::GetInstance()->set_process_name("PPAPI Process");
base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex(
diff --git a/chromium/content/ppapi_plugin/ppapi_thread.cc b/chromium/content/ppapi_plugin/ppapi_thread.cc
index 404c240cf02..258e8b31ac4 100644
--- a/chromium/content/ppapi_plugin/ppapi_thread.cc
+++ b/chromium/content/ppapi_plugin/ppapi_thread.cc
@@ -51,7 +51,6 @@
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/resource_reply_thread_registrar.h"
#include "services/service_manager/public/cpp/connector.h"
-#include "services/ws/public/mojom/constants.mojom.h"
#include "third_party/blink/public/web/blink.h"
#include "ui/base/buildflags.h"
#include "ui/base/ui_base_features.h"
@@ -122,17 +121,8 @@ PpapiThread::PpapiThread(base::RepeatingClosure quit_closure,
// allocator.
if (!command_line.HasSwitch(switches::kSingleProcess)) {
discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr;
- if (features::IsMultiProcessMash()) {
-#if defined(USE_AURA)
- GetServiceManagerConnection()->GetConnector()->BindInterface(
- ws::mojom::kServiceName, &manager_ptr);
-#else
- NOTREACHED();
-#endif
- } else {
- ChildThread::Get()->GetConnector()->BindInterface(
- mojom::kBrowserServiceName, mojo::MakeRequest(&manager_ptr));
- }
+ ChildThread::Get()->GetConnector()->BindInterface(
+ mojom::kSystemServiceName, mojo::MakeRequest(&manager_ptr));
discardable_shared_memory_manager_ = std::make_unique<
discardable_memory::ClientDiscardableSharedMemoryManager>(
std::move(manager_ptr), GetIOTaskRunner());
@@ -430,17 +420,6 @@ void PpapiThread::OnLoadPlugin(const base::FilePath& path,
return;
}
} else {
-#if defined(OS_MACOSX)
- // TODO(kerrnel): Delete this once the V2 sandbox is default.
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
- if (!cmdline->HasSwitch(sandbox::switches::kSeatbeltClientName)) {
- // We need to do this after getting |PPP_GetInterface()| (or presumably
- // doing something nontrivial with the library), else the sandbox
- // intercedes.
- CHECK(InitializeSandbox());
- }
-#endif
-
int32_t init_error = plugin_entry_points_.initialize_module(
local_pp_module_, &ppapi::proxy::PluginDispatcher::GetBrowserInterface);
if (init_error != PP_OK) {
diff --git a/chromium/content/public/android/BUILD.gn b/chromium/content/public/android/BUILD.gn
index 5431bd16319..b43789e1264 100644
--- a/chromium/content/public/android/BUILD.gn
+++ b/chromium/content/public/android/BUILD.gn
@@ -52,11 +52,14 @@ action("generate_sandboxed_service_srcjar") {
android_library("content_java") {
deps = [
":content_java_resources",
+ "$google_play_services_package:google_play_services_auth_api_phone_java",
+ "$google_play_services_package:google_play_services_base_java",
+ "$google_play_services_package:google_play_services_basement_java",
+ "$google_play_services_package:google_play_services_tasks_java",
"//base:base_java",
"//components/download/public/common:public_java",
"//device/bluetooth:java",
"//device/gamepad:java",
- "//device/usb:java",
"//media/base/android:media_java",
"//media/capture/content/android:screen_capture_java",
"//media/capture/video/android:capture_java",
@@ -146,6 +149,7 @@ android_library("content_java") {
"java/src/org/chromium/content/browser/PopupController.java",
"java/src/org/chromium/content/browser/RenderCoordinatesImpl.java",
"java/src/org/chromium/content/browser/ScreenOrientationProviderImpl.java",
+ "java/src/org/chromium/content/browser/SmsReceiver.java",
"java/src/org/chromium/content/browser/SpareChildConnection.java",
"java/src/org/chromium/content/browser/SpeechRecognitionImpl.java",
"java/src/org/chromium/content/browser/SyntheticGestureTarget.java",
@@ -403,6 +407,7 @@ generate_jni("content_jni_headers") {
"java/src/org/chromium/content/browser/MemoryMonitorAndroid.java",
"java/src/org/chromium/content/browser/NfcHost.java",
"java/src/org/chromium/content/browser/ScreenOrientationProviderImpl.java",
+ "java/src/org/chromium/content/browser/SmsReceiver.java",
"java/src/org/chromium/content/browser/SpeechRecognitionImpl.java",
"java/src/org/chromium/content/browser/SyntheticGestureTarget.java",
"java/src/org/chromium/content/browser/TracingControllerAndroidImpl.java",
@@ -424,6 +429,7 @@ generate_jni("content_jni_headers") {
"java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java",
"java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java",
"java/src/org/chromium/content/common/ServiceManagerConnectionImpl.java",
+ "java/src/org/chromium/content/common/SurfaceWrapper.java",
"java/src/org/chromium/content_public/browser/LoadUrlParams.java",
"java/src/org/chromium/content_public/browser/NavigationHandle.java",
"java/src/org/chromium/content_public/common/ResourceRequestBody.java",
@@ -527,6 +533,7 @@ android_library("content_javatests") {
"javatests/src/org/chromium/content/browser/input/CursorAnchorInfoControllerTest.java",
"javatests/src/org/chromium/content/browser/input/ImeActivityTestRule.java",
"javatests/src/org/chromium/content/browser/input/ImeAutocapitalizeTest.java",
+ "javatests/src/org/chromium/content/browser/input/ImeInputActionTest.java",
"javatests/src/org/chromium/content/browser/input/ImeInputModeTest.java",
"javatests/src/org/chromium/content/browser/input/ImeLollipopTest.java",
"javatests/src/org/chromium/content/browser/input/ImePasswordTest.java",
@@ -557,6 +564,7 @@ junit_binary("content_junit_tests") {
java_files = [
"junit/src/org/chromium/content/browser/BindingManagerTest.java",
"junit/src/org/chromium/content/browser/ChildProcessRankingTest.java",
+ "junit/src/org/chromium/content/browser/ScreenOrientationProviderImplTest.java",
"junit/src/org/chromium/content/browser/UiThreadTaskTraitsImplTest.java",
"junit/src/org/chromium/content/browser/accessibility/BrowserAccessibilityStateTest.java",
"junit/src/org/chromium/content/browser/SpareChildConnectionTest.java",
diff --git a/chromium/content/public/android/junit/src/org/chromium/content/browser/BindingManagerTest.java b/chromium/content/public/android/junit/src/org/chromium/content/browser/BindingManagerTest.java
index 46b9bf2f0e1..1f2062983dd 100644
--- a/chromium/content/public/android/junit/src/org/chromium/content/browser/BindingManagerTest.java
+++ b/chromium/content/public/android/junit/src/org/chromium/content/browser/BindingManagerTest.java
@@ -58,6 +58,7 @@ public class BindingManagerTest {
// Created in setUp() for convenience.
BindingManager mManager;
+ BindingManager mVariableManager;
List<ChildProcessConnection> mIterable;
@@ -69,6 +70,7 @@ public class BindingManagerTest {
mActivity = Robolectric.buildActivity(Activity.class).setup().get();
mIterable = new ArrayList<>();
mManager = new BindingManager(mActivity, 4, mIterable);
+ mVariableManager = new BindingManager(mActivity, mIterable);
}
@After
@@ -83,8 +85,16 @@ public class BindingManagerTest {
@Test
@Feature({"ProcessManagement"})
public void testModerateBindingDropOnBackground() {
- final BindingManager manager = mManager;
+ doTestModerateBindingDropOnBackground(mManager);
+ }
+ @Test
+ @Feature({"ProcessManagement"})
+ public void testModerateBindingDropOnBackgroundWithVariableSize() {
+ doTestModerateBindingDropOnBackground(mVariableManager);
+ }
+
+ private void doTestModerateBindingDropOnBackground(BindingManager manager) {
ChildProcessConnection[] connections = new ChildProcessConnection[3];
for (int i = 0; i < connections.length; i++) {
connections[i] = createTestChildProcessConnection(i + 1 /* pid */, manager, mIterable);
@@ -134,8 +144,17 @@ public class BindingManagerTest {
@Test
@Feature({"ProcessManagement"})
public void testModerateBindingDropOnLowMemory() {
+ doTestModerateBindingDropOnLowMemory(mManager);
+ }
+
+ @Test
+ @Feature({"ProcessManagement"})
+ public void testModerateBindingDropOnLowMemoryVariableSize() {
+ doTestModerateBindingDropOnLowMemory(mVariableManager);
+ }
+
+ private void doTestModerateBindingDropOnLowMemory(BindingManager manager) {
final Application app = mActivity.getApplication();
- final BindingManager manager = mManager;
ChildProcessConnection[] connections = new ChildProcessConnection[4];
for (int i = 0; i < connections.length; i++) {
@@ -159,9 +178,18 @@ public class BindingManagerTest {
@Test
@Feature({"ProcessManagement"})
public void testModerateBindingDropOnTrimMemory() {
+ doTestModerateBindingDropOnTrimMemory(mManager);
+ }
+
+ @Test
+ @Feature({"ProcessManagement"})
+ public void testModerateBindingDropOnTrimMemoryWithVariableSize() {
+ doTestModerateBindingDropOnTrimMemory(mVariableManager);
+ }
+
+ private void doTestModerateBindingDropOnTrimMemory(BindingManager manager) {
final Application app = mActivity.getApplication();
// This test applies only to the moderate-binding manager.
- final BindingManager manager = mManager;
ArrayList<Pair<Integer, Integer>> levelAndExpectedVictimCountList = new ArrayList<>();
levelAndExpectedVictimCountList.add(
@@ -202,8 +230,16 @@ public class BindingManagerTest {
@Test
@Feature({"ProcessManagement"})
public void testModerateBindingTillBackgroundedSentToBackground() {
- BindingManager manager = mManager;
+ doTestModerateBindingTillBackgroundedSentToBackground(mManager);
+ }
+
+ @Test
+ @Feature({"ProcessManagement"})
+ public void testModerateBindingTillBackgroundedSentToBackgroundWithVariableSize() {
+ doTestModerateBindingTillBackgroundedSentToBackground(mVariableManager);
+ }
+ private void doTestModerateBindingTillBackgroundedSentToBackground(BindingManager manager) {
ChildProcessConnection connection = createTestChildProcessConnection(0, manager, mIterable);
Assert.assertTrue(connection.isModerateBindingBound());
@@ -219,7 +255,16 @@ public class BindingManagerTest {
@Test
@Feature({"ProcessManagement"})
public void testOneWaivedConnection() {
- final BindingManager manager = mManager;
+ testOneWaivedConnection(mManager);
+ }
+
+ @Test
+ @Feature({"ProcessManagement"})
+ public void testOneWaivedConnectionWithVariableSize() {
+ testOneWaivedConnection(mVariableManager);
+ }
+
+ private void testOneWaivedConnection(BindingManager manager) {
ChildProcessConnection[] connections = new ChildProcessConnection[3];
for (int i = 0; i < connections.length; i++) {
connections[i] = createTestChildProcessConnection(i + 1 /* pid */, manager, mIterable);
diff --git a/chromium/content/public/android/junit/src/org/chromium/content/browser/ChildProcessRankingTest.java b/chromium/content/public/android/junit/src/org/chromium/content/browser/ChildProcessRankingTest.java
index f23d72f02f5..be1cf486e7f 100644
--- a/chromium/content/public/android/junit/src/org/chromium/content/browser/ChildProcessRankingTest.java
+++ b/chromium/content/public/android/junit/src/org/chromium/content/browser/ChildProcessRankingTest.java
@@ -10,6 +10,7 @@ import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowLooper;
import org.chromium.base.process_launcher.ChildProcessConnection;
import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -20,10 +21,12 @@ import org.chromium.content_public.browser.ChildProcessImportance;
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class ChildProcessRankingTest {
- private ChildProcessConnection createConnection() {
- return new TestChildProcessConnection(new ComponentName("pkg", "cls"),
- false /* bindToCallerCheck */, false /* bindAsExternalService */,
- null /* serviceBundle */);
+ private TestChildProcessConnection createConnection() {
+ TestChildProcessConnection connection = new TestChildProcessConnection(
+ new ComponentName("pkg", "cls"), false /* bindToCallerCheck */,
+ false /* bindAsExternalService */, null /* serviceBundle */);
+ connection.start(false /* useStrongBinding */, null /* serviceCallback */);
+ return connection;
}
private void assertRankingAndRemoveAll(
@@ -49,19 +52,42 @@ public class ChildProcessRankingTest {
Assert.assertNull(ranking.getLowestRankedConnection());
}
+ private void assertNotInGroup(ChildProcessConnection[] connections) {
+ for (ChildProcessConnection c : connections) {
+ Assert.assertEquals(0, c.getGroup());
+ }
+ }
+
+ private void assertInGroupOrderedByImportance(ChildProcessConnection[] connections) {
+ int importanceSoFar = -1;
+ for (ChildProcessConnection c : connections) {
+ Assert.assertTrue(c.getGroup() > 0);
+ Assert.assertTrue(c.getImportanceInGroup() > importanceSoFar);
+ importanceSoFar = c.getImportanceInGroup();
+ }
+ }
+
@Test
public void testRanking() {
ChildProcessRanking ranking = new ChildProcessRanking(10);
- doTestRanking(ranking);
+ doTestRanking(ranking, false);
}
@Test
public void testRankingWithoutLimit() {
ChildProcessRanking ranking = new ChildProcessRanking();
- doTestRanking(ranking);
+ doTestRanking(ranking, false);
}
- private void doTestRanking(ChildProcessRanking ranking) {
+ @Test
+ public void testEnableGroupAfter() {
+ ChildProcessRanking ranking = new ChildProcessRanking();
+ doTestRanking(ranking, true);
+ }
+
+ private void doTestRanking(ChildProcessRanking ranking, boolean enableGroupImportanceAfter) {
+ if (!enableGroupImportanceAfter) ranking.enableServiceGroupImportance();
+
ChildProcessConnection c1 = createConnection();
ChildProcessConnection c2 = createConnection();
ChildProcessConnection c3 = createConnection();
@@ -108,8 +134,17 @@ public class ChildProcessRankingTest {
ranking.addConnection(c10, true /* foreground */, 0 /* frameDepth */,
true /* intersectsViewport */, ChildProcessImportance.NORMAL);
+ if (enableGroupImportanceAfter) {
+ assertNotInGroup(
+ new ChildProcessConnection[] {c10, c9, c8, c7, c6, c5, c4, c3, c2, c1});
+ ranking.enableServiceGroupImportance();
+ }
+
assertRankingAndRemoveAll(
ranking, new ChildProcessConnection[] {c10, c9, c8, c7, c6, c5, c4, c3, c2, c1});
+
+ assertNotInGroup(new ChildProcessConnection[] {c10, c9, c8});
+ assertInGroupOrderedByImportance(new ChildProcessConnection[] {c7, c6, c5, c4, c3, c2, c1});
}
@Test
@@ -120,6 +155,7 @@ public class ChildProcessRankingTest {
ChildProcessConnection c4 = createConnection();
ChildProcessRanking ranking = new ChildProcessRanking(4);
+ ranking.enableServiceGroupImportance();
// Insert in lowest ranked to highest ranked order.
ranking.addConnection(c1, false /* foreground */, 0 /* frameDepth */,
@@ -132,6 +168,8 @@ public class ChildProcessRankingTest {
false /* intersectsViewport */, ChildProcessImportance.IMPORTANT);
assertRankingAndRemoveAll(ranking, new ChildProcessConnection[] {c4, c3, c2, c1});
+ assertNotInGroup(new ChildProcessConnection[] {c4, c3, c2});
+ assertInGroupOrderedByImportance(new ChildProcessConnection[] {c1});
}
@Test
@@ -142,6 +180,7 @@ public class ChildProcessRankingTest {
ChildProcessConnection c4 = createConnection();
ChildProcessRanking ranking = new ChildProcessRanking(4);
+ ranking.enableServiceGroupImportance();
// c1,2 are in one tab, and c3,4 are in second tab.
ranking.addConnection(c1, true /* foreground */, 1 /* frameDepth */,
@@ -165,63 +204,49 @@ public class ChildProcessRankingTest {
true /* intersectsViewport */, ChildProcessImportance.NORMAL);
assertRankingAndRemoveAll(ranking, new ChildProcessConnection[] {c4, c3, c2, c1});
+ assertNotInGroup(new ChildProcessConnection[] {c4, c3});
+ assertInGroupOrderedByImportance(new ChildProcessConnection[] {c2, c1});
}
@Test
- public void testStability() {
+ public void testIntersectsViewport() {
ChildProcessConnection c1 = createConnection();
ChildProcessConnection c2 = createConnection();
ChildProcessConnection c3 = createConnection();
- ChildProcessConnection c4 = createConnection();
ChildProcessRanking ranking = new ChildProcessRanking(4);
+ ranking.enableServiceGroupImportance();
- // Each connection is its own tab.
- ranking.addConnection(c1, true /* foreground */, 0 /* frameDepth */,
- false /* intersectsViewport */, ChildProcessImportance.NORMAL);
- ranking.addConnection(c2, false /* foreground */, 0 /* frameDepth */,
- false /* intersectsViewport */, ChildProcessImportance.NORMAL);
- ranking.addConnection(c3, false /* foreground */, 0 /* frameDepth */,
- false /* intersectsViewport */, ChildProcessImportance.NORMAL);
- ranking.addConnection(c4, false /* foreground */, 0 /* frameDepth */,
- false /* intersectsViewport */, ChildProcessImportance.NORMAL);
-
- // Tab through each connection.
- ranking.updateConnection(c2, true /* foreground */, 0 /* frameDepth */,
- false /* intersectsViewport */, ChildProcessImportance.NORMAL);
- ranking.updateConnection(c1, false /* foreground */, 0 /* frameDepth */,
- false /* intersectsViewport */, ChildProcessImportance.NORMAL);
-
- ranking.updateConnection(c3, true /* foreground */, 0 /* frameDepth */,
- false /* intersectsViewport */, ChildProcessImportance.NORMAL);
- ranking.updateConnection(c2, false /* foreground */, 0 /* frameDepth */,
- false /* intersectsViewport */, ChildProcessImportance.NORMAL);
-
- ranking.updateConnection(c4, true /* foreground */, 0 /* frameDepth */,
- false /* intersectsViewport */, ChildProcessImportance.NORMAL);
- ranking.updateConnection(c3, false /* foreground */, 0 /* frameDepth */,
+ // Insert in lowest ranked to highest ranked order.
+ ranking.addConnection(c1, true /* foreground */, 1 /* frameDepth */,
false /* intersectsViewport */, ChildProcessImportance.NORMAL);
+ ranking.addConnection(c2, true /* foreground */, 1 /* frameDepth */,
+ true /* intersectsViewport */, ChildProcessImportance.NORMAL);
+ ranking.addConnection(c3, true /* foreground */, 0 /* frameDepth */,
+ true /* intersectsViewport */, ChildProcessImportance.NORMAL);
- assertRankingAndRemoveAll(ranking, new ChildProcessConnection[] {c4, c3, c2, c1});
+ assertRankingAndRemoveAll(ranking, new ChildProcessConnection[] {c3, c2, c1});
+ assertNotInGroup(new ChildProcessConnection[] {c3, c2});
+ assertInGroupOrderedByImportance(new ChildProcessConnection[] {c1});
}
@Test
- public void testIntersectsViewport() {
+ public void testFrameDepthIntOverflow() {
ChildProcessConnection c1 = createConnection();
ChildProcessConnection c2 = createConnection();
ChildProcessConnection c3 = createConnection();
+ ChildProcessRanking ranking = new ChildProcessRanking();
- ChildProcessRanking ranking = new ChildProcessRanking(4);
-
- // Insert in lowest ranked to highest ranked order.
- ranking.addConnection(c1, true /* foreground */, 1 /* frameDepth */,
- false /* intersectsViewport */, ChildProcessImportance.NORMAL);
- ranking.addConnection(c2, true /* foreground */, 1 /* frameDepth */,
+ // Native can pass up the maximum value of unsigned int.
+ long intOverflow = ((long) Integer.MAX_VALUE) * 2;
+ ranking.addConnection(c3, true /* foreground */, intOverflow - 1 /* frameDepth */,
true /* intersectsViewport */, ChildProcessImportance.NORMAL);
- ranking.addConnection(c3, true /* foreground */, 0 /* frameDepth */,
+ ranking.addConnection(c2, true /* foreground */, 10 /* frameDepth */,
+ true /* intersectsViewport */, ChildProcessImportance.NORMAL);
+ ranking.addConnection(c1, true /* foreground */, intOverflow /* frameDepth */,
true /* intersectsViewport */, ChildProcessImportance.NORMAL);
- assertRankingAndRemoveAll(ranking, new ChildProcessConnection[] {c3, c2, c1});
+ assertRankingAndRemoveAll(ranking, new ChildProcessConnection[] {c2, c3, c1});
}
@Test
@@ -245,4 +270,34 @@ public class ChildProcessRankingTest {
}
Assert.assertTrue(exceptionThrown);
}
+
+ @Test
+ public void testRebindHighRankConnection() {
+ ChildProcessRanking ranking = new ChildProcessRanking();
+ ranking.enableServiceGroupImportance();
+
+ TestChildProcessConnection c1 = createConnection();
+ TestChildProcessConnection c2 = createConnection();
+ TestChildProcessConnection c3 = createConnection();
+
+ ranking.addConnection(c1, true /* foreground */, 0 /* frameDepth */,
+ false /* intersectsViewport */, ChildProcessImportance.IMPORTANT);
+ ranking.addConnection(c2, true /* foreground */, 2 /* frameDepth */,
+ false /* intersectsViewport */, ChildProcessImportance.NORMAL);
+ ranking.addConnection(c3, true /* foreground */, 3 /* frameDepth */,
+ false /* intersectsViewport */, ChildProcessImportance.NORMAL);
+
+ assertNotInGroup(new ChildProcessConnection[] {c1});
+ assertInGroupOrderedByImportance(new ChildProcessConnection[] {c2, c3});
+
+ c1.getAndResetRebindCalled();
+ ranking.updateConnection(c3, true /* foreground */, 1 /* frameDepth */,
+ false /* intersectsViewport */, ChildProcessImportance.NORMAL);
+ assertNotInGroup(new ChildProcessConnection[] {c1});
+ assertInGroupOrderedByImportance(new ChildProcessConnection[] {c3, c2});
+ Assert.assertFalse(c1.getAndResetRebindCalled());
+
+ ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+ Assert.assertTrue(c1.getAndResetRebindCalled());
+ }
}
diff --git a/chromium/content/public/android/junit/src/org/chromium/content/browser/ScreenOrientationProviderImplTest.java b/chromium/content/public/android/junit/src/org/chromium/content/browser/ScreenOrientationProviderImplTest.java
new file mode 100644
index 00000000000..64538e2cf16
--- /dev/null
+++ b/chromium/content/public/android/junit/src/org/chromium/content/browser/ScreenOrientationProviderImplTest.java
@@ -0,0 +1,108 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser;
+
+import android.app.Activity;
+import android.content.pm.ActivityInfo;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.content_public.common.ScreenOrientationValues;
+import org.chromium.ui.base.ActivityWindowAndroid;
+
+import java.lang.ref.WeakReference;
+
+/** Unit tests for {@link ScreenOrientationProviderImpl } */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public final class ScreenOrientationProviderImplTest {
+ /**
+ * Tests that when screen orientation requests are delayed that newer requests overwrite older
+ * requests for a given activity.
+ */
+ @Test
+ public void testDelayRequests() {
+ final Activity activity = Robolectric.buildActivity(Activity.class).create().get();
+ ActivityWindowAndroid window = buildMockWindowForActivity(activity);
+
+ // Last orientation lock request should take precedence.
+ ScreenOrientationProviderImpl instance = ScreenOrientationProviderImpl.getInstance();
+ instance.delayOrientationRequests(window);
+ instance.lockOrientation(window, (byte) ScreenOrientationValues.PORTRAIT_PRIMARY);
+ instance.lockOrientation(window, (byte) ScreenOrientationValues.LANDSCAPE_PRIMARY);
+ Assert.assertEquals(
+ ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, activity.getRequestedOrientation());
+
+ instance.runDelayedOrientationRequests(window);
+ Assert.assertEquals(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, activity.getRequestedOrientation());
+
+ // Lock then unlock screen orientation while requests are delayed.
+ instance.delayOrientationRequests(window);
+ instance.lockOrientation(window, (byte) ScreenOrientationValues.PORTRAIT_PRIMARY);
+ instance.unlockOrientation(window);
+ Assert.assertEquals(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, activity.getRequestedOrientation());
+
+ instance.runDelayedOrientationRequests(window);
+ Assert.assertEquals(
+ ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, activity.getRequestedOrientation());
+ }
+
+ /**
+ * Tests that whether screen orientation requests are delayed can be toggled for each activity
+ * independently.
+ */
+ @Test
+ public void testDelayRequestsAppliesOnlyToActivity() {
+ final Activity activity1 = Robolectric.buildActivity(Activity.class).create().get();
+ ActivityWindowAndroid window1 = buildMockWindowForActivity(activity1);
+ final Activity activity2 = Robolectric.buildActivity(Activity.class).create().get();
+ ActivityWindowAndroid window2 = buildMockWindowForActivity(activity2);
+
+ ScreenOrientationProviderImpl instance = ScreenOrientationProviderImpl.getInstance();
+ instance.delayOrientationRequests(window1);
+ instance.lockOrientation(window1, (byte) ScreenOrientationValues.PORTRAIT_PRIMARY);
+ instance.lockOrientation(window2, (byte) ScreenOrientationValues.LANDSCAPE_PRIMARY);
+ Assert.assertEquals(
+ ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, activity1.getRequestedOrientation());
+ Assert.assertEquals(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, activity2.getRequestedOrientation());
+
+ instance.runDelayedOrientationRequests(window1);
+ Assert.assertEquals(
+ ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, activity1.getRequestedOrientation());
+ Assert.assertEquals(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, activity2.getRequestedOrientation());
+ }
+
+ /**
+ * Tests that removing the screen orientation request delay is a no-op if there are no pending
+ * screen orientation requests.
+ */
+ @Test
+ public void testRemoveDelayNoPendingRequests() {
+ final Activity activity = Robolectric.buildActivity(Activity.class).create().get();
+ ActivityWindowAndroid window = buildMockWindowForActivity(activity);
+
+ ScreenOrientationProviderImpl instance = ScreenOrientationProviderImpl.getInstance();
+ instance.delayOrientationRequests(window);
+ instance.runDelayedOrientationRequests(window);
+ Assert.assertEquals(
+ ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, activity.getRequestedOrientation());
+ }
+
+ private ActivityWindowAndroid buildMockWindowForActivity(Activity activity) {
+ ActivityWindowAndroid window = Mockito.mock(ActivityWindowAndroid.class);
+ Mockito.when(window.getActivity()).thenReturn(new WeakReference<>(activity));
+ return window;
+ }
+}
diff --git a/chromium/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java b/chromium/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java
index b0fe84c0136..f2ba7649bc2 100644
--- a/chromium/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java
+++ b/chromium/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java
@@ -40,8 +40,8 @@ public class SpareChildConnectionTest {
// A connection allocator not used to create connections.
private final ChildConnectionAllocator mWrongConnectionAllocator =
- ChildConnectionAllocator.createForTest(null, "org.chromium.test", "TestServiceName",
- 3 /* serviceCount */, false /* bindToCaller */,
+ ChildConnectionAllocator.createFixedForTesting(null, "org.chromium.test",
+ "TestServiceName", 3 /* serviceCount */, false /* bindToCaller */,
false /* bindAsExternalService */, false /* useStrongBinding */);
// The allocator used to allocate the actual connection.
@@ -53,7 +53,8 @@ public class SpareChildConnectionTest {
@Override
public ChildProcessConnection createConnection(Context context, ComponentName serviceName,
- boolean bindToCaller, boolean bindAsExternalService, Bundle serviceBundle) {
+ boolean bindToCaller, boolean bindAsExternalService, Bundle serviceBundle,
+ String instanceName) {
// We expect to create only one connection in these tests.
assert mConnection == null;
mConnection = new TestChildProcessConnection(
@@ -86,10 +87,10 @@ public class SpareChildConnectionTest {
// asserts are not triggered.
LauncherThread.setCurrentThreadAsLauncherThread();
- mConnectionAllocator =
- ChildConnectionAllocator.createForTest(null, "org.chromium.test.spare_connection",
- "TestServiceName", 5 /* serviceCount */, false /* bindToCaller */,
- false /* bindAsExternalService */, false /* useStrongBinding */);
+ mConnectionAllocator = ChildConnectionAllocator.createFixedForTesting(null,
+ "org.chromium.test.spare_connection", "TestServiceName", 5 /* serviceCount */,
+ false /* bindToCaller */, false /* bindAsExternalService */,
+ false /* useStrongBinding */);
mConnectionAllocator.setConnectionFactoryForTesting(mTestConnectionFactory);
mSpareConnection = new SpareChildConnection(
null /* context */, mConnectionAllocator, null /* serviceBundle */);
diff --git a/chromium/content/public/android/junit/src/org/chromium/content/browser/input/ThreadedInputConnectionFactoryTest.java b/chromium/content/public/android/junit/src/org/chromium/content/browser/input/ThreadedInputConnectionFactoryTest.java
index f5e31542e89..9ff53201de4 100644
--- a/chromium/content/public/android/junit/src/org/chromium/content/browser/input/ThreadedInputConnectionFactoryTest.java
+++ b/chromium/content/public/android/junit/src/org/chromium/content/browser/input/ThreadedInputConnectionFactoryTest.java
@@ -154,7 +154,7 @@ public class ThreadedInputConnectionFactoryTest {
@Override
public InputConnection call() throws Exception {
return mFactory.initializeAndGet(
- mContainerView, mImeAdapter, 1, 0, 0, 0, 0, mEditorInfo);
+ mContainerView, mImeAdapter, 1, 0, 0, 0, 0, 0, mEditorInfo);
}
};
when(mProxyView.onCreateInputConnection(any(EditorInfo.class)))
@@ -197,7 +197,7 @@ public class ThreadedInputConnectionFactoryTest {
@Override
public void run() {
assertNull(mFactory.initializeAndGet(
- mContainerView, mImeAdapter, 1, 0, 0, 0, 0, mEditorInfo));
+ mContainerView, mImeAdapter, 1, 0, 0, 0, 0, 0, mEditorInfo));
}
});
}
diff --git a/chromium/content/public/android/junit/src/org/chromium/content/browser/picker/DateDialogNormalizerTest.java b/chromium/content/public/android/junit/src/org/chromium/content/browser/picker/DateDialogNormalizerTest.java
index 5429f6082ba..32ec176d5b7 100644
--- a/chromium/content/public/android/junit/src/org/chromium/content/browser/picker/DateDialogNormalizerTest.java
+++ b/chromium/content/public/android/junit/src/org/chromium/content/browser/picker/DateDialogNormalizerTest.java
@@ -23,8 +23,7 @@ import java.util.TimeZone;
* Tests for DateDialogNormalizer.
*/
@RunWith(BaseRobolectricTestRunner.class)
-// sdk 18 is used due to a bug in Robolectric, crbug.com/635199
-@Config(manifest = Config.NONE, sdk = 18)
+@Config(manifest = Config.NONE, sdk = 21)
public class DateDialogNormalizerTest {
private static final long MILLIS_PER_MINUTE = 60 * 1000;
private static final long MILLIS_PER_HOUR = 60 * 60 * 1000;
diff --git a/chromium/content/public/app/BUILD.gn b/chromium/content/public/app/BUILD.gn
index 6be5a789274..98feda5825d 100644
--- a/chromium/content/public/app/BUILD.gn
+++ b/chromium/content/public/app/BUILD.gn
@@ -214,48 +214,6 @@ source_set("content_gpu_manifest") {
]
}
-source_set("content_packaged_services_manifest") {
- sources = [
- "content_packaged_services_manifest.cc",
- "content_packaged_services_manifest.h",
- ]
-
- deps = [
- "//base",
- "//components/services/heap_profiling/public/cpp:manifest",
- "//content/public/common:service_names",
- "//media/mojo/services:cdm_manifest",
- "//media/mojo/services:media_manifest",
- "//services/audio/public/cpp:manifest",
- "//services/data_decoder/public/cpp:manifest",
- "//services/device/public/cpp:manifest",
- "//services/media_session/public/cpp:manifest",
- "//services/metrics/public/cpp:manifest",
- "//services/network/public/cpp:manifest",
- "//services/resource_coordinator/public/cpp:manifest",
- "//services/shape_detection/public/cpp:manifest",
- "//services/tracing:manifest",
- "//services/video_capture/public/cpp:manifest",
- "//services/viz/public/cpp:manifest",
- ]
-
- public_deps = [
- "//services/service_manager/public/cpp",
- ]
-
- if (is_linux) {
- deps += [ "//components/services/font/public/cpp:manifest" ]
- }
-
- if (is_chromeos) {
- deps += [ "//chromeos/assistant:buildflags" ]
- if (enable_cros_libassistant) {
- deps +=
- [ "//chromeos/services/assistant/public/cpp:audio_decoder_manifest" ]
- }
- }
-}
-
source_set("content_plugin_manifest") {
sources = [
"content_plugin_manifest.cc",
@@ -328,7 +286,6 @@ group("service_manifests") {
public_deps = [
":content_browser_manifest",
":content_gpu_manifest",
- ":content_packaged_services_manifest",
":content_plugin_manifest",
":content_renderer_manifest",
":content_utility_manifest",
diff --git a/chromium/content/public/app/DEPS b/chromium/content/public/app/DEPS
index ea62ec113f2..3f7937e357d 100644
--- a/chromium/content/public/app/DEPS
+++ b/chromium/content/public/app/DEPS
@@ -14,21 +14,4 @@ specific_include_rules = {
"+services/content/public/cpp/manifest.h",
"+services/file/public/cpp/manifest.h",
],
- "content_packaged_services_manifest\.cc": [
- "+chromeos/assistant/buildflags.h",
- "+chromeos/services/assistant/public/cpp/audio_decoder_manifest.h",
- "+components/services/font/public/cpp/manifest.h",
- "+components/services/heap_profiling/public/cpp/manifest.h",
- "+media/mojo/services/cdm_manifest.h",
- "+media/mojo/services/media_manifest.h",
- "+services/data_decoder/public/cpp/manifest.h",
- "+services/device/public/cpp/manifest.h",
- "+services/media_session/public/cpp/manifest.h",
- "+services/metrics/public/cpp/manifest.h",
- "+services/network/public/cpp/manifest.h",
- "+services/resource_coordinator/public/cpp/manifest.h",
- "+services/shape_detection/public/cpp/manifest.h",
- "+services/tracing/manifest.h",
- "+services/viz/public/cpp/manifest.h",
- ],
}
diff --git a/chromium/content/public/app/OWNERS b/chromium/content/public/app/OWNERS
index 6ec455e5428..9a246da6d8d 100644
--- a/chromium/content/public/app/OWNERS
+++ b/chromium/content/public/app/OWNERS
@@ -11,11 +11,6 @@ per-file content_gpu_manifest.cc=file://ipc/SECURITY_OWNERS
per-file content_gpu_manifest.h=set noparent
per-file content_gpu_manifest.h=file://ipc/SECURITY_OWNERS
-per-file content_packaged_services_manifest.cc=set noparent
-per-file content_packaged_services_manifest.cc=file://ipc/SECURITY_OWNERS
-per-file content_packaged_services_manifest.h=set noparent
-per-file content_packaged_services_manifest.h=file://ipc/SECURITY_OWNERS
-
per-file content_plugin_manifest.cc=set noparent
per-file content_plugin_manifest.cc=file://ipc/SECURITY_OWNERS
per-file content_plugin_manifest.h=set noparent
diff --git a/chromium/content/public/app/content_browser_manifest.cc b/chromium/content/public/app/content_browser_manifest.cc
index a1fa37e05ed..20ec094bce2 100644
--- a/chromium/content/public/app/content_browser_manifest.cc
+++ b/chromium/content/public/app/content_browser_manifest.cc
@@ -67,6 +67,7 @@ const service_manager::Manifest& GetContentBrowserManifest() {
"blink.mojom.MediaStreamTrackMetricsHost",
"blink.mojom.MimeRegistry",
"blink.mojom.PluginRegistry",
+ "blink.mojom.PushMessaging",
"blink.mojom.ReportingServiceProxy",
"blink.mojom.StoragePartitionService",
"blink.mojom.WebDatabaseHost",
@@ -74,7 +75,6 @@ const service_manager::Manifest& GetContentBrowserManifest() {
"content.mojom.FieldTrialRecorder",
"content.mojom.FrameSinkProvider",
"content.mojom.PeerConnectionTrackerHost",
- "content.mojom.PushMessaging",
"content.mojom.RendererHost",
"content.mojom.ReportingServiceProxy",
"content.mojom.WorkerURLLoaderFactoryProvider",
@@ -84,7 +84,6 @@ const service_manager::Manifest& GetContentBrowserManifest() {
"media.mojom.KeySystemSupport",
"media.mojom.InterfaceFactory",
"media.mojom.VideoCaptureHost",
- "media.mojom.VideoDecodePerfHistory",
"metrics.mojom.SingleSampleMetricsProvider",
"midi.mojom.MidiSessionProvider",
"network.mojom.P2PSocketManager",
@@ -158,9 +157,11 @@ const service_manager::Manifest& GetContentBrowserManifest() {
std::set<const char*>{
"blink.mojom.CacheStorage", "blink.mojom.FileSystemManager",
"blink.mojom.IDBFactory", "blink.mojom.LockManager",
+ "blink.mojom.NativeFileSystemManager",
"blink.mojom.NotificationService",
"blink.mojom.PermissionService",
"blink.mojom.QuotaDispatcherHost", "network.mojom.WebSocket",
+ "media.mojom.VideoDecodePerfHistory",
"payments.mojom.PaymentManager",
"shape_detection.mojom.BarcodeDetectionProvider",
"shape_detection.mojom.FaceDetectionProvider",
@@ -172,11 +173,14 @@ const service_manager::Manifest& GetContentBrowserManifest() {
"blink.mojom.DedicatedWorkerHostFactory",
"blink.mojom.FileSystemManager", "blink.mojom.IDBFactory",
"blink.mojom.IdleManager", "blink.mojom.LockManager",
+ "blink.mojom.NativeFileSystemManager",
"blink.mojom.NotificationService",
"blink.mojom.PermissionService",
"blink.mojom.QuotaDispatcherHost",
"blink.mojom.SerialService", "blink.mojom.WebUsbService",
- "network.mojom.WebSocket", "payments.mojom.PaymentManager",
+ "blink.mojom.SmsManager", "network.mojom.WebSocket",
+ "media.mojom.VideoDecodePerfHistory",
+ "payments.mojom.PaymentManager",
"shape_detection.mojom.BarcodeDetectionProvider",
"shape_detection.mojom.FaceDetectionProvider",
"shape_detection.mojom.TextDetection"})
@@ -186,9 +190,11 @@ const service_manager::Manifest& GetContentBrowserManifest() {
"blink.mojom.BackgroundFetchService",
"blink.mojom.CacheStorage", "blink.mojom.CookieStore",
"blink.mojom.IDBFactory", "blink.mojom.LockManager",
+ "blink.mojom.NativeFileSystemManager",
"blink.mojom.NotificationService",
"blink.mojom.PermissionService",
"blink.mojom.QuotaDispatcherHost",
+ "media.mojom.VideoDecodePerfHistory",
"network.mojom.RestrictedCookieManager",
"network.mojom.WebSocket", "payments.mojom.PaymentManager",
"shape_detection.mojom.BarcodeDetectionProvider",
@@ -204,6 +210,7 @@ const service_manager::Manifest& GetContentBrowserManifest() {
"blink.mojom.CacheStorage",
"blink.mojom.ColorChooserFactory",
"blink.mojom.ContactsManager",
+ "blink.mojom.DateTimeChooser",
"blink.mojom.DisplayCutoutHost",
"blink.mojom.DedicatedWorkerHostFactory",
"blink.mojom.FileChooser",
@@ -217,6 +224,7 @@ const service_manager::Manifest& GetContentBrowserManifest() {
"blink.mojom.MediaDevicesDispatcherHost",
"blink.mojom.MediaStreamDispatcherHost",
"blink.mojom.MediaSessionService",
+ "blink.mojom.NativeFileSystemManager",
"blink.mojom.NotificationService",
"blink.mojom.PermissionService",
"blink.mojom.PictureInPictureService",
@@ -226,6 +234,7 @@ const service_manager::Manifest& GetContentBrowserManifest() {
"blink.mojom.QuotaDispatcherHost",
"blink.mojom.SerialService",
"blink.mojom.SharedWorkerConnector",
+ "blink.mojom.SmsManager",
"blink.mojom.SpeechRecognizer",
"blink.mojom.TextSuggestionHost",
"blink.mojom.UnhandledTapNotifier",
@@ -242,19 +251,19 @@ const service_manager::Manifest& GetContentBrowserManifest() {
"device.mojom.SensorProvider",
"device.mojom.VibrationManager",
"device.mojom.VRService",
- "device.mojom.WakeLock",
"discardable_memory.mojom.DiscardableSharedMemoryManager",
"media.mojom.ImageCapture",
"media.mojom.InterfaceFactory",
"media.mojom.MediaMetricsProvider",
"media.mojom.RemoterFactory",
"media.mojom.Renderer",
+ "media.mojom.VideoDecodePerfHistory",
"mojom.ProcessInternalsHandler",
"network.mojom.RestrictedCookieManager",
"network.mojom.WebSocket",
"payments.mojom.PaymentManager",
"payments.mojom.PaymentRequest",
- "resource_coordinator.mojom.FrameCoordinationUnit",
+ "resource_coordinator.mojom.DocumentCoordinationUnit",
"shape_detection.mojom.BarcodeDetectionProvider",
"shape_detection.mojom.FaceDetectionProvider",
"shape_detection.mojom.TextDetection",
diff --git a/chromium/content/public/app/content_browser_manifest.h b/chromium/content/public/app/content_browser_manifest.h
index 535c14051c7..63b46d904d0 100644
--- a/chromium/content/public/app/content_browser_manifest.h
+++ b/chromium/content/public/app/content_browser_manifest.h
@@ -10,10 +10,9 @@
namespace content {
// Returns the service manifest for the "content_browser" service. There are
-// multiple instances of this service embedded within the browser process: a
-// global instance which establishes a process-wide connection to the Service
-// Manager, and one instance per BrowserContext which can be used to connect to
-// service instances isolated on a per-BrowserContext basis.
+// multiple instances of this service embedded within the browser process: one
+// instance per BrowserContext which can be used to connect to service instances
+// isolated on a per-BrowserContext basis.
//
// In-process services whose instances should each be bound to the lifetime of
// some BrowserContext are typically packaged within this manifest. For all
diff --git a/chromium/content/public/app/content_gpu_manifest.cc b/chromium/content/public/app/content_gpu_manifest.cc
index b9926a5a623..06b9be3525d 100644
--- a/chromium/content/public/app/content_gpu_manifest.cc
+++ b/chromium/content/public/app/content_gpu_manifest.cc
@@ -25,15 +25,15 @@ const service_manager::Manifest& GetContentGpuManifest() {
"IPC.mojom.ChannelBootstrap",
"ui.ozone.mojom.DeviceCursor",
"ui.ozone.mojom.DrmDevice",
- "ui.ozone.mojom.WaylandConnectionClient",
+ "ui.ozone.mojom.WaylandBufferManagerGpu",
"ui.mojom.ScenicGpuService",
"viz.mojom.CompositingModeReporter",
"viz.mojom.VizMain",
})
.RequireCapability("device", "device:power_monitor")
- .RequireCapability(mojom::kBrowserServiceName, "dwrite_font_proxy")
- .RequireCapability(mojom::kBrowserServiceName, "field_trials")
- .RequireCapability(mojom::kBrowserServiceName, "gpu")
+ .RequireCapability(mojom::kSystemServiceName, "dwrite_font_proxy")
+ .RequireCapability(mojom::kSystemServiceName, "field_trials")
+ .RequireCapability(mojom::kSystemServiceName, "gpu")
.RequireCapability("ui", "discardable_memory")
.RequireCapability("*", "app")
.RequireCapability("metrics", "url_keyed_metrics")
diff --git a/chromium/content/public/app/content_main.h b/chromium/content/public/app/content_main.h
index b3dd9edee9f..01208771aa3 100644
--- a/chromium/content/public/app/content_main.h
+++ b/chromium/content/public/app/content_main.h
@@ -70,6 +70,11 @@ struct ContentMainParams {
// This should only be called once before ContentMainRunner actually running.
// The ownership of |delegate| is transferred.
CONTENT_EXPORT void SetContentMainDelegate(ContentMainDelegate* delegate);
+
+// In browser tests, ContentMain.java is not run either, and the browser test
+// harness does not run ContentMain() at all. It does need to make use of the
+// delegate though while replacing ContentMain().
+CONTENT_EXPORT ContentMainDelegate* GetContentMainDelegateForTesting();
#else
// ContentMain should be called from the embedder's main() function to do the
// initial setup for every process. The embedder has a chance to customize
diff --git a/chromium/content/public/app/content_main_delegate.h b/chromium/content/public/app/content_main_delegate.h
index f498906f693..d4f3b8097c6 100644
--- a/chromium/content/public/app/content_main_delegate.h
+++ b/chromium/content/public/app/content_main_delegate.h
@@ -134,8 +134,13 @@ class CONTENT_EXPORT ContentMainDelegate {
// list initialization is complete.
virtual void PostFieldTrialInitialization() {}
+ // Allows the embedder to perform its own initialization after the
+ // TaskScheduler is started.
+ virtual void PostTaskSchedulerStart() {}
+
protected:
friend class ContentClientInitializer;
+ friend class BrowserTestBase;
// Called once per relevant process type to allow the embedder to customize
// content. If an embedder wants the default (empty) implementation, don't
diff --git a/chromium/content/public/app/content_packaged_services_manifest.cc b/chromium/content/public/app/content_packaged_services_manifest.cc
deleted file mode 100644
index 0bf10f268fd..00000000000
--- a/chromium/content/public/app/content_packaged_services_manifest.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2019 The Chromium Authors. All 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/app/content_packaged_services_manifest.h"
-
-#include "base/no_destructor.h"
-#include "build/build_config.h"
-#include "components/services/heap_profiling/public/cpp/manifest.h"
-#include "content/public/common/service_names.mojom.h"
-#include "media/mojo/services/cdm_manifest.h"
-#include "media/mojo/services/media_manifest.h"
-#include "services/audio/public/cpp/manifest.h"
-#include "services/data_decoder/public/cpp/manifest.h"
-#include "services/device/public/cpp/manifest.h"
-#include "services/media_session/public/cpp/manifest.h"
-#include "services/metrics/public/cpp/manifest.h"
-#include "services/network/public/cpp/manifest.h"
-#include "services/resource_coordinator/public/cpp/manifest.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-#include "services/shape_detection/public/cpp/manifest.h"
-#include "services/tracing/manifest.h"
-#include "services/video_capture/public/cpp/manifest.h"
-#include "services/viz/public/cpp/manifest.h"
-
-#if defined(OS_LINUX)
-#include "components/services/font/public/cpp/manifest.h" // nogncheck
-#endif
-
-#if defined(OS_CHROMEOS)
-#include "chromeos/assistant/buildflags.h"
-#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
-#include "chromeos/services/assistant/public/cpp/audio_decoder_manifest.h" // nogncheck
-#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
-#endif // defined(OS_CHROMEOS)
-
-namespace content {
-
-const service_manager::Manifest& GetContentPackagedServicesManifest() {
- static base::NoDestructor<service_manager::Manifest> manifest {
- service_manager::ManifestBuilder()
- .WithServiceName(mojom::kPackagedServicesServiceName)
- .WithOptions(service_manager::ManifestOptionsBuilder()
- .WithInstanceSharingPolicy(
- service_manager::Manifest::InstanceSharingPolicy::
- kSingleton)
- .CanConnectToInstancesInAnyGroup(true)
- .CanRegisterOtherServiceInstances(true)
- .Build())
- .RequireCapability(mojom::kBrowserServiceName, "")
- .RequireCapability("*", "app")
- .PackageService(heap_profiling::GetManifest())
- .PackageService(media::GetCdmManifest())
- .PackageService(media::GetMediaManifest())
- .PackageService(audio::GetManifest())
- .PackageService(data_decoder::GetManifest())
- .PackageService(device::GetManifest())
- .PackageService(media_session::GetManifest())
- .PackageService(metrics::GetManifest())
- .PackageService(network::GetManifest())
- .PackageService(resource_coordinator::GetManifest())
- .PackageService(shape_detection::GetManifest())
- .PackageService(tracing::GetManifest())
- .PackageService(video_capture::GetManifest())
- .PackageService(viz::GetManifest())
-#if defined(OS_LINUX)
- .PackageService(font_service::GetManifest())
-#endif
-#if defined(OS_CHROMEOS)
-#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
- // TODO(https://crbug.com/929340): This doesn't belong here!
- .PackageService(chromeos::assistant::GetAudioDecoderManifest())
-#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
-#endif // defined(OS_CHROMEOS)
- .Build()
- };
- return *manifest;
-}
-
-} // namespace content
diff --git a/chromium/content/public/app/content_packaged_services_manifest.h b/chromium/content/public/app/content_packaged_services_manifest.h
deleted file mode 100644
index 7e7497793af..00000000000
--- a/chromium/content/public/app/content_packaged_services_manifest.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_APP_CONTENT_PACKAGED_SERVICES_MANIFEST_H_
-#define CONTENT_PUBLIC_APP_CONTENT_PACKAGED_SERVICES_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace content {
-
-// Returns the service manifest for the "content_packaged_services" service.
-// This is a singleton service embedded in the browser process, and it exists
-// to package other in- and out-of-process services hosted by Content or its
-// embedder.
-//
-// TODO(https://crbug.com/689159): This can be removed once process launching is
-// moved out of Content and into the Service Manager. Instead of this hack, we
-// should have a Service Manager embedder API for plugging in manifests at
-// startup, as well as for hooking up in- and out-of-process service
-// instantiation logic for individual services.
-const service_manager::Manifest& GetContentPackagedServicesManifest();
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_APP_CONTENT_PACKAGED_SERVICES_MANIFEST_H_
diff --git a/chromium/content/public/app/content_plugin_manifest.cc b/chromium/content/public/app/content_plugin_manifest.cc
index 4f7618a741d..6d17755cab0 100644
--- a/chromium/content/public/app/content_plugin_manifest.cc
+++ b/chromium/content/public/app/content_plugin_manifest.cc
@@ -25,11 +25,11 @@ const service_manager::Manifest& GetContentPluginManifest() {
"IPC.mojom.ChannelBootstrap",
})
.RequireCapability("device", "device:power_monitor")
- .RequireCapability(mojom::kBrowserServiceName, "dwrite_font_proxy")
- .RequireCapability(mojom::kBrowserServiceName, "field_trials")
- .RequireCapability(mojom::kBrowserServiceName, "font_cache")
- .RequireCapability(mojom::kBrowserServiceName, "plugin")
- .RequireCapability(mojom::kBrowserServiceName, "sandbox_support")
+ .RequireCapability(mojom::kSystemServiceName, "dwrite_font_proxy")
+ .RequireCapability(mojom::kSystemServiceName, "field_trials")
+ .RequireCapability(mojom::kSystemServiceName, "font_cache")
+ .RequireCapability(mojom::kSystemServiceName, "plugin")
+ .RequireCapability(mojom::kSystemServiceName, "sandbox_support")
.RequireCapability("ui", "discardable_memory")
.RequireCapability("*", "app")
.RequireCapability("font_service", "font_service")
diff --git a/chromium/content/public/app/content_renderer_manifest.cc b/chromium/content/public/app/content_renderer_manifest.cc
index 92519a9bac1..6d6781a266f 100644
--- a/chromium/content/public/app/content_renderer_manifest.cc
+++ b/chromium/content/public/app/content_renderer_manifest.cc
@@ -46,9 +46,11 @@ const service_manager::Manifest& GetContentRendererManifest() {
.RequireCapability("device", "device:screen_orientation")
.RequireCapability("device", "device:time_zone_monitor")
.RequireCapability(mojom::kBrowserServiceName, "dwrite_font_proxy")
- .RequireCapability(mojom::kBrowserServiceName, "field_trials")
+ .RequireCapability(mojom::kSystemServiceName, "dwrite_font_proxy")
+ .RequireCapability(mojom::kSystemServiceName, "field_trials")
.RequireCapability(mojom::kBrowserServiceName, "renderer")
- .RequireCapability(mojom::kBrowserServiceName, "sandbox_support")
+ .RequireCapability(mojom::kSystemServiceName, "renderer")
+ .RequireCapability(mojom::kSystemServiceName, "sandbox_support")
.RequireInterfaceFilterCapability_Deprecated(
mojom::kBrowserServiceName, "navigation:shared_worker",
"renderer")
diff --git a/chromium/content/public/app/content_utility_manifest.cc b/chromium/content/public/app/content_utility_manifest.cc
index 42d17724abe..e3eafb71b0f 100644
--- a/chromium/content/public/app/content_utility_manifest.cc
+++ b/chromium/content/public/app/content_utility_manifest.cc
@@ -29,10 +29,10 @@ const service_manager::Manifest& GetContentUtilityManifest() {
})
.RequireCapability("device", "device:power_monitor")
.RequireCapability("device", "device:time_zone_monitor")
- .RequireCapability(mojom::kBrowserServiceName, "dwrite_font_proxy")
- .RequireCapability(mojom::kBrowserServiceName, "field_trials")
- .RequireCapability(mojom::kBrowserServiceName, "font_cache")
- .RequireCapability(mojom::kBrowserServiceName, "sandbox_support")
+ .RequireCapability(mojom::kSystemServiceName, "dwrite_font_proxy")
+ .RequireCapability(mojom::kSystemServiceName, "field_trials")
+ .RequireCapability(mojom::kSystemServiceName, "font_cache")
+ .RequireCapability(mojom::kSystemServiceName, "sandbox_support")
.RequireCapability("*", "app")
.RequireCapability("font_service", "font_service")
.Build()
diff --git a/chromium/content/public/app/mac_helpers.gni b/chromium/content/public/app/mac_helpers.gni
new file mode 100644
index 00000000000..1414b7426b2
--- /dev/null
+++ b/chromium/content/public/app/mac_helpers.gni
@@ -0,0 +1,54 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This list defines variants of the helper app bundles that macOS //content
+# embedders need to produce. The different variants are code signed with
+# different entitlements, which afford different capabilities depending on the
+# requirements of the process.
+#
+# This list should be kept in sync with the enum options defined in
+# //content/public/common/child_process_host.h.
+#
+# Each element of the list list is a tuple representing a helper variant. The
+# elements of the tuple are:
+# target name - A short name to be used when defining the target for that
+# helper variant.
+# bundle ID suffix - A string fragment to append to the CFBundleIdentifier of
+# the helper.
+# app name suffix - A string fragment to append to the outer bundle name as
+# well as the inner executable. This should be reflected in
+# the target's output_name.
+content_mac_helpers = [
+ # The basic helper with no special entitlements.
+ [
+ "default",
+ "",
+ "",
+ ],
+
+ # A helper with the capability to JIT (execute writable memory), needed by V8,
+ # and used to run renderer processes.
+ [
+ "renderer",
+ ".renderer",
+ " (Renderer)",
+ ],
+
+ # A helper with the capability to execute writable memory, needed by
+ # Swiftshader, and used to run renderer processes.
+ [
+ "gpu",
+ ".gpu",
+ " (GPU)",
+ ],
+
+ # A helper that does not perform library validation, allowing code not signed
+ # by either Apple or the signing identity to be loaded, and that can execute
+ # unsigned memory. This is used by binary plugins like Flash.
+ [
+ "plugin",
+ ".plugin",
+ " (Plugin)",
+ ],
+]
diff --git a/chromium/content/public/browser/BUILD.gn b/chromium/content/public/browser/BUILD.gn
index ae744eda8ae..ac3e1aa8c76 100644
--- a/chromium/content/public/browser/BUILD.gn
+++ b/chromium/content/public/browser/BUILD.gn
@@ -43,6 +43,7 @@ jumbo_source_set("browser_sources") {
"audio_loopback_stream_creator.h",
"audio_service_info.cc",
"audio_service_info.h",
+ "authenticator_environment.h",
"authenticator_request_client_delegate.cc",
"authenticator_request_client_delegate.h",
"ax_event_notification_details.cc",
@@ -63,6 +64,8 @@ jumbo_source_set("browser_sources") {
"blob_handle.h",
"bluetooth_chooser.cc",
"bluetooth_chooser.h",
+ "bluetooth_scanning_prompt.cc",
+ "bluetooth_scanning_prompt.h",
"browser_accessibility_state.h",
"browser_associated_interface.h",
"browser_child_process_host.h",
@@ -113,7 +116,6 @@ jumbo_source_set("browser_sources") {
"cors_exempt_headers.h",
"cors_origin_pattern_setter.cc",
"cors_origin_pattern_setter.h",
- "delegate_to_browser_gpu_service_accelerator_factory.h",
"desktop_capture.cc",
"desktop_capture.h",
"desktop_media_id.cc",
@@ -124,6 +126,7 @@ jumbo_source_set("browser_sources") {
"devtools_agent_host_client.h",
"devtools_agent_host_observer.cc",
"devtools_agent_host_observer.h",
+ "devtools_background_services_context.h",
"devtools_external_agent_proxy.h",
"devtools_external_agent_proxy_delegate.h",
"devtools_frontend_host.h",
@@ -283,6 +286,7 @@ jumbo_source_set("browser_sources") {
"site_instance.h",
"site_isolation_policy.cc",
"site_isolation_policy.h",
+ "sms_service.h",
"speech_recognition_event_listener.h",
"speech_recognition_manager.h",
"speech_recognition_manager_delegate.h",
@@ -371,11 +375,11 @@ jumbo_source_set("browser_sources") {
public_deps = [
"//components/download/public/common:public",
"//content/public/common:common_sources",
- "//device/usb/public/mojom",
"//ipc",
"//media/mojo/interfaces:remoting",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
+ "//services/device/public/mojom:usb",
"//services/media_session/public/cpp",
"//services/media_session/public/mojom",
"//services/network/public/mojom",
@@ -390,7 +394,6 @@ jumbo_source_set("browser_sources") {
# We expose storage headers for quota and blob storage context in the public API.
"//storage/browser",
- "//third_party/blink/public:mojo_bindings",
]
deps = [
"//cc",
@@ -440,10 +443,7 @@ jumbo_source_set("browser_sources") {
}
if (is_mac) {
- sources += [
- "ns_view_bridge_factory_host.h",
- "ns_view_bridge_factory_impl.h",
- ]
+ sources += [ "remote_cocoa.h" ]
}
if (!is_android) {
@@ -452,4 +452,9 @@ jumbo_source_set("browser_sources") {
"zoom_level_delegate.h",
]
}
+
+ if (is_chromeos) {
+ sources +=
+ [ "chromeos/delegate_to_browser_gpu_service_accelerator_factory.h" ]
+ }
}
diff --git a/chromium/content/public/browser/DEPS b/chromium/content/public/browser/DEPS
index 805504c5638..995eedcc1e2 100644
--- a/chromium/content/public/browser/DEPS
+++ b/chromium/content/public/browser/DEPS
@@ -4,7 +4,6 @@ include_rules = [
"+components/download/public/common",
"+components/viz/common",
"+components/viz/host",
- "+device/usb/public/mojom",
"+device/fido",
"+services/device/public",
"+services/media_session/public",
diff --git a/chromium/content/public/browser/android/compositor.h b/chromium/content/public/browser/android/compositor.h
index 54978c94313..c8fd681da7b 100644
--- a/chromium/content/public/browser/android/compositor.h
+++ b/chromium/content/public/browser/android/compositor.h
@@ -68,7 +68,8 @@ class CONTENT_EXPORT Compositor {
virtual void SetWindowBounds(const gfx::Size& size) = 0;
// Set the output surface which the compositor renders into.
- virtual void SetSurface(jobject surface, bool backed_by_surface_texture) = 0;
+ virtual void SetSurface(jobject surface,
+ bool can_be_used_with_surface_control) = 0;
// Set the background color used by the layer tree host.
virtual void SetBackgroundColor(int color) = 0;
@@ -88,6 +89,14 @@ class CONTENT_EXPORT Compositor {
// Returns the resource manager associated with the compositor.
virtual ui::ResourceManager& GetResourceManager() = 0;
+ // Caches the back buffer associated with the current surface, if any. The
+ // client is responsible for evicting this cache entry before destroying the
+ // associated window.
+ virtual void CacheBackBufferForCurrentSurface() = 0;
+
+ // Evicts the cache entry created from the cached call above.
+ virtual void EvictCachedBackBuffer() = 0;
+
protected:
Compositor() {}
};
diff --git a/chromium/content/public/browser/android/synchronous_compositor.h b/chromium/content/public/browser/android/synchronous_compositor.h
index 4049d9347bd..59d2651d802 100644
--- a/chromium/content/public/browser/android/synchronous_compositor.h
+++ b/chromium/content/public/browser/android/synchronous_compositor.h
@@ -92,7 +92,8 @@ class CONTENT_EXPORT SynchronousCompositor {
const std::vector<viz::ReturnedResource>& resources) = 0;
virtual void DidPresentCompositorFrames(
- viz::PresentationFeedbackMap feedbacks) = 0;
+ viz::PresentationFeedbackMap feedbacks,
+ uint32_t frame_token) = 0;
// "On demand" SW draw, into the supplied canvas (observing the transform
// and clip set there-in).
diff --git a/chromium/content/public/browser/authenticator_environment.h b/chromium/content/public/browser/authenticator_environment.h
new file mode 100644
index 00000000000..f9937199c64
--- /dev/null
+++ b/chromium/content/public/browser/authenticator_environment.h
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_AUTHENTICATOR_ENVIRONMENT_H_
+#define CONTENT_PUBLIC_BROWSER_AUTHENTICATOR_ENVIRONMENT_H_
+
+#include <memory>
+
+#include "content/common/content_export.h"
+
+namespace device {
+class FidoDiscoveryFactory;
+}
+
+namespace content {
+
+// Allows replacing the default FidoDiscoveryFactory to support injecting
+// virtual authenticators.
+class CONTENT_EXPORT AuthenticatorEnvironment {
+ public:
+ virtual ~AuthenticatorEnvironment() = default;
+
+ // Returns the singleton instance.
+ static AuthenticatorEnvironment* GetInstance();
+
+ // Sets a custom FidoDiscoveryFactory to be used instead of the default real
+ // FidoDiscoveryFactory.
+ virtual void ReplaceDefaultDiscoveryFactoryForTesting(
+ std::unique_ptr<device::FidoDiscoveryFactory> factory) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_AUTHENTICATOR_ENVIRONMENT_H_
diff --git a/chromium/content/public/browser/authenticator_request_client_delegate.h b/chromium/content/public/browser/authenticator_request_client_delegate.h
index 6d34ff72bde..ce8aca32beb 100644
--- a/chromium/content/public/browser/authenticator_request_client_delegate.h
+++ b/chromium/content/public/browser/authenticator_request_client_delegate.h
@@ -45,6 +45,9 @@ class CONTENT_EXPORT AuthenticatorRequestClientDelegate
kAuthenticatorRemovedDuringPINEntry,
kAuthenticatorMissingResidentKeys,
kAuthenticatorMissingUserVerification,
+ // kStorageFull indicates that a resident credential could not be created
+ // because the authenticator has insufficient storage.
+ kStorageFull,
};
AuthenticatorRequestClientDelegate();
diff --git a/chromium/content/public/browser/background_sync_parameters.cc b/chromium/content/public/browser/background_sync_parameters.cc
index 89d1021af76..dc19a5a162e 100644
--- a/chromium/content/public/browser/background_sync_parameters.cc
+++ b/chromium/content/public/browser/background_sync_parameters.cc
@@ -17,6 +17,7 @@ const int64_t kMinSyncRecoveryTimeSec = 60 * 6; // 6 minutes
BackgroundSyncParameters::BackgroundSyncParameters()
: disable(false),
max_sync_attempts(kMaxSyncAttempts),
+ max_sync_attempts_with_notification_permission(kMaxSyncAttempts),
initial_retry_delay(base::TimeDelta::FromSeconds(kInitialRetryDelaySec)),
retry_delay_factor(kRetryDelayFactor),
min_sync_recovery_time(
@@ -27,6 +28,8 @@ bool BackgroundSyncParameters::operator==(
const BackgroundSyncParameters& other) const {
return disable == other.disable &&
max_sync_attempts == other.max_sync_attempts &&
+ max_sync_attempts_with_notification_permission ==
+ other.max_sync_attempts_with_notification_permission &&
initial_retry_delay == other.initial_retry_delay &&
retry_delay_factor == other.retry_delay_factor &&
min_sync_recovery_time == other.min_sync_recovery_time &&
diff --git a/chromium/content/public/browser/background_sync_parameters.h b/chromium/content/public/browser/background_sync_parameters.h
index 1c1afaeac9f..24643dcabea 100644
--- a/chromium/content/public/browser/background_sync_parameters.h
+++ b/chromium/content/public/browser/background_sync_parameters.h
@@ -20,10 +20,16 @@ struct CONTENT_EXPORT BackgroundSyncParameters {
// fail.
bool disable;
- // The number of attempts the BackgroundSyncManager will make to fire an event
- // before giving up.
+ // The number of attempts the BackgroundSyncManager will make to fire an
+ // event before giving up.
int max_sync_attempts;
+ // The number of attempts the BackgroundSyncManager will make to fire an
+ // event before giving up, assuming the origin has notification permission.
+ // This value will override |max_sync_attempts| assuming the Sync
+ // Registration's origin has notification permissions.
+ int max_sync_attempts_with_notification_permission;
+
// The first time that a registration retries, it will wait at least this much
// time before doing so.
base::TimeDelta initial_retry_delay;
diff --git a/chromium/content/public/browser/background_tracing_config.h b/chromium/content/public/browser/background_tracing_config.h
index 6cd614587e8..f7922399973 100644
--- a/chromium/content/public/browser/background_tracing_config.h
+++ b/chromium/content/public/browser/background_tracing_config.h
@@ -31,7 +31,7 @@ class CONTENT_EXPORT BackgroundTracingConfig {
static std::unique_ptr<BackgroundTracingConfig> FromDict(
const base::DictionaryValue* dict);
- virtual void IntoDict(base::DictionaryValue* dict) const = 0;
+ virtual void IntoDict(base::DictionaryValue* dict) = 0;
private:
friend class BackgroundTracingConfigImpl;
diff --git a/chromium/content/public/browser/background_tracing_manager.h b/chromium/content/public/browser/background_tracing_manager.h
index d3178a3cbf5..c6d470004c9 100644
--- a/chromium/content/public/browser/background_tracing_manager.h
+++ b/chromium/content/public/browser/background_tracing_manager.h
@@ -102,8 +102,9 @@ class BackgroundTracingManager {
virtual std::string GetLatestTraceToUpload() = 0;
// For tests
- virtual void AbortScenario() = 0;
- virtual void SetTraceToUploadForTesting(base::StringPiece data) = 0;
+ virtual void AbortScenarioForTesting() = 0;
+ virtual void SetTraceToUploadForTesting(
+ std::unique_ptr<std::string> trace_data) = 0;
protected:
virtual ~BackgroundTracingManager() {}
diff --git a/chromium/content/public/browser/bluetooth_scanning_prompt.cc b/chromium/content/public/browser/bluetooth_scanning_prompt.cc
new file mode 100644
index 00000000000..669c18fd1b8
--- /dev/null
+++ b/chromium/content/public/browser/bluetooth_scanning_prompt.cc
@@ -0,0 +1,13 @@
+// Copyright 2019 The Chromium Authors. All 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/bluetooth_scanning_prompt.h"
+
+namespace content {
+
+BluetoothScanningPrompt::BluetoothScanningPrompt() = default;
+
+BluetoothScanningPrompt::~BluetoothScanningPrompt() = default;
+
+} // namespace content
diff --git a/chromium/content/public/browser/bluetooth_scanning_prompt.h b/chromium/content/public/browser/bluetooth_scanning_prompt.h
new file mode 100644
index 00000000000..6f8b3398ced
--- /dev/null
+++ b/chromium/content/public/browser/bluetooth_scanning_prompt.h
@@ -0,0 +1,53 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_BLUETOOTH_SCANNING_PROMPT_H_
+#define CONTENT_PUBLIC_BROWSER_BLUETOOTH_SCANNING_PROMPT_H_
+
+#include <string>
+
+#include "base/callback_forward.h"
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Represents a way to ask the user permission to allow a site to receive
+// Bluetooth advertisement packets from Bluetooth devices.
+class CONTENT_EXPORT BluetoothScanningPrompt {
+ public:
+ enum class Event {
+ kAllow,
+ kBlock,
+ // This can happen when multiple request scanning functions are called,
+ // and in this case, the previous prompts will be closed.
+ kCanceled,
+ };
+
+ // Prompt implementations are constructed with an |EventHandler| and report
+ // user interaction with the prompt through it.
+ //
+ // The EventHandler won't be called after the prompt object is destroyed.
+ //
+ // After the EventHandler is called, it won't be called again, and
+ // users must not call any more BluetoothScanningPrompt methods.
+ using EventHandler = base::RepeatingCallback<void(Event)>;
+
+ BluetoothScanningPrompt();
+ virtual ~BluetoothScanningPrompt();
+
+ // Adds a new device to the prompt or updates the information of an
+ // existing device.
+ //
+ // Sometimes when a Bluetooth device stops advertising, the |device_name|
+ // can be invalid, and in that case |should_update_name| will be set
+ // false.
+ virtual void AddOrUpdateDevice(const std::string& device_id,
+ bool should_update_name,
+ const base::string16& device_name) {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_BLUETOOTH_SCANNING_PROMPT_H_
diff --git a/chromium/content/public/browser/browser_accessibility_state.h b/chromium/content/public/browser/browser_accessibility_state.h
index 389acd30dd7..94afa54314e 100644
--- a/chromium/content/public/browser/browser_accessibility_state.h
+++ b/chromium/content/public/browser/browser_accessibility_state.h
@@ -31,7 +31,7 @@ class CONTENT_EXPORT BrowserAccessibilityState {
virtual bool IsRendererAccessibilityEnabled() = 0;
- virtual ui::AXMode GetAccessibilityMode() const = 0;
+ virtual ui::AXMode GetAccessibilityMode() = 0;
// Adds the given accessibility mode flags to the current accessibility
// mode bitmap.
diff --git a/chromium/content/public/browser/browser_context.h b/chromium/content/public/browser/browser_context.h
index d2570b23290..abbedb874e9 100644
--- a/chromium/content/public/browser/browser_context.h
+++ b/chromium/content/public/browser/browser_context.h
@@ -23,6 +23,7 @@
#include "services/network/public/mojom/cors_origin_pattern.mojom-forward.h"
#include "services/service_manager/public/mojom/service.mojom-forward.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-forward.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom-forward.h"
#if !defined(OS_ANDROID)
#include "content/public/browser/zoom_level_delegate.h"
@@ -85,6 +86,7 @@ class PermissionControllerDelegate;
class PushMessagingService;
class ResourceContext;
class ServiceManagerConnection;
+class SmsService;
class SharedCorsOriginAccessList;
class SiteInstance;
class StoragePartition;
@@ -180,8 +182,9 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
+ const std::string& message_id,
base::Optional<std::string> payload,
- const base::Callback<void(mojom::PushDeliveryStatus)>& callback);
+ const base::Callback<void(blink::mojom::PushDeliveryStatus)>& callback);
static void NotifyWillBeDestroyed(BrowserContext* browser_context);
@@ -364,6 +367,10 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
virtual download::InProgressDownloadManager*
RetriveInProgressDownloadManager();
+ // Returns the SmsService associated with this context if any,
+ // nullptr otherwise.
+ virtual SmsService* GetSmsService();
+
private:
const std::string unique_id_;
bool was_notify_will_be_destroyed_called_ = false;
diff --git a/chromium/content/public/browser/browser_plugin_guest_delegate.cc b/chromium/content/public/browser/browser_plugin_guest_delegate.cc
index 0afafccbde1..b7ff8c561ce 100644
--- a/chromium/content/public/browser/browser_plugin_guest_delegate.cc
+++ b/chromium/content/public/browser/browser_plugin_guest_delegate.cc
@@ -32,4 +32,9 @@ SiteInstance* BrowserPluginGuestDelegate::GetOwnerSiteInstance() {
return nullptr;
}
+RenderFrameHost* BrowserPluginGuestDelegate::GetEmbedderFrame() const {
+ NOTREACHED();
+ return nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/public/browser/browser_plugin_guest_delegate.h b/chromium/content/public/browser/browser_plugin_guest_delegate.h
index bf2226b53dd..b7db83c24fc 100644
--- a/chromium/content/public/browser/browser_plugin_guest_delegate.h
+++ b/chromium/content/public/browser/browser_plugin_guest_delegate.h
@@ -17,6 +17,7 @@ class Size;
namespace content {
class GuestHost;
+class RenderFrameHost;
class RenderWidgetHost;
class SiteInstance;
@@ -81,6 +82,9 @@ class CONTENT_EXPORT BrowserPluginGuestDelegate {
// Returns true if the corresponding guest is allowed to be embedded inside an
// <iframe> which is cross process.
virtual bool CanBeEmbeddedInsideCrossProcessFrames();
+
+ // Returns the embedder frame for this guest.
+ virtual RenderFrameHost* GetEmbedderFrame() const;
};
} // namespace content
diff --git a/chromium/content/public/browser/browser_thread.h b/chromium/content/public/browser/browser_thread.h
index 247c7405cdb..4e168643596 100644
--- a/chromium/content/public/browser/browser_thread.h
+++ b/chromium/content/public/browser/browser_thread.h
@@ -103,11 +103,30 @@ class CONTENT_EXPORT BrowserThread {
//
// TODO(crbug.com/887407): Replace callsites with PostTaskWithTraits and
// appropriate traits (TBD).
+ //
+ // DEPRECATED(carlscab): This method is deprecated and will go away soon,
+ // consider posting the task with priority BEST_EFFORT. For example:
+ // base::PostTaskWithTraits(
+ // FROM_HERE, {content::BrowserThread::UI, base::TaskPriority::BEST_EFFORT},
+ // base::BindOnce(...));
+ // Or if you need to run in a special TaskRunner by using the
+ // PostBestEffortTask function below
static void PostAfterStartupTask(
const base::Location& from_here,
const scoped_refptr<base::TaskRunner>& task_runner,
base::OnceClosure task);
+ // Posts a |task| to run at BEST_EFFORT priority using an arbitrary
+ // |task_runner| for which we do not control the priority
+ //
+ // This is useful when a task needs to run on |task_runner| (for thread-safety
+ // reasons) but should be delayed until after critical phases (e.g. startup).
+ // TODO(crbug.com/793069): Add support for sequence-funneling and remove this
+ // method.
+ static void PostBestEffortTask(const base::Location& from_here,
+ scoped_refptr<base::TaskRunner> task_runner,
+ base::OnceClosure task);
+
// Callable on any thread. Returns whether the given well-known thread is
// initialized.
static bool IsThreadInitialized(ID identifier) WARN_UNUSED_RESULT;
diff --git a/chromium/content/public/browser/browsing_data_filter_builder.h b/chromium/content/public/browser/browsing_data_filter_builder.h
index fc290d18687..b1f05a4ec38 100644
--- a/chromium/content/public/browser/browsing_data_filter_builder.h
+++ b/chromium/content/public/browser/browsing_data_filter_builder.h
@@ -59,42 +59,40 @@ class CONTENT_EXPORT BrowsingDataFilterBuilder {
virtual void AddRegisterableDomain(const std::string& registrable_domain) = 0;
// Returns true if we're an empty blacklist, where we delete everything.
- virtual bool IsEmptyBlacklist() const = 0;
+ virtual bool IsEmptyBlacklist() = 0;
// Builds a filter that matches URLs that are in the whitelist,
// or aren't in the blacklist.
- virtual base::RepeatingCallback<bool(const GURL&)>
- BuildGeneralFilter() const = 0;
+ virtual base::RepeatingCallback<bool(const GURL&)> BuildGeneralFilter() = 0;
// Builds a filter that can be used with the network service. This uses a Mojo
// struct rather than a predicate function (as used by the rest of the filters
// built by this class) because we need to be able to pass the filter to the
// network service via IPC. Returns nullptr if |IsEmptyBlacklist()| is true.
- virtual network::mojom::ClearDataFilterPtr BuildNetworkServiceFilter()
- const = 0;
+ virtual network::mojom::ClearDataFilterPtr BuildNetworkServiceFilter() = 0;
// Builds a CookieDeletionInfo object that matches cookies whose sources are
// in the whitelist, or aren't in the blacklist.
- virtual network::mojom::CookieDeletionFilterPtr BuildCookieDeletionFilter()
- const = 0;
+ virtual network::mojom::CookieDeletionFilterPtr
+ BuildCookieDeletionFilter() = 0;
// Builds a filter that matches the |site| of a plugin.
virtual base::RepeatingCallback<bool(const std::string& site)>
- BuildPluginFilter() const = 0;
+ BuildPluginFilter() = 0;
// A convenience method to produce an empty blacklist, a filter that matches
// everything.
static base::Callback<bool(const GURL&)> BuildNoopFilter();
// The mode of the filter.
- virtual Mode GetMode() const = 0;
+ virtual Mode GetMode() = 0;
// Create a new filter builder with the same set of origins, set of domains,
// and mode.
- virtual std::unique_ptr<BrowsingDataFilterBuilder> Copy() const = 0;
+ virtual std::unique_ptr<BrowsingDataFilterBuilder> Copy() = 0;
// Comparison.
- virtual bool operator==(const BrowsingDataFilterBuilder& other) const = 0;
+ virtual bool operator==(const BrowsingDataFilterBuilder& other) = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/browsing_data_remover.h b/chromium/content/public/browser/browsing_data_remover.h
index 6708519017e..638958972b0 100644
--- a/chromium/content/public/browser/browsing_data_remover.h
+++ b/chromium/content/public/browser/browsing_data_remover.h
@@ -89,7 +89,6 @@ class BrowsingDataRemover {
// Other datatypes.
DATA_TYPE_COOKIES = 1 << 8,
- DATA_TYPE_CHANNEL_IDS = 1 << 9,
DATA_TYPE_CACHE = 1 << 10,
DATA_TYPE_DOWNLOADS = 1 << 11,
DATA_TYPE_MEDIA_LICENSES = 1 << 12,
@@ -99,7 +98,7 @@ class BrowsingDataRemover {
DATA_TYPE_NO_CHECKS = 1 << 13,
// AVOID_CLOSING_CONNECTIONS is a pseudo-datatype indicating that when
- // deleting COOKIES and CHANNEL IDs, BrowsingDataRemover should skip
+ // deleting COOKIES, BrowsingDataRemover should skip
// storage backends whose deletion would cause closing network connections.
// TODO(crbug.com/798760): Remove when fixed.
DATA_TYPE_AVOID_CLOSING_CONNECTIONS = 1 << 15,
diff --git a/chromium/content/public/browser/browsing_data_remover_delegate.h b/chromium/content/public/browser/browsing_data_remover_delegate.h
index 108145717b2..bcb9f979588 100644
--- a/chromium/content/public/browser/browsing_data_remover_delegate.h
+++ b/chromium/content/public/browser/browsing_data_remover_delegate.h
@@ -39,19 +39,18 @@ class BrowsingDataRemoverDelegate {
// parameter containing ONLY embedder-defined origin types, and must be able
// to handle ALL embedder-defined typed. It must be static and support
// being called on the UI and IO thread.
- virtual EmbedderOriginTypeMatcher GetOriginTypeMatcher() const = 0;
+ virtual EmbedderOriginTypeMatcher GetOriginTypeMatcher() = 0;
// Whether the embedder allows the removal of download history.
- virtual bool MayRemoveDownloadHistory() const = 0;
+ virtual bool MayRemoveDownloadHistory() = 0;
// Removes embedder-specific data.
- virtual void RemoveEmbedderData(
- const base::Time& delete_begin,
- const base::Time& delete_end,
- int remove_mask,
- const BrowsingDataFilterBuilder& filter_builder,
- int origin_type_mask,
- base::OnceClosure callback) = 0;
+ virtual void RemoveEmbedderData(const base::Time& delete_begin,
+ const base::Time& delete_end,
+ int remove_mask,
+ BrowsingDataFilterBuilder* filter_builder,
+ int origin_type_mask,
+ base::OnceClosure callback) = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/cache_storage_context.h b/chromium/content/public/browser/cache_storage_context.h
index 81205ba6939..50d28203ddd 100644
--- a/chromium/content/public/browser/cache_storage_context.h
+++ b/chromium/content/public/browser/cache_storage_context.h
@@ -24,7 +24,7 @@ class CacheStorageContext
base::OnceCallback<void(const std::vector<StorageUsageInfo>& usage_info)>;
// Methods used in response to browsing data and quota manager requests.
- // Must be called on the IO thread.
+ // May be called on any sequence.
virtual void GetAllOriginsInfo(GetUsageInfoCallback callback) = 0;
virtual void DeleteForOrigin(const GURL& origin_url) = 0;
diff --git a/chromium/content/public/browser/child_process_termination_info.h b/chromium/content/public/browser/child_process_termination_info.h
index 633ac786fa6..7957a114fd3 100644
--- a/chromium/content/public/browser/child_process_termination_info.h
+++ b/chromium/content/public/browser/child_process_termination_info.h
@@ -58,6 +58,12 @@ struct CONTENT_EXPORT ChildProcessTerminationInfo {
int remaining_process_with_strong_binding = 0;
int remaining_process_with_moderate_binding = 0;
int remaining_process_with_waived_binding = 0;
+
+ // Eg lowest ranked process at time of death should have value 0.
+ // Valid values are non-negative.
+ // -1 means could not be obtained due to threading restrictions.
+ // -2 means not applicable because process is not ranked.
+ int best_effort_reverse_rank = -1;
#endif
};
diff --git a/chromium/content/public/browser/delegate_to_browser_gpu_service_accelerator_factory.h b/chromium/content/public/browser/chromeos/delegate_to_browser_gpu_service_accelerator_factory.h
index 7dfee02211e..46f10decfd6 100644
--- a/chromium/content/public/browser/delegate_to_browser_gpu_service_accelerator_factory.h
+++ b/chromium/content/public/browser/chromeos/delegate_to_browser_gpu_service_accelerator_factory.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_PUBLIC_BROWSER_DELEGATE_TO_BROWSER_GPU_SERVICE_ACCELERATOR_FACTORY_H_
-#define CONTENT_PUBLIC_BROWSER_DELEGATE_TO_BROWSER_GPU_SERVICE_ACCELERATOR_FACTORY_H_
+#ifndef CONTENT_PUBLIC_BROWSER_CHROMEOS_DELEGATE_TO_BROWSER_GPU_SERVICE_ACCELERATOR_FACTORY_H_
+#define CONTENT_PUBLIC_BROWSER_CHROMEOS_DELEGATE_TO_BROWSER_GPU_SERVICE_ACCELERATOR_FACTORY_H_
#include "content/common/content_export.h"
#include "services/video_capture/public/mojom/device_factory_provider.mojom.h"
@@ -17,9 +17,10 @@ class CONTENT_EXPORT DelegateToBrowserGpuServiceAcceleratorFactory
: public video_capture::mojom::AcceleratorFactory {
public:
void CreateJpegDecodeAccelerator(
- media::mojom::MjpegDecodeAcceleratorRequest jda_request) override;
+ chromeos_camera::mojom::MjpegDecodeAcceleratorRequest jda_request)
+ override;
};
} // namespace content
-#endif // CONTENT_PUBLIC_BROWSER_DELEGATE_TO_BROWSER_GPU_SERVICE_ACCELERATOR_FACTORY_H_
+#endif // CONTENT_PUBLIC_BROWSER_CHROMEOS_DELEGATE_TO_BROWSER_GPU_SERVICE_ACCELERATOR_FACTORY_H_
diff --git a/chromium/content/public/browser/content_browser_client.cc b/chromium/content/public/browser/content_browser_client.cc
index 445e1febebe..42247de8ab1 100644
--- a/chromium/content/public/browser/content_browser_client.cc
+++ b/chromium/content/public/browser/content_browser_client.cc
@@ -14,6 +14,7 @@
#include "build/build_config.h"
#include "content/public/browser/authenticator_request_client_delegate.h"
#include "content/public/browser/browser_accessibility_state.h"
+#include "content/public/browser/browser_main_parts.h"
#include "content/public/browser/client_certificate_delegate.h"
#include "content/public/browser/login_delegate.h"
#include "content/public/browser/navigation_ui_data.h"
@@ -51,7 +52,7 @@ void OverrideOnBindInterface(const service_manager::BindSourceInfo& remote_info,
handle);
}
-BrowserMainParts* ContentBrowserClient::CreateBrowserMainParts(
+std::unique_ptr<BrowserMainParts> ContentBrowserClient::CreateBrowserMainParts(
const MainFunctionParams& parameters) {
return nullptr;
}
@@ -279,9 +280,8 @@ std::string ContentBrowserClient::GetAcceptLangs(BrowserContext* context) {
return std::string();
}
-const gfx::ImageSkia* ContentBrowserClient::GetDefaultFavicon() {
- static gfx::ImageSkia* empty = new gfx::ImageSkia();
- return empty;
+gfx::ImageSkia ContentBrowserClient::GetDefaultFavicon() {
+ return gfx::ImageSkia();
}
base::FilePath ContentBrowserClient::GetLoggingFileName(
@@ -423,7 +423,7 @@ void ContentBrowserClient::AllowCertificateError(
int cert_error,
const net::SSLInfo& ssl_info,
const GURL& request_url,
- ResourceType resource_type,
+ bool is_main_frame_request,
bool strict_enforcement,
bool expired_previous_decision,
const base::Callback<void(CertificateRequestResultType)>& callback) {
@@ -652,9 +652,9 @@ ContentBrowserClient::GetReceiverPresentationServiceDelegate(
void ContentBrowserClient::OpenURL(
content::SiteInstance* site_instance,
const content::OpenURLParams& params,
- const base::Callback<void(content::WebContents*)>& callback) {
+ base::OnceCallback<void(content::WebContents*)> callback) {
DCHECK(site_instance);
- callback.Run(nullptr);
+ std::move(callback).Run(nullptr);
}
std::string ContentBrowserClient::GetMetricSuffixForURL(const GURL& url) {
@@ -688,27 +688,13 @@ base::string16 ContentBrowserClient::GetAppContainerSidForSandboxType(
}
#endif // defined(OS_WIN)
-ContentBrowserClient::OutOfProcessServiceInfo::OutOfProcessServiceInfo() =
- default;
+void ContentBrowserClient::RunServiceInstance(
+ const service_manager::Identity& identity,
+ mojo::PendingReceiver<service_manager::mojom::Service>* receiver) {}
-ContentBrowserClient::OutOfProcessServiceInfo::OutOfProcessServiceInfo(
- const ProcessNameCallback& process_name_callback)
- : process_name_callback(process_name_callback) {}
-
-ContentBrowserClient::OutOfProcessServiceInfo::OutOfProcessServiceInfo(
- const ProcessNameCallback& process_name_callback,
- const std::string& process_group)
- : process_name_callback(process_name_callback),
- process_group(process_group) {
- DCHECK(!process_group.empty());
-}
-
-ContentBrowserClient::OutOfProcessServiceInfo::~OutOfProcessServiceInfo() =
- default;
-
-void ContentBrowserClient::HandleServiceRequest(
- const std::string& service_name,
- service_manager::mojom::ServiceRequest request) {}
+void ContentBrowserClient::RunServiceInstanceOnIOThread(
+ const service_manager::Identity& identity,
+ mojo::PendingReceiver<service_manager::mojom::Service>* receiver) {}
bool ContentBrowserClient::ShouldTerminateOnServiceQuit(
const service_manager::Identity& id) {
@@ -733,11 +719,6 @@ std::vector<std::string> ContentBrowserClient::GetStartupServices() {
return nullptr;
}
-std::unique_ptr<base::ThreadPool::InitParams>
-ContentBrowserClient::GetThreadPoolInitParams() {
- return nullptr;
-}
-
std::vector<std::unique_ptr<URLLoaderThrottle>>
ContentBrowserClient::CreateURLLoaderThrottles(
const network::ResourceRequest& request,
@@ -771,6 +752,12 @@ bool ContentBrowserClient::WillCreateURLLoaderFactory(
return false;
}
+#if defined(OS_ANDROID)
+void ContentBrowserClient::WillCreateURLLoaderFactoryForAppCacheSubresource(
+ int render_process_id,
+ network::mojom::URLLoaderFactoryPtrInfo* factory_ptr_info) {}
+#endif
+
void ContentBrowserClient::WillCreateWebSocket(
RenderFrameHost* frame,
network::mojom::WebSocketRequest* request,
@@ -899,8 +886,6 @@ bool ContentBrowserClient::HandleExternalProtocol(
bool is_main_frame,
ui::PageTransition page_transition,
bool has_user_gesture,
- const std::string& method,
- const net::HttpRequestHeaders& headers,
network::mojom::URLLoaderFactoryRequest* factory_request,
network::mojom::URLLoaderFactory*& out_factory) {
return true;
@@ -964,6 +949,10 @@ blink::UserAgentMetadata ContentBrowserClient::GetUserAgentMetadata() const {
return blink::UserAgentMetadata();
}
+base::Optional<gfx::ImageSkia> ContentBrowserClient::GetProductLogo() const {
+ return base::nullopt;
+}
+
bool ContentBrowserClient::IsBuiltinComponent(BrowserContext* browser_context,
const url::Origin& origin) {
return false;
@@ -987,9 +976,28 @@ ContentBrowserClient::GetWideColorGamutHeuristic() const {
}
#endif
-base::flat_set<std::string> ContentBrowserClient::GetMimeHandlerViewMimeTypes(
+base::flat_set<std::string>
+ContentBrowserClient::GetPluginMimeTypesWithExternalHandlers(
ResourceContext* resource_context) {
return base::flat_set<std::string>();
}
+void ContentBrowserClient::AugmentNavigationDownloadPolicy(
+ const WebContents* web_contents,
+ const RenderFrameHost* frame_host,
+ bool user_gesture,
+ NavigationDownloadPolicy* download_policy) const {}
+
+bool ContentBrowserClient::IsBluetoothScanningBlocked(
+ content::BrowserContext* browser_context,
+ const url::Origin& requesting_origin,
+ const url::Origin& embedding_origin) const {
+ return false;
+}
+
+void ContentBrowserClient::BlockBluetoothScanning(
+ content::BrowserContext* browser_context,
+ const url::Origin& requesting_origin,
+ const url::Origin& embedding_origin) const {}
+
} // namespace content
diff --git a/chromium/content/public/browser/content_browser_client.h b/chromium/content/public/browser/content_browser_client.h
index 39174b67d1d..a2ef727d3a6 100644
--- a/chromium/content/public/browser/content_browser_client.h
+++ b/chromium/content/public/browser/content_browser_client.h
@@ -33,6 +33,7 @@
#include "content/public/browser/quota_permission_context.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/navigation_policy.h"
#include "content/public/common/previews_state.h"
#include "content/public/common/resource_type.h"
#include "content/public/common/socket_permission_request.h"
@@ -41,12 +42,14 @@
#include "media/cdm/cdm_proxy.h"
#include "media/media_buildflags.h"
#include "media/mojo/interfaces/remoting.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "net/base/mime_util.h"
#include "net/cookies/canonical_cookie.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/websocket.mojom-forward.h"
#include "services/service_manager/public/cpp/binder_registry.h"
+#include "services/service_manager/public/cpp/identity.h"
#include "services/service_manager/public/cpp/manifest.h"
#include "services/service_manager/public/mojom/service.mojom-forward.h"
#include "services/service_manager/sandbox/sandbox_type.h"
@@ -62,6 +65,7 @@
#include "ui/accessibility/ax_mode.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
+#include "ui/gfx/image/image_skia.h"
#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || defined(OS_FUCHSIA)
#include "base/posix/global_descriptors.h"
@@ -91,10 +95,6 @@ namespace device {
class LocationProvider;
}
-namespace gfx {
-class ImageSkia;
-}
-
namespace media {
class AudioLogFactory;
class AudioManager;
@@ -122,7 +122,6 @@ class ClientCertIdentity;
using ClientCertIdentityList = std::vector<std::unique_ptr<ClientCertIdentity>>;
class ClientCertStore;
class CookieStore;
-class HttpRequestHeaders;
class NetLog;
class SSLCertRequestInfo;
class SSLInfo;
@@ -179,7 +178,6 @@ class RenderProcessHost;
class RenderViewHost;
class ResourceContext;
class SerialDelegate;
-class ServiceManagerConnection;
class SiteInstance;
class SpeechRecognitionManagerDelegate;
class StoragePartition;
@@ -217,7 +215,7 @@ class CONTENT_EXPORT ContentBrowserClient {
// Allows the embedder to set any number of custom BrowserMainParts
// implementations for the browser startup code. See comments in
// browser_main_parts.h.
- virtual BrowserMainParts* CreateBrowserMainParts(
+ virtual std::unique_ptr<BrowserMainParts> CreateBrowserMainParts(
const MainFunctionParams& parameters);
// Allows the embedder to change the default behavior of
@@ -410,10 +408,12 @@ class CONTENT_EXPORT ContentBrowserClient {
// Allows the embedder to override parameters when navigating. Called for both
// opening new URLs and when transferring URLs across processes.
- virtual void OverrideNavigationParams(SiteInstance* site_instance,
- ui::PageTransition* transition,
- bool* is_renderer_initiated,
- content::Referrer* referrer) {}
+ virtual void OverrideNavigationParams(
+ SiteInstance* site_instance,
+ ui::PageTransition* transition,
+ bool* is_renderer_initiated,
+ content::Referrer* referrer,
+ base::Optional<url::Origin>* initiator_origin) {}
// Temporary hack to determine whether to skip OOPIFs on the new tab page.
// TODO(creis): Remove when https://crbug.com/566091 is fixed.
@@ -525,8 +525,8 @@ class CONTENT_EXPORT ContentBrowserClient {
// (Not called GetAcceptLanguages so it doesn't clash with win32).
virtual std::string GetAcceptLangs(BrowserContext* context);
- // Returns the default favicon. The callee doesn't own the given bitmap.
- virtual const gfx::ImageSkia* GetDefaultFavicon();
+ // Returns the default favicon.
+ virtual gfx::ImageSkia GetDefaultFavicon();
// Returns the fully qualified path to the log file name, or an empty path.
// This function is used by the sandbox to allow write access to the log.
@@ -763,7 +763,7 @@ class CONTENT_EXPORT ContentBrowserClient {
int cert_error,
const net::SSLInfo& ssl_info,
const GURL& request_url,
- ResourceType resource_type,
+ bool is_main_frame_request,
bool strict_enforcement,
bool expired_previous_decision,
const base::Callback<void(CertificateRequestResultType)>& callback);
@@ -1002,56 +1002,34 @@ class CONTENT_EXPORT ContentBrowserClient {
const std::string& interface_name,
mojo::ScopedMessagePipeHandle* interface_pipe) {}
- // Registers services to be run in the browser process. |connection| is the
- // ServiceManagerConnection service are registered with. Use
- // |ServiceManagerConnection::AddServiceRequestHandler| to register each
- // service.
- //
- // NOTE: This should ONLY be overridden to register services which MUST run on
- // the IO thread. For other in-process services, use |HandleServiceRequest|
- // below.
- virtual void RegisterIOThreadServiceHandlers(
- ServiceManagerConnection* connection) {}
-
virtual void OverrideOnBindInterface(
const service_manager::BindSourceInfo& remote_info,
const std::string& name,
mojo::ScopedMessagePipeHandle* handle) {}
- using ProcessNameCallback = base::RepeatingCallback<base::string16()>;
-
- struct CONTENT_EXPORT OutOfProcessServiceInfo {
- OutOfProcessServiceInfo();
- OutOfProcessServiceInfo(const ProcessNameCallback& process_name_callback);
- OutOfProcessServiceInfo(const ProcessNameCallback& process_name_callback,
- const std::string& process_group);
- ~OutOfProcessServiceInfo();
-
- // The callback function to get the display name of the service process
- // launched for the service.
- ProcessNameCallback process_name_callback;
+ // Called just before the Service Manager is initialized.
+ virtual void WillStartServiceManager() {}
- // If provided, a string which groups this service into a process shared
- // by other services using the same string.
- base::Optional<std::string> process_group;
- };
-
- using OutOfProcessServiceMap = std::map<std::string, OutOfProcessServiceInfo>;
-
- // Registers services to be loaded out of the browser process in an
- // utility process. The value of each map entry should be a process name,
- // to use for the service's host process when launched.
- virtual void RegisterOutOfProcessServices(OutOfProcessServiceMap* services) {}
+ // Handles a service instance request for a new service instance with identity
+ // |identity|. If the client knows how to run the named service, it should
+ // bind |*receiver| accordingly, in the browser process.
+ //
+ // Note that this runs on the main thread, so if a service may need to start
+ // and run on the IO thread while the main thread is blocking on something,
+ // the service request should instead be handled by
+ // |RunServiceInstanceOnIOThread| below.
+ virtual void RunServiceInstance(
+ const service_manager::Identity& identity,
+ mojo::PendingReceiver<service_manager::mojom::Service>* receiver);
- // Handles a Service request for the service named |service_name|. If the
- // client knows how to run |service_name|, it should bind |request|
- // accordingly. Note that this runs on the main thread, so if a service may
- // need to start and run on the IO thread while the main thread is blocking on
- // something, the service should instead by registered in
- // |RegisterIOThreadServiceHandlers| above.
- virtual void HandleServiceRequest(
- const std::string& service_name,
- service_manager::mojom::ServiceRequest request);
+ // Handles an incoming service instance request on the IO thread.
+ //
+ // NOTE: This should ONLY be overridden to register services which MUST run on
+ // the browser's IO thread. For other in-process services, use
+ // |RunServiceInstance| above.
+ virtual void RunServiceInstanceOnIOThread(
+ const service_manager::Identity& identity,
+ mojo::PendingReceiver<service_manager::mojom::Service>* receiver);
// Allows the embedder to terminate the browser if a specific service instance
// quits or crashes.
@@ -1100,7 +1078,7 @@ class CONTENT_EXPORT ContentBrowserClient {
// invoked with the appropriate WebContents* when available.
virtual void OpenURL(SiteInstance* site_instance,
const OpenURLParams& params,
- const base::Callback<void(WebContents*)>& callback);
+ base::OnceCallback<void(WebContents*)> callback);
// Allows the embedder to record |metric| for a specific |url|.
virtual void RecordURLMetric(const std::string& metric, const GURL& url) {}
@@ -1181,11 +1159,6 @@ class CONTENT_EXPORT ContentBrowserClient {
// Returns the RapporService from the browser process.
virtual ::rappor::RapporService* GetRapporService();
- // Provides parameters for initializing the global thread pool. Default
- // params are used if this returns nullptr.
- virtual std::unique_ptr<base::ThreadPool::InitParams>
- GetThreadPoolInitParams();
-
// Allows the embedder to register one or more URLLoaderThrottles for a
// navigation request.
// This is called both when the network service is enabled and disabled.
@@ -1265,6 +1238,19 @@ class CONTENT_EXPORT ContentBrowserClient {
network::mojom::TrustedURLLoaderHeaderClientPtrInfo* header_client,
bool* bypass_redirect_checks);
+#if defined(OS_ANDROID)
+ // Similar to WillCreateURLLoaderFactory but for appcache subresources.
+ // WillCreateURLLoaderFactory couldn't be used because when the appcache
+ // URLLoaderFactory is sent on the UI thread, the URLLoaderFactoryRequest is
+ // already consumed. And on the IO thread when it's created but before it's
+ // consumed, we don't have the process ID.
+ // This is behind an OS_ANDROID ifdef because we don't need this on desktop.
+ // Only WebView should implement this, see https://crbug.com/977873.
+ virtual void WillCreateURLLoaderFactoryForAppCacheSubresource(
+ int render_process_id,
+ network::mojom::URLLoaderFactoryPtrInfo* factory_ptr_info);
+#endif
+
// Allows the embedder to intercept a WebSocket connection. |*request|
// is always valid upon entry and MUST be valid upon return. The embedder
// may swap out the value of |*request| for its own.
@@ -1380,11 +1366,11 @@ class CONTENT_EXPORT ContentBrowserClient {
int /* render_process_id */,
int /* render_frame_id */)> callback);
- // Returns whether a base::ThreadPool should be created when
+ // Returns whether a base::ThreadPoolInstance should be created when
// BrowserMainLoop starts.
// If false, a thread pool has been created by the embedder, and
// BrowserMainLoop should skip creating a second one.
- // Note: the embedder should *not* start the ThreadPool for
+ // Note: the embedder should *not* start the ThreadPoolInstance for
// BrowserMainLoop, BrowserMainLoop itself is responsible for that.
virtual bool ShouldCreateThreadPool();
@@ -1461,8 +1447,6 @@ class CONTENT_EXPORT ContentBrowserClient {
bool is_main_frame,
ui::PageTransition page_transition,
bool has_user_gesture,
- const std::string& method,
- const net::HttpRequestHeaders& headers,
network::mojom::URLLoaderFactoryRequest* factory_request,
network::mojom::URLLoaderFactory*& out_factory);
@@ -1539,6 +1523,10 @@ class CONTENT_EXPORT ContentBrowserClient {
// Returns user agent metadata. Content may cache this value.
virtual blink::UserAgentMetadata GetUserAgentMetadata() const;
+ // Returns a 256x256 transparent background image of the product logo, i.e.
+ // the browser icon, if available.
+ virtual base::Optional<gfx::ImageSkia> GetProductLogo() const;
+
// Returns whether |origin| should be considered a integral component similar
// to native code, and as such whether its log messages should be recorded.
virtual bool IsBuiltinComponent(BrowserContext* browser_context,
@@ -1566,9 +1554,29 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual WideColorGamutHeuristic GetWideColorGamutHeuristic() const;
#endif
- // Obtains the list of MIME types that are handled by a MimeHandlerView.
- virtual base::flat_set<std::string> GetMimeHandlerViewMimeTypes(
+ // Obtains the list of MIME types that are for plugins with external handlers.
+ virtual base::flat_set<std::string> GetPluginMimeTypesWithExternalHandlers(
ResourceContext* resource_context);
+
+ // Possibly augment |download_policy| based on the status of |frame_host| as
+ // well as |user_gesture|.
+ virtual void AugmentNavigationDownloadPolicy(
+ const WebContents* web_contents,
+ const RenderFrameHost* frame_host,
+ bool user_gesture,
+ NavigationDownloadPolicy* download_policy) const;
+
+ // Returns whether a site is blocked to use Bluetooth scanning API.
+ virtual bool IsBluetoothScanningBlocked(
+ content::BrowserContext* browser_context,
+ const url::Origin& requesting_origin,
+ const url::Origin& embedding_origin) const;
+
+ // Blocks a site to use Bluetooth scanning API.
+ virtual void BlockBluetoothScanning(
+ content::BrowserContext* browser_context,
+ const url::Origin& requesting_origin,
+ const url::Origin& embedding_origin) const;
};
} // namespace content
diff --git a/chromium/content/public/browser/cookie_store_factory.h b/chromium/content/public/browser/cookie_store_factory.h
index c459156bd3b..300160e23c5 100644
--- a/chromium/content/public/browser/cookie_store_factory.h
+++ b/chromium/content/public/browser/cookie_store_factory.h
@@ -18,7 +18,6 @@ class SequencedTaskRunner;
}
namespace net {
-class ChannelIDService;
class CookieCryptoDelegate;
class CookieStore;
class NetLog;
@@ -61,11 +60,6 @@ struct CONTENT_EXPORT CookieStoreConfig {
// config.
net::CookieCryptoDelegate* crypto_delegate;
- // Provides the cookie store with a pointer to the corresponding
- // ChannelIDService that should be used with that cookie store. The
- // ChannelIDService must outlive any cookie store created with this config.
- net::ChannelIDService* channel_id_service;
-
// Callbacks for data load events will be performed on |client_task_runner|.
// If nullptr, uses the task runner for BrowserThread::IO.
//
diff --git a/chromium/content/public/browser/devtools_background_services_context.h b/chromium/content/public/browser/devtools_background_services_context.h
new file mode 100644
index 00000000000..bc479aadf99
--- /dev/null
+++ b/chromium/content/public/browser/devtools_background_services_context.h
@@ -0,0 +1,60 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_DEVTOOLS_BACKGROUND_SERVICES_CONTEXT_H_
+#define CONTENT_PUBLIC_BROWSER_DEVTOOLS_BACKGROUND_SERVICES_CONTEXT_H_
+
+#include <stdint.h>
+#include <map>
+#include <string>
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+
+namespace url {
+class Origin;
+} // namespace url
+
+namespace content {
+
+enum class DevToolsBackgroundService {
+ kBackgroundFetch = 2,
+ kBackgroundSync = 3,
+ kPushMessaging = 4,
+ kNotifications = 5,
+
+ // Keep at the end.
+ kMaxValue = kNotifications,
+};
+
+// This class is responsible for persisting the debugging events for the
+// relevant Web Platform Features.
+class CONTENT_EXPORT DevToolsBackgroundServicesContext {
+ public:
+ DevToolsBackgroundServicesContext() = default;
+ virtual ~DevToolsBackgroundServicesContext() = default;
+
+ // Whether events related to |service| should be recorded.
+ virtual bool IsRecording(DevToolsBackgroundService service) = 0;
+
+ // Logs the event if recording for |service| is enabled.
+ // |event_name| is a description of the event.
+ // |instance_id| is for tracking events related to the same feature instance.
+ // Any additional useful information relating to the feature can be sent via
+ // |event_metadata|. Called from the UI thread.
+ virtual void LogBackgroundServiceEvent(
+ uint64_t service_worker_registration_id,
+ const url::Origin& origin,
+ DevToolsBackgroundService service,
+ const std::string& event_name,
+ const std::string& instance_id,
+ const std::map<std::string, std::string>& event_metadata) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DevToolsBackgroundServicesContext);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_DEVTOOLS_BACKGROUND_SERVICES_CONTEXT_H_
diff --git a/chromium/content/public/browser/devtools_frontend_host.h b/chromium/content/public/browser/devtools_frontend_host.h
index 8eff9783476..824a1f4fe14 100644
--- a/chromium/content/public/browser/devtools_frontend_host.h
+++ b/chromium/content/public/browser/devtools_frontend_host.h
@@ -23,7 +23,8 @@ class RenderFrameHost;
// Note: DevToolsFrontendHost is not supported on Android.
class DevToolsFrontendHost {
public:
- using HandleMessageCallback = base::Callback<void(const std::string&)>;
+ using HandleMessageCallback =
+ base::RepeatingCallback<void(const std::string&)>;
// Creates a new DevToolsFrontendHost for RenderFrameHost where DevTools
// frontend is loaded.
diff --git a/chromium/content/public/browser/download_manager.h b/chromium/content/public/browser/download_manager.h
index 82474b8cb65..2a3db81afc2 100644
--- a/chromium/content/public/browser/download_manager.h
+++ b/chromium/content/public/browser/download_manager.h
@@ -34,6 +34,7 @@
#include "base/callback.h"
#include "base/files/file_path.h"
+#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
#include "components/download/public/common/download_interrupt_reasons.h"
@@ -46,6 +47,7 @@
#include "net/base/net_errors.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "storage/browser/blob/blob_data_handle.h"
+#include "url/origin.h"
class GURL;
@@ -72,7 +74,7 @@ class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data,
// Sets/Gets the delegate for this DownloadManager. The delegate has to live
// past its Shutdown method being called (by the DownloadManager).
virtual void SetDelegate(DownloadManagerDelegate* delegate) = 0;
- virtual DownloadManagerDelegate* GetDelegate() const = 0;
+ virtual DownloadManagerDelegate* GetDelegate() = 0;
// Shutdown the download manager. Content calls this when BrowserContext is
// being destructed. If the embedder needs this to be called earlier, it can
@@ -164,6 +166,7 @@ class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data,
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_referrer_url,
+ const base::Optional<url::Origin>& request_initiator,
const std::string& mime_type,
const std::string& original_mime_type,
base::Time start_time,
@@ -195,20 +198,20 @@ class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data,
DownloadInitializationDependency dependency) = 0;
// Returns if the manager has been initialized and loaded all the data.
- virtual bool IsManagerInitialized() const = 0;
+ virtual bool IsManagerInitialized() = 0;
// The number of in progress (including paused) downloads.
// Performance note: this loops over all items. If profiling finds that this
// is too slow, use an AllDownloadItemNotifier to count in-progress items.
- virtual int InProgressCount() const = 0;
+ virtual int InProgressCount() = 0;
// The number of in progress (including paused) downloads.
// Performance note: this loops over all items. If profiling finds that this
// is too slow, use an AllDownloadItemNotifier to count in-progress items.
// This excludes downloads that are marked as malicious.
- virtual int NonMaliciousInProgressCount() const = 0;
+ virtual int NonMaliciousInProgressCount() = 0;
- virtual BrowserContext* GetBrowserContext() const = 0;
+ virtual BrowserContext* GetBrowserContext() = 0;
// Checks whether downloaded files still exist. Updates state of downloads
// that refer to removed files. The check runs in the background and may
diff --git a/chromium/content/public/browser/download_manager_delegate.cc b/chromium/content/public/browser/download_manager_delegate.cc
index 6aca5afad69..fd0e57473ed 100644
--- a/chromium/content/public/browser/download_manager_delegate.cc
+++ b/chromium/content/public/browser/download_manager_delegate.cc
@@ -44,6 +44,7 @@ bool DownloadManagerDelegate::InterceptDownloadIfApplicable(
const std::string& mime_type,
const std::string& request_origin,
int64_t content_length,
+ bool is_transient,
WebContents* web_contents) {
return false;
}
@@ -53,10 +54,6 @@ bool DownloadManagerDelegate::IsMostRecentDownloadItemAtFilePath(
return true;
}
-bool DownloadManagerDelegate::GenerateFileHash() {
- return false;
-}
-
std::string
DownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
return std::string();
diff --git a/chromium/content/public/browser/download_manager_delegate.h b/chromium/content/public/browser/download_manager_delegate.h
index faeeb685241..fe1d8fadc7d 100644
--- a/chromium/content/public/browser/download_manager_delegate.h
+++ b/chromium/content/public/browser/download_manager_delegate.h
@@ -130,11 +130,9 @@ class CONTENT_EXPORT DownloadManagerDelegate {
const std::string& mime_type,
const std::string& request_origin,
int64_t content_length,
+ bool is_transient,
WebContents* web_contents);
- // Returns true if we need to generate a binary hash for downloads.
- virtual bool GenerateFileHash();
-
// Retrieve the directories to save html pages and downloads to.
virtual void GetSaveDir(BrowserContext* browser_context,
base::FilePath* website_save_dir,
diff --git a/chromium/content/public/browser/favicon_status.cc b/chromium/content/public/browser/favicon_status.cc
index 89fd46d7fd0..0a10179edd5 100644
--- a/chromium/content/public/browser/favicon_status.cc
+++ b/chromium/content/public/browser/favicon_status.cc
@@ -10,7 +10,7 @@
namespace content {
FaviconStatus::FaviconStatus() : valid(false) {
- image = gfx::Image(*GetContentClient()->browser()->GetDefaultFavicon());
+ image = gfx::Image(GetContentClient()->browser()->GetDefaultFavicon());
}
} // namespace content
diff --git a/chromium/content/public/browser/gpu_data_manager.h b/chromium/content/public/browser/gpu_data_manager.h
index 3dfa8220341..46dec9d16c4 100644
--- a/chromium/content/public/browser/gpu_data_manager.h
+++ b/chromium/content/public/browser/gpu_data_manager.h
@@ -22,6 +22,11 @@ struct VideoMemoryUsageStats;
}
namespace content {
+enum GpuProcessKind {
+ GPU_PROCESS_KIND_UNSANDBOXED_NO_GL, // Unsandboxed, no init GL bindings.
+ GPU_PROCESS_KIND_SANDBOXED,
+ GPU_PROCESS_KIND_COUNT
+};
class GpuDataManagerObserver;
@@ -68,7 +73,8 @@ class GpuDataManager {
virtual bool HardwareAccelerationEnabled() const = 0;
// Insert switches into gpu process command line: kUseGL, etc.
- virtual void AppendGpuCommandLine(base::CommandLine* command_line) const = 0;
+ virtual void AppendGpuCommandLine(base::CommandLine* command_line,
+ GpuProcessKind kind) const = 0;
protected:
virtual ~GpuDataManager() {}
diff --git a/chromium/content/public/browser/gpu_utils.cc b/chromium/content/public/browser/gpu_utils.cc
index 8502b829ea7..78dc61c3505 100644
--- a/chromium/content/public/browser/gpu_utils.cc
+++ b/chromium/content/public/browser/gpu_utils.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/single_thread_task_runner.h"
-#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "components/viz/common/features.h"
@@ -26,15 +25,6 @@
namespace {
-bool GetUintFromSwitch(const base::CommandLine* command_line,
- const base::StringPiece& switch_string,
- uint32_t* value) {
- if (!command_line->HasSwitch(switch_string))
- return false;
- std::string switch_value(command_line->GetSwitchValueASCII(switch_string));
- return base::StringToUint(switch_value, value);
-}
-
void RunTaskOnTaskRunner(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const base::Closure& callback) {
@@ -74,14 +64,6 @@ const gpu::GpuPreferences GetGpuPreferencesFromCommandLine() {
gpu_preferences.disable_accelerated_video_encode =
command_line->HasSwitch(switches::kDisableAcceleratedVideoEncode);
#if defined(OS_WIN)
- uint32_t enable_accelerated_vpx_decode_val =
- gpu::GpuPreferences::VPX_VENDOR_MICROSOFT;
- if (GetUintFromSwitch(command_line, switches::kEnableAcceleratedVpxDecode,
- &enable_accelerated_vpx_decode_val)) {
- gpu_preferences.enable_accelerated_vpx_decode =
- static_cast<gpu::GpuPreferences::VpxDecodeVendors>(
- enable_accelerated_vpx_decode_val);
- }
gpu_preferences.enable_low_latency_dxva =
!command_line->HasSwitch(switches::kDisableLowLatencyDxva);
gpu_preferences.enable_zero_copy_dxgi_video =
@@ -93,8 +75,6 @@ const gpu::GpuPreferences GetGpuPreferencesFromCommandLine() {
command_line->HasSwitch(switches::kDisableSoftwareRasterizer);
gpu_preferences.log_gpu_control_list_decisions =
command_line->HasSwitch(switches::kLogGpuControlListDecisions);
- GetUintFromSwitch(command_line, switches::kMaxActiveWebGLContexts,
- &gpu_preferences.max_active_webgl_contexts);
gpu_preferences.gpu_startup_dialog =
command_line->HasSwitch(switches::kGpuStartupDialog);
gpu_preferences.disable_gpu_watchdog =
@@ -118,6 +98,10 @@ const gpu::GpuPreferences GetGpuPreferencesFromCommandLine() {
gpu_preferences.disable_vulkan_fallback_to_gl_for_testing =
command_line->HasSwitch(switches::kDisableVulkanFallbackToGLForTesting);
+#if defined(OS_MACOSX)
+ gpu_preferences.enable_metal = base::FeatureList::IsEnabled(features::kMetal);
+#endif
+
gpu_preferences.enable_gpu_benchmarking_extension =
command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking);
@@ -131,8 +115,7 @@ const gpu::GpuPreferences GetGpuPreferencesFromCommandLine() {
void StopGpuProcess(const base::Closure& callback) {
content::GpuProcessHost::CallOnIO(
- content::GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- false /* force_create */,
+ content::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
base::Bind(&StopGpuProcessImpl,
base::Bind(RunTaskOnTaskRunner,
base::ThreadTaskRunnerHandle::Get(), callback)));
diff --git a/chromium/content/public/browser/indexed_db_context.h b/chromium/content/public/browser/indexed_db_context.h
index 6e42ec2fe95..36bc0d3a111 100644
--- a/chromium/content/public/browser/indexed_db_context.h
+++ b/chromium/content/public/browser/indexed_db_context.h
@@ -28,6 +28,8 @@ struct StorageUsageInfo;
// Represents the per-BrowserContext IndexedDB data.
// Call these methods only via the exposed TaskRunner.
+// Refcounted because this class is used throughout the codebase on different
+// threads.
class IndexedDBContext : public base::RefCountedThreadSafe<IndexedDBContext> {
public:
// Only call the below methods by posting to this TaskRunner.
@@ -51,6 +53,9 @@ class IndexedDBContext : public base::RefCountedThreadSafe<IndexedDBContext> {
// Forget the origins/sizes read from disk.
virtual void ResetCachesForTesting() = 0;
+ // Disables the exit-time deletion of session-only data.
+ virtual void SetForceKeepSessionState() = 0;
+
protected:
friend class base::RefCountedThreadSafe<IndexedDBContext>;
virtual ~IndexedDBContext() {}
diff --git a/chromium/content/public/browser/interstitial_page.h b/chromium/content/public/browser/interstitial_page.h
index da8437e9460..e43373598d2 100644
--- a/chromium/content/public/browser/interstitial_page.h
+++ b/chromium/content/public/browser/interstitial_page.h
@@ -92,11 +92,11 @@ class InterstitialPage {
// notifications (e.g. RenderFrameDeleted). The only sensible use of this
// returned WebContents is to add a WebContentObserver and listen for the
// DidAttachInterstitialPage or DidDetachInterstitialPage notifications.
- virtual WebContents* GetWebContents() const = 0;
+ virtual WebContents* GetWebContents() = 0;
// Gets the RenderFrameHost associated with the interstitial page's main
// frame. May return nullptr if the interstitial is already hidden.
- virtual RenderFrameHost* GetMainFrame() const = 0;
+ virtual RenderFrameHost* GetMainFrame() = 0;
virtual InterstitialPageDelegate* GetDelegateForTesting() = 0;
virtual void DontCreateViewForTesting() = 0;
diff --git a/chromium/content/public/browser/navigation_data.h b/chromium/content/public/browser/navigation_data.h
index f75d3adf30d..d753809ea5d 100644
--- a/chromium/content/public/browser/navigation_data.h
+++ b/chromium/content/public/browser/navigation_data.h
@@ -17,7 +17,7 @@ class NavigationData {
virtual ~NavigationData() {}
// Creates a new NavigationData that is a deep copy of the original
- virtual std::unique_ptr<NavigationData> Clone() const = 0;
+ virtual std::unique_ptr<NavigationData> Clone() = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/navigation_handle.h b/chromium/content/public/browser/navigation_handle.h
index cb60e28bb10..48d6cf290db 100644
--- a/chromium/content/public/browser/navigation_handle.h
+++ b/chromium/content/public/browser/navigation_handle.h
@@ -60,6 +60,8 @@ class CONTENT_EXPORT NavigationHandle {
// WebContents::GetVisibleURL and WebContents::GetLastCommittedURL. For
// example, viewing a page's source navigates to the URL of the page, but the
// virtual URL is prefixed with "view-source:".
+ // Note: The URL of a NavigationHandle can change over its lifetime.
+ // e.g. URLs might be rewritten by the renderer before being committed.
virtual const GURL& GetURL() = 0;
// Returns the SiteInstance that started the request.
@@ -160,7 +162,7 @@ class CONTENT_EXPORT NavigationHandle {
virtual ui::PageTransition GetPageTransition() = 0;
// Returns the NavigationUIData associated with the navigation.
- virtual const NavigationUIData* GetNavigationUIData() = 0;
+ virtual NavigationUIData* GetNavigationUIData() = 0;
// Whether the target URL cannot be handled by the browser's internal protocol
// handlers.
@@ -283,6 +285,9 @@ class CONTENT_EXPORT NavigationHandle {
// Returns true if this navigation was initiated by a form submission.
virtual bool IsFormSubmission() = 0;
+ // Returns true if this navigation was initiated by a link click.
+ virtual bool WasInitiatedByLinkClick() = 0;
+
// Returns true if the target is an inner response of a signed exchange.
virtual bool IsSignedExchangeInnerResponse() = 0;
diff --git a/chromium/content/public/browser/navigation_ui_data.h b/chromium/content/public/browser/navigation_ui_data.h
index 586e4a04fd3..ecbec55aa12 100644
--- a/chromium/content/public/browser/navigation_ui_data.h
+++ b/chromium/content/public/browser/navigation_ui_data.h
@@ -18,7 +18,7 @@ class NavigationUIData {
virtual ~NavigationUIData() {}
// Creates a new NavigationData that is a deep copy of the original.
- virtual std::unique_ptr<NavigationUIData> Clone() const = 0;
+ virtual std::unique_ptr<NavigationUIData> Clone() = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/network_service_instance.h b/chromium/content/public/browser/network_service_instance.h
index 3bed383266d..905385e6893 100644
--- a/chromium/content/public/browser/network_service_instance.h
+++ b/chromium/content/public/browser/network_service_instance.h
@@ -9,6 +9,7 @@
#include "base/callback.h"
#include "base/callback_list.h"
+#include "build/build_config.h"
#include "content/common/content_export.h"
#include "services/network/public/cpp/network_connection_tracker.h"
@@ -49,22 +50,17 @@ CONTENT_EXPORT network::mojom::NetworkService* GetNetworkService();
CONTENT_EXPORT network::mojom::NetworkService* GetNetworkServiceFromConnector(
service_manager::Connector* connector);
-// Registers |handler| to run (on UI thread) after NetworkServicePtr encounters
-// an error. Note that there are no ordering guarantees wrt error handlers for
-// other interfaces (e.g. NetworkContextPtr and/or URLLoaderFactoryPtr).
-//
-// Can only be called on the UI thread. No-op if NetworkService is disabled.
-CONTENT_EXPORT std::unique_ptr<base::CallbackList<void()>::Subscription>
-RegisterNetworkServiceCrashHandler(base::RepeatingClosure handler);
-
// When network service is disabled, returns the in-process NetworkService
// pointer which is used to ease transition to network service.
// Must only be called on the IO thread. Must not be called if the network
// service is enabled.
CONTENT_EXPORT network::NetworkService* GetNetworkServiceImpl();
+// Only on ChromeOS since it's only used there.
+#if defined(OS_CHROMEOS)
// Returns the global NetworkChangeNotifier instance.
CONTENT_EXPORT net::NetworkChangeNotifier* GetNetworkChangeNotifier();
+#endif
// Call |FlushForTesting()| on cached |NetworkServicePtr|. For testing only.
// Must only be called on the UI thread.
diff --git a/chromium/content/public/browser/ns_view_bridge_factory_host.h b/chromium/content/public/browser/ns_view_bridge_factory_host.h
deleted file mode 100644
index f389d0f6ad1..00000000000
--- a/chromium/content/public/browser/ns_view_bridge_factory_host.h
+++ /dev/null
@@ -1,44 +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_PUBLIC_BROWSER_NS_VIEW_BRIDGE_FACTORY_HOST_H_
-#define CONTENT_PUBLIC_BROWSER_NS_VIEW_BRIDGE_FACTORY_HOST_H_
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "content/public/common/ns_view_bridge_factory.mojom.h"
-
-namespace content {
-
-// The host interface to the factory that will instantiate content NSViews
-// (RenderWidgetHostView and WebContentsView) in an app shim process. Each
-// app shim will create an instance of this class for to create windows in
-// its app.
-class CONTENT_EXPORT NSViewBridgeFactoryHost {
- public:
- NSViewBridgeFactoryHost(mojom::NSViewBridgeFactoryAssociatedRequest* request,
- uint64_t host_id);
- ~NSViewBridgeFactoryHost();
-
- // The host id that refers to creating NSViews in the local process, and
- // and accessing directly via pointers (instead of through mojo pipes).
- static const uint64_t kLocalDirectHostId;
-
- // Look up a NSViewBridgeFactoryHost from the host id. This host id can
- // be used (e.g, by views::NativeViewHost) to associate different Cocoa
- // factories that refer to the same app shim process.
- static NSViewBridgeFactoryHost* GetFromHostId(uint64_t host_id);
-
- mojom::NSViewBridgeFactory* GetFactory();
-
- private:
- const uint64_t host_id_;
- mojom::NSViewBridgeFactoryAssociatedPtr factory_;
-
- DISALLOW_COPY_AND_ASSIGN(NSViewBridgeFactoryHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_NS_VIEW_BRIDGE_FACTORY_HOST_H_
diff --git a/chromium/content/public/browser/ns_view_bridge_factory_impl.h b/chromium/content/public/browser/ns_view_bridge_factory_impl.h
deleted file mode 100644
index 0ebebc7a886..00000000000
--- a/chromium/content/public/browser/ns_view_bridge_factory_impl.h
+++ /dev/null
@@ -1,47 +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_PUBLIC_BROWSER_NS_VIEW_BRIDGE_FACTORY_IMPL_H_
-#define CONTENT_PUBLIC_BROWSER_NS_VIEW_BRIDGE_FACTORY_IMPL_H_
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "content/public/common/ns_view_bridge_factory.mojom.h"
-#include "content/public/common/web_contents_ns_view_bridge.mojom.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
-
-namespace content {
-
-// The factory that creates content NSView (RenderWidgetHostView and, if
-// necessary, WebContentsView) instances. This is a singleton object that is
-// to be instantiated in the app shim process.
-class CONTENT_EXPORT NSViewBridgeFactoryImpl
- : public mojom::NSViewBridgeFactory {
- public:
- // Get the singleton instance of this factory for this app shim process.
- static NSViewBridgeFactoryImpl* Get();
- void BindRequest(mojom::NSViewBridgeFactoryAssociatedRequest request);
-
- // mojom::NSViewBridgeFactory:
- void CreateRenderWidgetHostNSViewBridge(
- mojom::StubInterfaceAssociatedPtrInfo client,
- mojom::StubInterfaceAssociatedRequest bridge_request) override;
- void CreateWebContentsNSViewBridge(
- uint64_t view_id,
- mojom::WebContentsNSViewClientAssociatedPtrInfo client,
- mojom::WebContentsNSViewBridgeAssociatedRequest bridge_request) override;
-
- private:
- friend class base::NoDestructor<NSViewBridgeFactoryImpl>;
- NSViewBridgeFactoryImpl();
- ~NSViewBridgeFactoryImpl() override;
-
- mojo::AssociatedBinding<mojom::NSViewBridgeFactory> binding_;
-
- DISALLOW_COPY_AND_ASSIGN(NSViewBridgeFactoryImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_NS_VIEW_BRIDGE_FACTORY_IMPL_H_
diff --git a/chromium/content/public/browser/overlay_window.h b/chromium/content/public/browser/overlay_window.h
index 68d020c8c2c..6e1a8e06fd6 100644
--- a/chromium/content/public/browser/overlay_window.h
+++ b/chromium/content/public/browser/overlay_window.h
@@ -14,10 +14,14 @@ class Rect;
class Size;
}
-namespace ui {
+namespace cc {
class Layer;
}
+namespace viz {
+class SurfaceId;
+}
+
namespace content {
class PictureInPictureWindowController;
@@ -53,7 +57,6 @@ class OverlayWindow {
virtual void Hide() = 0;
virtual bool IsVisible() const = 0;
virtual bool IsAlwaysOnTop() const = 0;
- virtual ui::Layer* GetLayer() = 0;
// Retrieves the window's current bounds, including its window.
virtual gfx::Rect GetBounds() const = 0;
virtual void UpdateVideoSize(const gfx::Size& natural_size) = 0;
@@ -63,13 +66,8 @@ class OverlayWindow {
virtual void SetSkipAdButtonVisibility(bool is_visible) = 0;
virtual void SetNextTrackButtonVisibility(bool is_visible) = 0;
virtual void SetPreviousTrackButtonVisibility(bool is_visible) = 0;
-
- // Retrieves the ui::Layers corresponding to the window and video.
- virtual ui::Layer* GetWindowBackgroundLayer() = 0;
- virtual ui::Layer* GetVideoLayer() = 0;
-
- // Retrieves the bounds of the video.
- virtual gfx::Rect GetVideoBounds() = 0;
+ virtual void SetSurfaceId(const viz::SurfaceId& surface_id) = 0;
+ virtual cc::Layer* GetLayerForTesting() = 0;
private:
DISALLOW_COPY_AND_ASSIGN(OverlayWindow);
diff --git a/chromium/content/public/browser/overscroll_configuration.h b/chromium/content/public/browser/overscroll_configuration.h
index eff32974562..c4262178fda 100644
--- a/chromium/content/public/browser/overscroll_configuration.h
+++ b/chromium/content/public/browser/overscroll_configuration.h
@@ -25,27 +25,15 @@ class CONTENT_EXPORT OverscrollConfig {
kEnabledTouchschreen,
};
- // Specifies an overscroll controller threshold.
- enum class Threshold {
- // Threshold to complete touchpad overscroll, in terms of the percentage of
- // the display size.
- kCompleteTouchpad,
+ // These are percentages of the display size.
+ static const float kCompleteTouchpadThresholdPercent;
+ static const float kCompleteTouchscreenThresholdPercent;
- // Threshold to complete touchscreen overscroll, in terms of the percentage
- // of the display size.
- kCompleteTouchscreen,
-
- // Threshold to start touchpad overscroll, in DIPs.
- kStartTouchpad,
-
- // Threshold to start touchscreen overscroll, in DIPs.
- kStartTouchscreen,
- };
+ static const float kStartTouchpadThresholdDips;
+ static const float kStartTouchscreenThresholdDips;
static PullToRefreshMode GetPullToRefreshMode();
- static float GetThreshold(Threshold threshold);
-
static bool TouchpadOverscrollHistoryNavigationEnabled();
static base::TimeDelta MaxInertialEventsBeforeOverscrollCancellation();
diff --git a/chromium/content/public/browser/permission_controller_delegate.h b/chromium/content/public/browser/permission_controller_delegate.h
index 2ba6de9deec..269d5e70b13 100644
--- a/chromium/content/public/browser/permission_controller_delegate.h
+++ b/chromium/content/public/browser/permission_controller_delegate.h
@@ -31,7 +31,7 @@ class CONTENT_EXPORT PermissionControllerDelegate {
RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
bool user_gesture,
- const base::Callback<void(blink::mojom::PermissionStatus)>& callback) = 0;
+ base::OnceCallback<void(blink::mojom::PermissionStatus)> callback) = 0;
// Requests multiple permissions on behalf of a frame identified by
// render_frame_host.
@@ -48,8 +48,8 @@ class CONTENT_EXPORT PermissionControllerDelegate {
RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
bool user_gesture,
- const base::Callback<void(
- const std::vector<blink::mojom::PermissionStatus>&)>& callback) = 0;
+ base::OnceCallback<void(
+ const std::vector<blink::mojom::PermissionStatus>&)> callback) = 0;
// Returns the permission status of a given requesting_origin/embedding_origin
// tuple. This is not taking a RenderFrameHost because the call might happen
@@ -84,7 +84,8 @@ class CONTENT_EXPORT PermissionControllerDelegate {
content::PermissionType permission,
content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
- const base::Callback<void(blink::mojom::PermissionStatus)>& callback) = 0;
+ base::RepeatingCallback<void(blink::mojom::PermissionStatus)>
+ callback) = 0;
// Unregisters from permission status change notifications.
// The |subscription_id| must match the value returned by the
diff --git a/chromium/content/public/browser/permission_type.h b/chromium/content/public/browser/permission_type.h
index 16c3c2ad4ec..5082c001154 100644
--- a/chromium/content/public/browser/permission_type.h
+++ b/chromium/content/public/browser/permission_type.h
@@ -31,6 +31,7 @@ enum class PermissionType {
PAYMENT_HANDLER = 16,
BACKGROUND_FETCH = 17,
IDLE_DETECTION = 18,
+ PERIODIC_BACKGROUND_SYNC = 19,
// Always keep this at the end.
NUM,
diff --git a/chromium/content/public/browser/picture_in_picture_window_controller.h b/chromium/content/public/browser/picture_in_picture_window_controller.h
index 706b5079299..8ed12997c20 100644
--- a/chromium/content/public/browser/picture_in_picture_window_controller.h
+++ b/chromium/content/public/browser/picture_in_picture_window_controller.h
@@ -39,7 +39,7 @@ class PictureInPictureWindowController {
// Called to notify the controller that the window was requested to be closed
// by the user or the content.
- virtual void Close(bool should_pause_video, bool should_reset_pip_player) = 0;
+ virtual void Close(bool should_pause_video) = 0;
// Called to notify the controller that the window was requested to be closed
// by the content and that initiator should be focused.
diff --git a/chromium/content/public/browser/platform_notification_context.h b/chromium/content/public/browser/platform_notification_context.h
index ee0eb8f3eca..a0eeee57333 100644
--- a/chromium/content/public/browser/platform_notification_context.h
+++ b/chromium/content/public/browser/platform_notification_context.h
@@ -107,10 +107,12 @@ class PlatformNotificationContext
WriteResultCallback callback) = 0;
// Deletes all data associated with |notification_id| belonging to |origin|
- // from the database. |callback| will be invoked with the success status
- // when the operation has completed.
+ // from the database. Closes the notification if |close_notification| is true.
+ // |callback| will be invoked with the success status when the operation has
+ // completed.
virtual void DeleteNotificationData(const std::string& notification_id,
const GURL& origin,
+ bool close_notification,
DeleteResultCallback callback) = 0;
// Checks permissions for all notifications in the database and deletes all
diff --git a/chromium/content/public/browser/push_messaging_service.cc b/chromium/content/public/browser/push_messaging_service.cc
index 2abf1a3d564..f2853b28309 100644
--- a/chromium/content/public/browser/push_messaging_service.cc
+++ b/chromium/content/public/browser/push_messaging_service.cc
@@ -36,10 +36,10 @@ void CallStringCallbackFromIO(
base::BindOnce(callback, result, success, not_found));
}
-void CallClosureFromIO(const base::Closure& callback,
+void CallClosureFromIO(base::OnceClosure callback,
blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, callback);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(callback));
}
void GetUserDataOnIO(
@@ -56,12 +56,12 @@ void GetUserDataOnIO(
void ClearPushSubscriptionIdOnIO(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
int64_t service_worker_registration_id,
- const base::Closure& callback) {
+ base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_worker_context->ClearRegistrationUserData(
service_worker_registration_id, {kPushRegistrationIdServiceWorkerKey},
- base::BindOnce(&CallClosureFromIO, callback));
+ base::BindOnce(&CallClosureFromIO, std::move(callback)));
}
void StorePushSubscriptionOnIOForTesting(
@@ -70,14 +70,14 @@ void StorePushSubscriptionOnIOForTesting(
const GURL& origin,
const std::string& subscription_id,
const std::string& sender_id,
- const base::Closure& callback) {
+ base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_worker_context->StoreRegistrationUserData(
service_worker_registration_id, origin,
{{kPushRegistrationIdServiceWorkerKey, subscription_id},
{kPushSenderIdServiceWorkerKey, sender_id}},
- base::BindOnce(&CallClosureFromIO, callback));
+ base::BindOnce(&CallClosureFromIO, std::move(callback)));
}
scoped_refptr<ServiceWorkerContextWrapper> GetServiceWorkerContext(
@@ -109,13 +109,13 @@ void PushMessagingService::ClearPushSubscriptionId(
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
- const base::Closure& callback) {
+ base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ClearPushSubscriptionIdOnIO,
GetServiceWorkerContext(browser_context, origin),
- service_worker_registration_id, callback));
+ service_worker_registration_id, std::move(callback)));
}
// static
diff --git a/chromium/content/public/browser/push_messaging_service.h b/chromium/content/public/browser/push_messaging_service.h
index 682a856ddb4..7b2a07a51ce 100644
--- a/chromium/content/public/browser/push_messaging_service.h
+++ b/chromium/content/public/browser/push_messaging_service.h
@@ -16,31 +16,28 @@
namespace blink {
namespace mojom {
enum class PermissionStatus;
-}
-} // namespace blink
-
-namespace content {
-
-namespace mojom {
enum class PushRegistrationStatus;
enum class PushUnregistrationReason;
enum class PushUnregistrationStatus;
} // namespace mojom
+struct WebPushSubscriptionOptions;
+} // namespace blink
+
+namespace content {
class BrowserContext;
-struct PushSubscriptionOptions;
// A push service-agnostic interface that the Push API uses for talking to
// push messaging services like GCM. Must only be used on the UI thread.
class CONTENT_EXPORT PushMessagingService {
public:
using RegisterCallback =
- base::Callback<void(const std::string& registration_id,
- const std::vector<uint8_t>& p256dh,
- const std::vector<uint8_t>& auth,
- mojom::PushRegistrationStatus status)>;
+ base::OnceCallback<void(const std::string& registration_id,
+ const std::vector<uint8_t>& p256dh,
+ const std::vector<uint8_t>& auth,
+ blink::mojom::PushRegistrationStatus status)>;
using UnregisterCallback =
- base::Callback<void(mojom::PushUnregistrationStatus)>;
+ base::OnceCallback<void(blink::mojom::PushUnregistrationStatus)>;
using SubscriptionInfoCallback =
base::Callback<void(bool is_valid,
const std::vector<uint8_t>& p256dh,
@@ -61,23 +58,25 @@ class CONTENT_EXPORT PushMessagingService {
// displayed to the user. It's safe to call this method multiple times for
// the same registration information, in which case the existing subscription
// will be returned by the server.
- virtual void SubscribeFromDocument(const GURL& requesting_origin,
- int64_t service_worker_registration_id,
- int renderer_id,
- int render_frame_id,
- const PushSubscriptionOptions& options,
- bool user_gesture,
- const RegisterCallback& callback) = 0;
+ virtual void SubscribeFromDocument(
+ const GURL& requesting_origin,
+ int64_t service_worker_registration_id,
+ int renderer_id,
+ int render_frame_id,
+ const blink::WebPushSubscriptionOptions& options,
+ bool user_gesture,
+ RegisterCallback callback) = 0;
// Subscribe the given |options.sender_info| with the push messaging service.
// The frame is not known so if permission was not previously granted by the
// user this request should fail. It's safe to call this method multiple times
// for the same registration information, in which case the existing
// subscription will be returned by the server.
- virtual void SubscribeFromWorker(const GURL& requesting_origin,
- int64_t service_worker_registration_id,
- const PushSubscriptionOptions& options,
- const RegisterCallback& callback) = 0;
+ virtual void SubscribeFromWorker(
+ const GURL& requesting_origin,
+ int64_t service_worker_registration_id,
+ const blink::WebPushSubscriptionOptions& options,
+ RegisterCallback callback) = 0;
// Retrieves the subscription associated with |origin| and
// |service_worker_registration_id|, validates that the provided
@@ -95,11 +94,11 @@ class CONTENT_EXPORT PushMessagingService {
// Unsubscribe the given |sender_id| from the push messaging service. Locally
// deactivates the subscription, then runs |callback|, then asynchronously
// attempts to unsubscribe with the push service.
- virtual void Unsubscribe(mojom::PushUnregistrationReason reason,
+ virtual void Unsubscribe(blink::mojom::PushUnregistrationReason reason,
const GURL& requesting_origin,
int64_t service_worker_registration_id,
const std::string& sender_id,
- const UnregisterCallback& callback) = 0;
+ UnregisterCallback callback) = 0;
// Returns whether subscriptions that do not mandate user visible UI upon
// receiving a push message are supported. Influences permission request and
@@ -127,7 +126,7 @@ class CONTENT_EXPORT PushMessagingService {
static void ClearPushSubscriptionId(BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
- const base::Closure& callback);
+ base::OnceClosure callback);
// Stores a push subscription in the service worker for the given |origin|.
// Must only be used by tests.
diff --git a/chromium/content/public/browser/remote_cocoa.h b/chromium/content/public/browser/remote_cocoa.h
new file mode 100644
index 00000000000..5506c5e8a1a
--- /dev/null
+++ b/chromium/content/public/browser/remote_cocoa.h
@@ -0,0 +1,29 @@
+// 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_PUBLIC_BROWSER_REMOTE_COCOA_H_
+#define CONTENT_PUBLIC_BROWSER_REMOTE_COCOA_H_
+
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
+
+namespace content {
+
+// Create the NSView for a RenderWidgetHostView or WebContentsView. This is
+// called in the app shim process through an interface in remote_cocoa. These
+// functions should be moved to remote_cocoa, but currently have dependencies on
+// content.
+// https://crbug.com/888290
+void CONTENT_EXPORT CreateRenderWidgetHostNSView(
+ mojo::ScopedInterfaceEndpointHandle host_handle,
+ mojo::ScopedInterfaceEndpointHandle view_request_handle);
+
+void CONTENT_EXPORT CreateWebContentsNSView(
+ uint64_t view_id,
+ mojo::ScopedInterfaceEndpointHandle host_handle,
+ mojo::ScopedInterfaceEndpointHandle view_request_handle);
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_REMOTE_COCOA_H_
diff --git a/chromium/content/public/browser/render_frame_host.h b/chromium/content/public/browser/render_frame_host.h
index 056aa14bac7..6e92678d431 100644
--- a/chromium/content/public/browser/render_frame_host.h
+++ b/chromium/content/public/browser/render_frame_host.h
@@ -19,7 +19,9 @@
#include "ipc/ipc_sender.h"
#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
+#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
+#include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
#include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom-forward.h"
#include "third_party/blink/public/platform/web_sudden_termination_disabler_type.h"
@@ -159,6 +161,9 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
// of its size.
virtual const base::Optional<gfx::Size>& GetFrameSize() = 0;
+ // Returns the distance from this frame to the root frame.
+ virtual size_t GetFrameDepth() = 0;
+
// Returns true if the frame is out of process.
virtual bool IsCrossProcessSubframe() = 0;
@@ -182,7 +187,7 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
using JavaScriptResultCallback = base::OnceCallback<void(base::Value)>;
// This is the default API to run JavaScript in this frame. This API can only
- // be called on chrome:// or chrome-devtools:// URLs.
+ // be called on chrome:// or devtools:// URLs.
virtual void ExecuteJavaScript(const base::string16& javascript,
JavaScriptResultCallback callback) = 0;
@@ -395,6 +400,12 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
// running renderer, or in case of Network Service connection errors.
virtual void UpdateSubresourceLoaderFactories() = 0;
+ // Returns the type of frame owner element for the FrameTreeNode associated
+ // with this RenderFrameHost (e.g., <iframe>, <object>, etc). Note that it
+ // returns blink::FrameOwnerElementType::kNone if the RenderFrameHost is a
+ // main frame.
+ virtual blink::FrameOwnerElementType GetFrameOwnerElementType() = 0;
+
private:
// This interface should only be implemented inside content.
friend class RenderFrameHostImpl;
diff --git a/chromium/content/public/browser/render_widget_host_view.h b/chromium/content/public/browser/render_widget_host_view.h
index ebe6ae74f31..07d4351d0a8 100644
--- a/chromium/content/public/browser/render_widget_host_view.h
+++ b/chromium/content/public/browser/render_widget_host_view.h
@@ -263,7 +263,9 @@ class CONTENT_EXPORT RenderWidgetHostView {
// Set the last time a tab change starts to be processed for this
// RenderWidgetHostView. Will overwrite any previously stored value.
- virtual void SetLastTabChangeStartTime(base::TimeTicks start_time) = 0;
+ virtual void SetRecordTabSwitchTimeRequest(base::TimeTicks start_time,
+ bool destination_is_loaded,
+ bool destination_is_frozen) = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/resource_dispatcher_host.h b/chromium/content/public/browser/resource_dispatcher_host.h
index eb25debee16..7669ed29c13 100644
--- a/chromium/content/public/browser/resource_dispatcher_host.h
+++ b/chromium/content/public/browser/resource_dispatcher_host.h
@@ -67,10 +67,6 @@ class CONTENT_EXPORT ResourceDispatcherHost {
// delegate have a longer lifetime than the ResourceDispatcherHost.
virtual void SetDelegate(ResourceDispatcherHostDelegate* delegate) = 0;
- // Controls whether third-party sub-content can pop-up HTTP basic auth
- // dialog boxes.
- virtual void SetAllowCrossOriginAuthPrompt(bool value) = 0;
-
// Registers the |interceptor| for the |http_header| passed in.
// The |starts_with| parameter is used to match the prefix of the
// |http_header| in the response and the interceptor will be invoked if there
diff --git a/chromium/content/public/browser/resource_throttle.h b/chromium/content/public/browser/resource_throttle.h
index b1adaca3a39..f0c9c1fb75b 100644
--- a/chromium/content/public/browser/resource_throttle.h
+++ b/chromium/content/public/browser/resource_throttle.h
@@ -58,7 +58,7 @@ class CONTENT_EXPORT ResourceThrottle {
// Returns the name of the throttle, as a UTF-8 C-string, for logging
// purposes. nullptr is not allowed. Caller does *not* take ownership of the
// returned string.
- virtual const char* GetNameForLogging() const = 0;
+ virtual const char* GetNameForLogging() = 0;
// Whether this ResourceThrottle needs to execute WillProcessResponse before
// any part of the response body is read. Normally this is false. This should
diff --git a/chromium/content/public/browser/serial_delegate.h b/chromium/content/public/browser/serial_delegate.h
index aaea94ba3c1..0ea8032bcf8 100644
--- a/chromium/content/public/browser/serial_delegate.h
+++ b/chromium/content/public/browser/serial_delegate.h
@@ -23,12 +23,16 @@ class CONTENT_EXPORT SerialDelegate {
// Shows a chooser for the user to select a serial port. |callback| will be
// run when the prompt is closed. Deleting the returned object will cancel the
- // prompt.
+ // prompt. This method should not be called if CanRequestPortPermission()
+ // below returned false.
virtual std::unique_ptr<SerialChooser> RunChooser(
RenderFrameHost* frame,
std::vector<blink::mojom::SerialPortFilterPtr> filters,
SerialChooser::Callback callback) = 0;
+ // Returns whether |frame| has permission to request access to a port.
+ virtual bool CanRequestPortPermission(RenderFrameHost* frame) = 0;
+
// Returns whether |frame| has permission to access |port|.
virtual bool HasPortPermission(RenderFrameHost* frame,
const device::mojom::SerialPortInfo& port) = 0;
diff --git a/chromium/content/public/browser/session_storage_namespace.h b/chromium/content/public/browser/session_storage_namespace.h
index 7abe623c6de..c41b07fac69 100644
--- a/chromium/content/public/browser/session_storage_namespace.h
+++ b/chromium/content/public/browser/session_storage_namespace.h
@@ -21,13 +21,13 @@ class SessionStorageNamespace
public:
// Returns the ID for the |SessionStorageNamespace|. The ID is unique among
// all SessionStorageNamespace objects and across browser runs.
- virtual const std::string& id() const = 0;
+ virtual const std::string& id() = 0;
// For marking that the sessionStorage will be needed or won't be needed by
// session restore.
virtual void SetShouldPersist(bool should_persist) = 0;
- virtual bool should_persist() const = 0;
+ virtual bool should_persist() = 0;
protected:
friend class base::RefCountedThreadSafe<SessionStorageNamespace>;
diff --git a/chromium/content/public/browser/site_instance.h b/chromium/content/public/browser/site_instance.h
index e3b2796e1d5..a3e880e20e5 100644
--- a/chromium/content/public/browser/site_instance.h
+++ b/chromium/content/public/browser/site_instance.h
@@ -79,6 +79,11 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> {
// Returns a unique ID for this SiteInstance.
virtual int32_t GetId() = 0;
+ // Returns a unique ID for the BrowsingInstance (i.e., group of related
+ // browsing contexts) to which this SiteInstance belongs. This allows callers
+ // to identify which SiteInstances can asynchronously script each other.
+ virtual int32_t GetBrowsingInstanceId() = 0;
+
// Whether this SiteInstance has a running process associated with it.
// This may return true before the first call to GetProcess(), in cases where
// we use process-per-site and there is an existing process available.
@@ -98,7 +103,7 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> {
// Browser context to which this SiteInstance (and all related
// SiteInstances) belongs.
- virtual content::BrowserContext* GetBrowserContext() const = 0;
+ virtual content::BrowserContext* GetBrowserContext() = 0;
// Get the web site that this SiteInstance is rendering pages for. This
// includes the scheme and registered domain, but not the port.
@@ -114,7 +119,7 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> {
// derived from the origin, it only contains the scheme and the eTLD + 1,
// i.e. an origin with the host "deeply.nested.subdomain.example.com"
// corresponds to a site URL with the host "example.com".
- virtual const GURL& GetSiteURL() const = 0;
+ virtual const GURL& GetSiteURL() = 0;
// Gets a SiteInstance for the given URL that shares the current
// BrowsingInstance, creating a new SiteInstance if necessary. This ensures
diff --git a/chromium/content/public/browser/site_isolation_policy.cc b/chromium/content/public/browser/site_isolation_policy.cc
index 52b515f00fb..683579d33ab 100644
--- a/chromium/content/public/browser/site_isolation_policy.cc
+++ b/chromium/content/public/browser/site_isolation_policy.cc
@@ -18,6 +18,7 @@
#include "base/no_destructor.h"
#include "base/strings/string_split.h"
#include "base/timer/timer.h"
+#include "build/build_config.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
@@ -36,10 +37,13 @@ bool IsSiteIsolationDisabled() {
return true;
}
+#if defined(OS_ANDROID)
+ // Desktop platforms no longer support disabling Site Isolation by policy.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableSiteIsolationForPolicy)) {
return true;
}
+#endif
return GetContentClient() &&
GetContentClient()->browser()->ShouldDisableSiteIsolation();
@@ -76,10 +80,6 @@ void SiteIsolationPolicy::PopulateURLLoaderFactoryParamsPtrForCORB(
}
params->is_corb_enabled = true;
- params->corb_detachable_resource_type =
- static_cast<int>(ResourceType::kPrefetch);
- params->corb_excluded_resource_type =
- static_cast<int>(ResourceType::kPluginResource);
}
// static
@@ -102,6 +102,19 @@ bool SiteIsolationPolicy::AreIsolatedOriginsEnabled() {
}
// static
+bool SiteIsolationPolicy::IsStrictOriginIsolationEnabled() {
+ // TODO(wjmaclean): Figure out what should happen when this feature is
+ // combined with --isolate-origins.
+ if (IsSiteIsolationDisabled())
+ return false;
+
+ // The feature needs to be checked last, because checking the feature
+ // activates the field trial and assigns the client either to a control or an
+ // experiment group - such assignment should be final.
+ return base::FeatureList::IsEnabled(features::kStrictOriginIsolation);
+}
+
+// static
bool SiteIsolationPolicy::IsErrorPageIsolationEnabled(bool in_main_frame) {
return GetContentClient()->browser()->ShouldIsolateErrorPage(in_main_frame);
}
diff --git a/chromium/content/public/browser/site_isolation_policy.h b/chromium/content/public/browser/site_isolation_policy.h
index 793b9fb176b..4a6dd8e751d 100644
--- a/chromium/content/public/browser/site_isolation_policy.h
+++ b/chromium/content/public/browser/site_isolation_policy.h
@@ -41,6 +41,10 @@ class CONTENT_EXPORT SiteIsolationPolicy {
// Returns true if isolated origins feature is enabled.
static bool AreIsolatedOriginsEnabled();
+ // Returns true if strict origin isolation is enabled. Controls whether site
+ // isolation uses origins instead of scheme and eTLD+1.
+ static bool IsStrictOriginIsolationEnabled();
+
// Returns true if error page isolation is enabled.
static bool IsErrorPageIsolationEnabled(bool in_main_frame);
diff --git a/chromium/content/public/browser/site_isolation_policy_unittest.cc b/chromium/content/public/browser/site_isolation_policy_unittest.cc
index a3ed6c16cff..cc6f4b2ed70 100644
--- a/chromium/content/public/browser/site_isolation_policy_unittest.cc
+++ b/chromium/content/public/browser/site_isolation_policy_unittest.cc
@@ -4,6 +4,10 @@
#include "content/public/browser/site_isolation_policy.h"
+#include "base/command_line.h"
+#include "base/test/scoped_command_line.h"
+#include "build/build_config.h"
+#include "content/public/common/content_switches.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -45,4 +49,52 @@ TEST(SiteIsolationPolicyTest, ParseIsolatedOrigins) {
url::Origin::Create(GURL("https://b.com:1234"))));
}
+TEST(SiteIsolationPolicyTest, DisableSiteIsolationSwitch) {
+ // Skip this test if the --site-per-process switch is present (e.g. on Site
+ // Isolation Android chromium.fyi bot). The test is still valid if
+ // SitePerProcess is the default (e.g. via ContentBrowserClient's
+ // ShouldEnableStrictSiteIsolation method) - don't skip the test in such case.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess)) {
+ return;
+ }
+
+ base::test::ScopedCommandLine scoped_command_line;
+ base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
+ command_line->AppendSwitch(switches::kDisableSiteIsolation);
+ EXPECT_FALSE(SiteIsolationPolicy::UseDedicatedProcessesForAllSites());
+ EXPECT_FALSE(SiteIsolationPolicy::AreIsolatedOriginsEnabled());
+ EXPECT_FALSE(SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled());
+
+ // Error page isolation should not be affected by --disable-site-isolation-...
+ // switches.
+ EXPECT_TRUE(SiteIsolationPolicy::IsErrorPageIsolationEnabled(true));
+}
+
+#if defined(OS_ANDROID)
+// Since https://crbug.com/910273, the kDisableSiteIsolationForPolicy switch is
+// only available/used on Android.
+TEST(SiteIsolationPolicyTest, DisableSiteIsolationForPolicySwitch) {
+ // Skip this test if the --site-per-process switch is present (e.g. on Site
+ // Isolation Android chromium.fyi bot). The test is still valid if
+ // SitePerProcess is the default (e.g. via ContentBrowserClient's
+ // ShouldEnableStrictSiteIsolation method) - don't skip the test in such case.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess)) {
+ return;
+ }
+
+ base::test::ScopedCommandLine scoped_command_line;
+ base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
+ command_line->AppendSwitch(switches::kDisableSiteIsolationForPolicy);
+ EXPECT_FALSE(SiteIsolationPolicy::UseDedicatedProcessesForAllSites());
+ EXPECT_FALSE(SiteIsolationPolicy::AreIsolatedOriginsEnabled());
+ EXPECT_FALSE(SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled());
+
+ // Error page isolation should not be affected by --disable-site-isolation-...
+ // switches.
+ EXPECT_TRUE(SiteIsolationPolicy::IsErrorPageIsolationEnabled(true));
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/public/browser/sms_service.h b/chromium/content/public/browser/sms_service.h
new file mode 100644
index 00000000000..39e0c999352
--- /dev/null
+++ b/chromium/content/public/browser/sms_service.h
@@ -0,0 +1,32 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_SMS_SERVICE_H_
+#define CONTENT_PUBLIC_BROWSER_SMS_SERVICE_H_
+
+#include "content/common/content_export.h"
+#include "third_party/blink/public/mojom/sms/sms_manager.mojom.h"
+
+namespace url {
+class Origin;
+}
+
+namespace content {
+
+// The interface to be implemented by the browser to mediate between SMS
+// Receiver calls and the underlying operating system.
+// https://github.com/samuelgoto/sms-receiver
+class CONTENT_EXPORT SmsService {
+ public:
+ virtual ~SmsService() {}
+
+ static std::unique_ptr<SmsService> Create();
+
+ virtual void Bind(blink::mojom::SmsManagerRequest request,
+ const url::Origin& origin) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_SMS_SERVICE_H_
diff --git a/chromium/content/public/browser/storage_partition.h b/chromium/content/public/browser/storage_partition.h
index de7455a49e3..c39844feba0 100644
--- a/chromium/content/public/browser/storage_partition.h
+++ b/chromium/content/public/browser/storage_partition.h
@@ -54,6 +54,7 @@ class BackgroundSyncContext;
class BrowserContext;
class CacheStorageContext;
class DOMStorageContext;
+class DevToolsBackgroundServicesContext;
class IndexedDBContext;
class GeneratedCodeCacheContext;
class PlatformNotificationContext;
@@ -111,6 +112,8 @@ class CONTENT_EXPORT StoragePartition {
virtual SharedWorkerService* GetSharedWorkerService() = 0;
virtual CacheStorageContext* GetCacheStorageContext() = 0;
virtual GeneratedCodeCacheContext* GetGeneratedCodeCacheContext() = 0;
+ virtual DevToolsBackgroundServicesContext*
+ GetDevToolsBackgroundServicesContext() = 0;
#if !defined(OS_ANDROID)
virtual HostZoomMap* GetHostZoomMap() = 0;
virtual HostZoomLevelContext* GetHostZoomLevelContext() = 0;
diff --git a/chromium/content/public/browser/tts_controller.h b/chromium/content/public/browser/tts_controller.h
index 82f0ede81e8..b52834495b0 100644
--- a/chromium/content/public/browser/tts_controller.h
+++ b/chromium/content/public/browser/tts_controller.h
@@ -151,6 +151,10 @@ class CONTENT_EXPORT TtsController {
virtual void SetTtsPlatform(TtsPlatform* tts_platform) = 0;
virtual int QueueSize() = 0;
+ virtual void StripSSML(
+ const std::string& utterance,
+ base::OnceCallback<void(const std::string&)> callback) = 0;
+
protected:
virtual ~TtsController() {}
};
diff --git a/chromium/content/public/browser/tts_platform.h b/chromium/content/public/browser/tts_platform.h
index 3f26101add6..74603da2e65 100644
--- a/chromium/content/public/browser/tts_platform.h
+++ b/chromium/content/public/browser/tts_platform.h
@@ -37,11 +37,12 @@ class CONTENT_EXPORT TtsPlatform {
// The TtsController will only try to speak one utterance at
// a time. If it wants to interrupt speech, it will always call Stop
// before speaking again.
- virtual bool Speak(int utterance_id,
+ virtual void Speak(int utterance_id,
const std::string& utterance,
const std::string& lang,
const VoiceData& voice,
- const UtteranceContinuousParameters& params) = 0;
+ const UtteranceContinuousParameters& params,
+ base::OnceCallback<void(bool)> on_speak_finished) = 0;
// Stop speaking immediately and return true on success.
virtual bool StopSpeaking() = 0;
diff --git a/chromium/content/public/browser/url_data_source.h b/chromium/content/public/browser/url_data_source.h
index 22ed30b8c97..4fc97fb57d7 100644
--- a/chromium/content/public/browser/url_data_source.h
+++ b/chromium/content/public/browser/url_data_source.h
@@ -134,7 +134,7 @@ class CONTENT_EXPORT URLDataSource {
// happening, return false. It is OK to return false as needed.
virtual bool ShouldDenyXFrameOptions() const;
- // By default, only chrome: and chrome-devtools: requests are allowed.
+ // By default, only chrome: and devtools: requests are allowed.
// Override in specific WebUI data sources to enable for additional schemes or
// to implement fancier access control. Typically used in concert with
// ContentBrowserClient::GetAdditionalWebUISchemes() to permit additional
@@ -147,7 +147,7 @@ class CONTENT_EXPORT URLDataSource {
// To start sending mime type returned by GetMimeType in HTTP headers,
// return true. It is useful when tunneling response served from this data
// source programmatically. Or when AppCache is enabled for this source as it
- // is for chrome-devtools.
+ // is for devtools.
virtual bool ShouldServeMimeTypeAsContentTypeHeader() const;
// This method is called when the request contains "Origin:" header. The value
diff --git a/chromium/content/public/browser/web_contents_binding_set.cc b/chromium/content/public/browser/web_contents_binding_set.cc
index 0ef198a34af..455a5fea04a 100644
--- a/chromium/content/public/browser/web_contents_binding_set.cc
+++ b/chromium/content/public/browser/web_contents_binding_set.cc
@@ -17,12 +17,14 @@ void WebContentsBindingSet::Binder::OnRequestForFrame(
NOTREACHED();
}
+void WebContentsBindingSet::Binder::CloseAllBindings() {
+ NOTREACHED();
+}
+
WebContentsBindingSet::WebContentsBindingSet(WebContents* web_contents,
- const std::string& interface_name,
- std::unique_ptr<Binder> binder)
+ const std::string& interface_name)
: remove_callback_(static_cast<WebContentsImpl*>(web_contents)
- ->AddBindingSet(interface_name, this)),
- binder_(std::move(binder)) {}
+ ->AddBindingSet(interface_name, this)) {}
WebContentsBindingSet::~WebContentsBindingSet() {
remove_callback_.Run();
@@ -37,20 +39,15 @@ WebContentsBindingSet* WebContentsBindingSet::GetForWebContents(
}
void WebContentsBindingSet::CloseAllBindings() {
- binder_for_testing_.reset();
- binder_.reset();
+ binder_->CloseAllBindings();
+ binder_ = nullptr;
}
void WebContentsBindingSet::OnRequestForFrame(
RenderFrameHost* render_frame_host,
mojo::ScopedInterfaceEndpointHandle handle) {
- if (binder_for_testing_) {
- binder_for_testing_->OnRequestForFrame(render_frame_host,
- std::move(handle));
- return;
- }
- DCHECK(binder_);
- binder_->OnRequestForFrame(render_frame_host, std::move(handle));
+ if (binder_)
+ binder_->OnRequestForFrame(render_frame_host, std::move(handle));
}
} // namespace content
diff --git a/chromium/content/public/browser/web_contents_binding_set.h b/chromium/content/public/browser/web_contents_binding_set.h
index 3d5f0227946..bfe6fcef0b3 100644
--- a/chromium/content/public/browser/web_contents_binding_set.h
+++ b/chromium/content/public/browser/web_contents_binding_set.h
@@ -29,16 +29,16 @@ class CONTENT_EXPORT WebContentsBindingSet {
public:
class CONTENT_EXPORT Binder {
public:
- virtual ~Binder() {}
+ virtual ~Binder() = default;
virtual void OnRequestForFrame(
RenderFrameHost* render_frame_host,
mojo::ScopedInterfaceEndpointHandle handle);
+ virtual void CloseAllBindings();
};
- void SetBinderForTesting(std::unique_ptr<Binder> binder) {
- binder_for_testing_ = std::move(binder);
- }
+ // |binder| must outlive |this| or be reset to null before being destroyed.
+ void SetBinder(Binder* binder) { binder_ = binder; }
template <typename Interface>
static WebContentsBindingSet* GetForWebContents(WebContents* web_contents) {
@@ -47,8 +47,7 @@ class CONTENT_EXPORT WebContentsBindingSet {
protected:
WebContentsBindingSet(WebContents* web_contents,
- const std::string& interface_name,
- std::unique_ptr<Binder> binder);
+ const std::string& interface_name);
~WebContentsBindingSet();
private:
@@ -62,8 +61,7 @@ class CONTENT_EXPORT WebContentsBindingSet {
mojo::ScopedInterfaceEndpointHandle handle);
const base::Closure remove_callback_;
- std::unique_ptr<Binder> binder_;
- std::unique_ptr<Binder> binder_for_testing_;
+ Binder* binder_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(WebContentsBindingSet);
};
@@ -113,22 +111,23 @@ template <typename Interface>
class WebContentsFrameBindingSet : public WebContentsBindingSet {
public:
WebContentsFrameBindingSet(WebContents* web_contents, Interface* impl)
- : WebContentsBindingSet(
- web_contents,
- Interface::Name_,
- std::make_unique<FrameInterfaceBinder>(this, web_contents, impl)) {}
- ~WebContentsFrameBindingSet() {}
+ : WebContentsBindingSet(web_contents, Interface::Name_),
+ binder_(this, web_contents, impl) {
+ SetBinder(&binder_);
+ }
+ ~WebContentsFrameBindingSet() = default;
// Returns the RenderFrameHost currently targeted by a message dispatch to
// this interface. Must only be called during the extent of a message dispatch
// for this interface.
RenderFrameHost* GetCurrentTargetFrame() {
- DCHECK(current_target_frame_);
- return current_target_frame_;
+ if (current_target_frame_for_testing_)
+ return current_target_frame_for_testing_;
+ return binder_.GetCurrentTargetFrame();
}
void SetCurrentTargetFrameForTesting(RenderFrameHost* render_frame_host) {
- current_target_frame_ = render_frame_host;
+ current_target_frame_for_testing_ = render_frame_host;
}
private:
@@ -137,14 +136,15 @@ class WebContentsFrameBindingSet : public WebContentsBindingSet {
FrameInterfaceBinder(WebContentsFrameBindingSet* binding_set,
WebContents* web_contents,
Interface* impl)
- : WebContentsObserver(web_contents), impl_(impl) {
- bindings_.set_pre_dispatch_handler(
- base::Bind(&WebContentsFrameBindingSet::WillDispatchForContext,
- base::Unretained(binding_set)));
- }
+ : WebContentsObserver(web_contents), impl_(impl) {}
+
+ ~FrameInterfaceBinder() override = default;
- ~FrameInterfaceBinder() override {}
+ RenderFrameHost* GetCurrentTargetFrame() {
+ return bindings_.dispatch_context();
+ }
+ private:
// Binder:
void OnRequestForFrame(
RenderFrameHost* render_frame_host,
@@ -155,6 +155,8 @@ class WebContentsFrameBindingSet : public WebContentsBindingSet {
frame_to_bindings_map_[render_frame_host].push_back(id);
}
+ void CloseAllBindings() override { bindings_.CloseAllBindings(); }
+
// WebContentsObserver:
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override {
auto it = frame_to_bindings_map_.find(render_frame_host);
@@ -173,11 +175,8 @@ class WebContentsFrameBindingSet : public WebContentsBindingSet {
DISALLOW_COPY_AND_ASSIGN(FrameInterfaceBinder);
};
- void WillDispatchForContext(RenderFrameHost* const& frame_host) {
- current_target_frame_ = frame_host;
- }
-
- RenderFrameHost* current_target_frame_ = nullptr;
+ FrameInterfaceBinder binder_;
+ RenderFrameHost* current_target_frame_for_testing_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(WebContentsFrameBindingSet);
};
diff --git a/chromium/content/public/browser/web_contents_delegate.cc b/chromium/content/public/browser/web_contents_delegate.cc
index b077a21e537..848f8904839 100644
--- a/chromium/content/public/browser/web_contents_delegate.cc
+++ b/chromium/content/public/browser/web_contents_delegate.cc
@@ -47,7 +47,7 @@ bool WebContentsDelegate::ShouldPreserveAbortedURLs(WebContents* source) {
bool WebContentsDelegate::DidAddMessageToConsole(
WebContents* source,
- int32_t level,
+ blink::mojom::ConsoleMessageLevel log_level,
const base::string16& message,
int32_t line_no,
const base::string16& source_id) {
@@ -143,6 +143,13 @@ std::unique_ptr<BluetoothChooser> WebContentsDelegate::RunBluetoothChooser(
return nullptr;
}
+std::unique_ptr<BluetoothScanningPrompt>
+WebContentsDelegate::ShowBluetoothScanningPrompt(
+ RenderFrameHost* frame,
+ const BluetoothScanningPrompt::EventHandler& event_handler) {
+ return nullptr;
+}
+
bool WebContentsDelegate::EmbedsFullscreenWidget() const {
return false;
}
diff --git a/chromium/content/public/browser/web_contents_delegate.h b/chromium/content/public/browser/web_contents_delegate.h
index 3789137953a..e99b9c52101 100644
--- a/chromium/content/public/browser/web_contents_delegate.h
+++ b/chromium/content/public/browser/web_contents_delegate.h
@@ -17,6 +17,7 @@
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/public/browser/bluetooth_chooser.h"
+#include "content/public/browser/bluetooth_scanning_prompt.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/media_stream_request.h"
#include "content/public/browser/serial_chooser.h"
@@ -195,11 +196,12 @@ class CONTENT_EXPORT WebContentsDelegate {
// A message was added to the console of a frame of the page. Returning true
// indicates that the delegate handled the message. If false is returned the
// default logging mechanism will be used for the message.
- virtual bool DidAddMessageToConsole(WebContents* source,
- int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id);
+ virtual bool DidAddMessageToConsole(
+ WebContents* source,
+ blink::mojom::ConsoleMessageLevel log_level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id);
// Tells us that we've finished firing this tab's beforeunload event.
// The proceed bool tells us whether the user chose to proceed closing the
@@ -396,6 +398,12 @@ class CONTENT_EXPORT WebContentsDelegate {
RenderFrameHost* frame,
const BluetoothChooser::EventHandler& event_handler);
+ // Shows a prompt for the user to allow/block Bluetooth scanning. The
+ // observer must live at least as long as the returned prompt object.
+ virtual std::unique_ptr<BluetoothScanningPrompt> ShowBluetoothScanningPrompt(
+ RenderFrameHost* frame,
+ const BluetoothScanningPrompt::EventHandler& event_handler);
+
// Returns true if the delegate will embed a WebContents-owned fullscreen
// render widget. In this case, the delegate may access the widget by calling
// WebContents::GetFullscreenRenderWidgetHostView(). If false is returned,
diff --git a/chromium/content/public/browser/web_contents_observer.h b/chromium/content/public/browser/web_contents_observer.h
index 68273fe6e3e..da548fd1913 100644
--- a/chromium/content/public/browser/web_contents_observer.h
+++ b/chromium/content/public/browser/web_contents_observer.h
@@ -515,6 +515,9 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener {
// Invoked when the renderer process changes the page scale factor.
virtual void OnPageScaleFactorChanged(float page_scale_factor) {}
+ // Invoked when a paste event occurs.
+ virtual void OnPaste() {}
+
// Invoked if an IPC message is coming from a specific RenderFrameHost.
virtual bool OnMessageReceived(const IPC::Message& message,
RenderFrameHost* render_frame_host);
diff --git a/chromium/content/public/browser/web_ui_data_source.h b/chromium/content/public/browser/web_ui_data_source.h
index bdcfff5bc9c..7a1973a028b 100644
--- a/chromium/content/public/browser/web_ui_data_source.h
+++ b/chromium/content/public/browser/web_ui_data_source.h
@@ -118,14 +118,6 @@ class WebUIDataSource {
const std::string& data) = 0;
virtual void DisableDenyXFrameOptions() = 0;
- // Tells the loading code that resources are gzipped on disk.
- virtual void UseGzip() = 0;
-
- // Same as UseGzip() above, but |is_gzipped_callback| is used to dynamically
- // determine whether a given |const std::string& path| argument is gzipped.
- virtual void UseGzip(base::RepeatingCallback<bool(const std::string&)>
- is_gzipped_callback) = 0;
-
// The |source_name| this WebUIDataSource was created with.
virtual std::string GetSource() const = 0;
};
diff --git a/chromium/content/public/browser/websocket_handshake_request_info.h b/chromium/content/public/browser/websocket_handshake_request_info.h
index def71272d6b..4b34f537c15 100644
--- a/chromium/content/public/browser/websocket_handshake_request_info.h
+++ b/chromium/content/public/browser/websocket_handshake_request_info.h
@@ -19,13 +19,13 @@ class WebSocketHandshakeRequestInfo {
public:
virtual ~WebSocketHandshakeRequestInfo() {}
// Returns the ID of the child process where the WebSocket connection lives.
- virtual int GetChildId() const = 0;
+ virtual int GetChildId() = 0;
// Returns the ID of the renderer frame where the WebSocket connection lives.
- virtual int GetRenderFrameId() const = 0;
+ virtual int GetRenderFrameId() = 0;
// Returns the WebSocketHandshakeRequestInfo instance attached to the given
// URLRequest. Returns nullptr when no instance is attached.
- CONTENT_EXPORT static const WebSocketHandshakeRequestInfo* ForRequest(
+ CONTENT_EXPORT static WebSocketHandshakeRequestInfo* ForRequest(
const net::URLRequest* request);
};
diff --git a/chromium/content/public/common/BUILD.gn b/chromium/content/public/common/BUILD.gn
index da96b060bb1..2384d52fa49 100644
--- a/chromium/content/public/common/BUILD.gn
+++ b/chromium/content/public/common/BUILD.gn
@@ -178,7 +178,6 @@ jumbo_source_set("common_sources") {
"process_type.h",
"profiling.cc",
"profiling.h",
- "push_subscription_options.h",
"referrer.cc",
"referrer.h",
"referrer_type_converters.cc",
@@ -244,7 +243,7 @@ jumbo_source_set("common_sources") {
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
"//third_party/blink/public:blink_headers",
- "//third_party/blink/public:mojo_bindings",
+ "//third_party/blink/public/mojom:mojom_platform_headers",
"//ui/accessibility",
"//ui/surface",
"//url/ipc:url_ipc",
@@ -365,7 +364,6 @@ mojom("interfaces") {
"drop_data.mojom",
"fullscreen_video_element.mojom",
"load_timing_info.mojom",
- "push_messaging_status.mojom",
"resource_load_info.mojom",
"resource_usage_reporter.mojom",
"transferrable_url_loader.mojom",
@@ -383,23 +381,11 @@ mojom("interfaces") {
"//services/network/public/mojom",
"//services/network/public/mojom:mojom_ip_address",
"//services/network/public/mojom:websocket_mojom",
- "//third_party/blink/public:mojo_bindings",
"//ui/accessibility:ax_enums_mojo",
"//url/mojom:url_mojom_gurl",
"//url/mojom:url_mojom_origin",
]
- if (is_mac) {
- sources += [
- "ns_view_bridge_factory.mojom",
- "web_contents_ns_view_bridge.mojom",
- ]
- public_deps += [
- "//ui/gfx/geometry/mojo",
- "//ui/gfx/image/mojo:interfaces",
- ]
- }
-
component_output_prefix = "content_public_common_mojo_bindings"
export_class_attribute = "CONTENT_EXPORT"
export_define = "CONTENT_IMPLEMENTATION=1"
diff --git a/chromium/content/public/common/DEPS b/chromium/content/public/common/DEPS
index b84338ed9c3..e9b03e477d0 100644
--- a/chromium/content/public/common/DEPS
+++ b/chromium/content/public/common/DEPS
@@ -19,4 +19,7 @@ specific_include_rules = {
"simple_url_loader_unittest\.cc": [
"+content/public/network",
],
+ "url_utils_unittest\.cc": [
+ "+content/public/test",
+ ],
}
diff --git a/chromium/content/public/common/child_process_host.h b/chromium/content/public/common/child_process_host.h
index 8f26d3b7f30..e62da71fc16 100644
--- a/chromium/content/public/common/child_process_host.h
+++ b/chromium/content/public/common/child_process_host.h
@@ -60,7 +60,33 @@ class CONTENT_EXPORT ChildProcessHost : public IPC::Sender {
// gdb). In this case, you'd use GetChildPath to get the real executable
// file name, and then prepend the GDB command to the command line.
CHILD_ALLOW_SELF = 1 << 0,
-#endif // defined(OS_LINUX)
+#elif defined(OS_MACOSX)
+ // Note, on macOS these are not bitwise flags and each value is mutually
+ // exclusive with the others. Each one of these options should correspond
+ // to a value in //content/public/app/mac_helpers.gni.
+
+ // Starts a child process with the macOS entitlement that allows JIT (i.e.
+ // memory that is writable and executable). In order to make use of this,
+ // memory cannot simply be allocated as read-write-execute; instead, the
+ // MAP_JIT flag must be passed to mmap() when allocating the memory region
+ // into which the writable-and-executable data are stored.
+ CHILD_RENDERER,
+
+ // Starts a child process with the macOS entitlement that allows unsigned
+ // executable memory.
+ // TODO(https://crbug.com/985816): Change this to use MAP_JIT and the
+ // allow-jit entitlement instead.
+ CHILD_GPU,
+
+ // Starts a child process with the macOS entitlement that ignores the
+ // library validation code signing enforcement. Library validation mandates
+ // that all executable pages be backed by a code signature that either 1)
+ // is signed by Apple, or 2) signed by the same Team ID as the main
+ // executable. Binary plug-ins that are not always signed by the same Team
+ // ID as the main binary, so this flag should be used when needing to load
+ // third-party plug-ins.
+ CHILD_PLUGIN,
+#endif
};
// Returns the pathname to be used for a child process. If a subprocess
diff --git a/chromium/content/public/common/common_param_traits_macros.h b/chromium/content/public/common/common_param_traits_macros.h
index c97b4e009ba..9ad8ad0bfa5 100644
--- a/chromium/content/public/common/common_param_traits_macros.h
+++ b/chromium/content/public/common/common_param_traits_macros.h
@@ -132,7 +132,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(databases_enabled)
IPC_STRUCT_TRAITS_MEMBER(application_cache_enabled)
IPC_STRUCT_TRAITS_MEMBER(tabs_to_links)
- IPC_STRUCT_TRAITS_MEMBER(history_entry_requires_user_gesture)
IPC_STRUCT_TRAITS_MEMBER(disable_ipc_flooding_protection)
IPC_STRUCT_TRAITS_MEMBER(hyperlink_auditing_enabled)
IPC_STRUCT_TRAITS_MEMBER(allow_universal_access_from_file_urls)
@@ -207,18 +206,17 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(double_tap_to_zoom_enabled)
IPC_STRUCT_TRAITS_MEMBER(dont_send_key_events_to_javascript)
IPC_STRUCT_TRAITS_MEMBER(web_app_scope)
+ IPC_STRUCT_TRAITS_MEMBER(fullscreen_supported)
#if defined(OS_ANDROID)
IPC_STRUCT_TRAITS_MEMBER(font_scale_factor)
IPC_STRUCT_TRAITS_MEMBER(device_scale_adjustment)
IPC_STRUCT_TRAITS_MEMBER(force_enable_zoom)
- IPC_STRUCT_TRAITS_MEMBER(fullscreen_supported)
IPC_STRUCT_TRAITS_MEMBER(default_video_poster_url)
IPC_STRUCT_TRAITS_MEMBER(support_deprecated_target_density_dpi)
IPC_STRUCT_TRAITS_MEMBER(use_legacy_background_size_shorthand_behavior)
IPC_STRUCT_TRAITS_MEMBER(wide_viewport_quirk)
IPC_STRUCT_TRAITS_MEMBER(use_wide_viewport)
IPC_STRUCT_TRAITS_MEMBER(force_zero_layout_height)
- IPC_STRUCT_TRAITS_MEMBER(viewport_meta_layout_size_quirk)
IPC_STRUCT_TRAITS_MEMBER(viewport_meta_merge_content_quirk)
IPC_STRUCT_TRAITS_MEMBER(viewport_meta_non_user_scalable_quirk)
IPC_STRUCT_TRAITS_MEMBER(viewport_meta_zero_values_quirk)
diff --git a/chromium/content/public/common/content_client.cc b/chromium/content/public/common/content_client.cc
index 9ab2f2396be..b738513d87b 100644
--- a/chromium/content/public/common/content_client.cc
+++ b/chromium/content/public/common/content_client.cc
@@ -92,6 +92,10 @@ base::RefCountedMemory* ContentClient::GetDataResourceBytes(
return nullptr;
}
+bool ContentClient::IsDataResourceGzipped(int resource_id) const {
+ return false;
+}
+
gfx::Image& ContentClient::GetNativeImageNamed(int resource_id) const {
static base::NoDestructor<gfx::Image> kEmptyImage;
return *kEmptyImage;
diff --git a/chromium/content/public/common/content_client.h b/chromium/content/public/common/content_client.h
index 394936ebccd..83c2abb4e2a 100644
--- a/chromium/content/public/common/content_client.h
+++ b/chromium/content/public/common/content_client.h
@@ -168,6 +168,9 @@ class CONTENT_EXPORT ContentClient {
virtual base::RefCountedMemory* GetDataResourceBytes(
int resource_id) const;
+ // Returns whether the contents of a resource are compressed (with gzip).
+ virtual bool IsDataResourceGzipped(int resource_id) const;
+
// Returns a native image given its id.
virtual gfx::Image& GetNativeImageNamed(int resource_id) const;
diff --git a/chromium/content/public/common/content_features.cc b/chromium/content/public/common/content_features.cc
index 7add6fe50ca..bd79f0ebd3b 100644
--- a/chromium/content/public/common/content_features.cc
+++ b/chromium/content/public/common/content_features.cc
@@ -18,7 +18,7 @@ const base::Feature kAllowActivationDelegationAttr{
// Allows starting services without the browser process.
const base::Feature kAllowStartingServiceManagerOnly{
- "AllowStartingServiceManagerOnly", base::FEATURE_DISABLED_BY_DEFAULT};
+ "AllowStartingServiceManagerOnly", base::FEATURE_ENABLED_BY_DEFAULT};
// Enables content-initiated, main frame navigations to data URLs.
// TODO(meacer): Remove when the deprecation is complete.
@@ -51,10 +51,6 @@ const base::Feature kAudioServiceLaunchOnStartup{
const base::Feature kAudioServiceOutOfProcess{
"AudioServiceOutOfProcess", base::FEATURE_DISABLED_BY_DEFAULT};
-// Enables await taking 1 tick on the microtask queue.
-const base::Feature kAwaitOptimization{"AwaitOptimization",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Kill switch for Background Fetch.
const base::Feature kBackgroundFetch{"BackgroundFetch",
base::FEATURE_ENABLED_BY_DEFAULT};
@@ -68,6 +64,9 @@ const base::Feature kBackForwardCache{"BackForwardCache",
const base::Feature kBlinkHeapIncrementalMarking{
"BlinkHeapIncrementalMarking", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kBlinkHeapUnifiedGCScheduling{
+ "BlinkHeapUnifiedGCScheduling", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enable bloated renderer detection.
const base::Feature kBloatedRendererDetection{
"BloatedRendererDetection", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -88,10 +87,10 @@ const base::Feature kTouchpadOverscrollHistoryNavigation {
const base::Feature kBlockCredentialedSubresources{
"BlockCredentialedSubresources", base::FEATURE_ENABLED_BY_DEFAULT};
-// Enables brotli "Accept-Encoding" advertising and "Content-Encoding" support.
-// Brotli format specification: http://www.ietf.org/id/draft-alakuijala-brotli
-const base::Feature kBrotliEncoding{"brotli-encoding",
- base::FEATURE_ENABLED_BY_DEFAULT};
+// Controls whether Bundled HTTP Exchanges is enabled.
+// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html
+const base::Feature kBundledHTTPExchanges{"BundledHTTPExchanges",
+ base::FEATURE_DISABLED_BY_DEFAULT};
// Enables code caching for inline scripts.
const base::Feature kCacheInlineScriptCode{"CacheInlineScriptCode",
@@ -118,16 +117,16 @@ const base::Feature kCompositeOpaqueFixedPosition{
const base::Feature kCompositeOpaqueScrollers{"CompositeOpaqueScrollers",
base::FEATURE_ENABLED_BY_DEFAULT};
+// Show messages in the DevTools console about upcoming deprecations
+// that would affect sent/received cookies.
+const base::Feature kCookieDeprecationMessages{
+ "CookieDeprecationMessages", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enables crash reporting via Reporting API.
// https://www.w3.org/TR/reporting/#crash-report
const base::Feature kCrashReporting{"CrashReporting",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Enables specification of a target element in the fragment identifier
-// via a CSS selector.
-const base::Feature kCSSFragmentIdentifiers{"CSSFragmentIdentifiers",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
// Puts save-data header in the holdback mode. This disables sending of
// save-data header to origins, and to the renderer processes within Chrome.
const base::Feature kDataSaverHoldback{"DataSaverHoldback",
@@ -140,7 +139,7 @@ const base::Feature kDesktopCaptureChangeSource{
// When a screen reader is detected, allow users the option of letting
// Google provide descriptions for unlabeled images.
const base::Feature kExperimentalAccessibilityLabels{
- "ExperimentalAccessibilityLabels", base::FEATURE_DISABLED_BY_DEFAULT};
+ "ExperimentalAccessibilityLabels", base::FEATURE_ENABLED_BY_DEFAULT};
// Throttle tasks in Blink background timer queues based on CPU budgets
// for the background tab. Bug: https://crbug.com/639852.
@@ -156,21 +155,12 @@ const base::Feature kExtendedMouseButtons{"ExtendedMouseButtons",
const base::Feature kFeaturePolicyForSandbox{"FeaturePolicyForSandbox",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Enables a blink::FontCache optimization that reuses a font to serve different
-// size of font.
-const base::Feature kFontCacheScaling{"FontCacheScaling",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
// Enables fixes for matching src: local() for web fonts correctly against full
// font name or postscript name. Rolling out behind a flag, as enabling this
// enables a font indexer on Android which we need to test in the field first.
const base::Feature kFontSrcLocalMatching{"FontSrcLocalMatching",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Enables freezing frame support based on feature policies.
-const base::Feature kFreezeFramesOnVisibility{
- "FreezeFramesOnVisibility", base::FEATURE_DISABLED_BY_DEFAULT};
-
// Puts network quality estimate related Web APIs in the holdback mode. When the
// holdback is enabled the related Web APIs return network quality estimate
// set by the experiment (regardless of the actual quality).
@@ -193,7 +183,7 @@ const base::Feature kHistoryManipulationIntervention{
"HistoryManipulationIntervention", base::FEATURE_ENABLED_BY_DEFAULT};
// This is intended as a kill switch for the Idle Detection feature. To enable
-// this feature,the experimental web platform features flag should be set,
+// this feature, the experimental web platform features flag should be set,
// or the site should obtain an Origin Trial token.
const base::Feature kIdleDetection{"IdleDetection",
base::FEATURE_ENABLED_BY_DEFAULT};
@@ -272,15 +262,8 @@ const base::Feature kMimeHandlerViewInCrossProcessFrame{
"MimeHandlerViewInCrossProcessFrame", base::FEATURE_DISABLED_BY_DEFAULT};
// Enables/disables the video capture service.
-const base::Feature kMojoVideoCapture {
- "MojoVideoCapture",
-#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_CHROMEOS) || \
- defined(OS_ANDROID)
- base::FEATURE_ENABLED_BY_DEFAULT
-#else
- base::FEATURE_DISABLED_BY_DEFAULT
-#endif
-};
+const base::Feature kMojoVideoCapture{"MojoVideoCapture",
+ base::FEATURE_ENABLED_BY_DEFAULT};
// A secondary switch used in combination with kMojoVideoCapture.
// This is intended as a kill switch to allow disabling the service on
@@ -290,14 +273,14 @@ const base::Feature kMojoVideoCaptureSecondary{
"MojoVideoCaptureSecondary", base::FEATURE_ENABLED_BY_DEFAULT};
// If the network service is enabled, runs it in process.
-const base::Feature kNetworkServiceInProcess{"NetworkServiceInProcess",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Turns on / off the new accessibility selection code which uses a more
-// predictable algorithm for mapping between positions in the DOM and the
-// accessibility trees.
-const base::Feature kNewAccessibilitySelection{
- "NewAccessibilitySelection", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kNetworkServiceInProcess {
+ "NetworkServiceInProcess",
+#if defined(OS_ANDROID)
+ base::FEATURE_ENABLED_BY_DEFAULT
+#else
+ base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
// Kill switch for Web Notification content images.
const base::Feature kNotificationContentImage{"NotificationContentImage",
@@ -316,7 +299,7 @@ const base::Feature kOriginTrials{"OriginTrials",
base::FEATURE_ENABLED_BY_DEFAULT};
// History navigation in response to horizontal overscroll (aka gesture-nav).
-const base::Feature kOverscrollHistoryNavigation{
+const base::Feature kOverscrollHistoryNavigation {
"OverscrollHistoryNavigation",
#if defined(OS_ANDROID)
base::FEATURE_DISABLED_BY_DEFAULT
@@ -325,10 +308,6 @@ const base::Feature kOverscrollHistoryNavigation{
#endif
};
-// Blink PageLifecycle feature. See https://crbug.com/775194
-const base::Feature kPageLifecycle{"PageLifecycle",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Whether document level event listeners should default 'passive' to true.
const base::Feature kPassiveDocumentEventListeners{
"PassiveDocumentEventListeners", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -347,10 +326,19 @@ const base::Feature kPassiveEventListenersDueToFling{
const base::Feature kPaymentRequestHasEnrolledInstrument = {
"PaymentRequestHasEnrolledInstrument", base::FEATURE_ENABLED_BY_DEFAULT};
+// Whether ExecutionContext is paused (and workers) on background freeze.
+const base::Feature kPauseExecutionContextOnBackgroundFreeze = {
+ "PauseExecutionContextOnBackgroundFreeze",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
// Whether PDF files should be rendered in diffent processes based on origin.
const base::Feature kPdfIsolation = {"PdfIsolation",
base::FEATURE_ENABLED_BY_DEFAULT};
+// Whether web apps can run periodic tasks upon network connectivity.
+const base::Feature kPeriodicBackgroundSync{"PeriodicBackgroundSync",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Whether we should use the navigation_client mojo interface for navigations.
const base::Feature kPerNavigationMojoInterface = {
"PerNavigationMojoInterface", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -382,6 +370,24 @@ const base::Feature kPrioritizeBootstrapTasks = {
const base::Feature kRasterInducingScroll{"RasterInducingScroll",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Reduce the amount of information in the default 'referer' header for
+// cross-origin requests.
+const base::Feature kReducedReferrerGranularity{
+ "ReducedReferrerGranularity", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Causes hidden tabs with crashed subframes to be marked for reload, meaning
+// that if a user later switches to that tab, the current page will be
+// reloaded. This will hide crashed subframes from the user at the cost of
+// extra reloads.
+const base::Feature kReloadHiddenTabsWithCrashedSubframes {
+ "ReloadHiddenTabsWithCrashedSubframes",
+#if defined(OS_ANDROID)
+ base::FEATURE_ENABLED_BY_DEFAULT
+#else
+ base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
+
// RenderDocument:
//
// Currently, a RenderFrameHost represents neither a frame nor a document, but a
@@ -424,11 +430,6 @@ const base::Feature kSendBeaconThrowForBlobWithNonSimpleType{
"SendBeaconThrowForBlobWithNonSimpleType",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Keep processes with service workers controlling clients from other
-// processes at foreground priority. (crbug.com/928904)
-const base::Feature kServiceWorkerForegroundPriority{
- "ServiceWorkerForegroundPriority", base::FEATURE_ENABLED_BY_DEFAULT};
-
// Enables long running message dispatch for service workers.
// This is a temporary addition only to be used for the Android Messages
// integration with ChromeOS (http://crbug.com/823256).
@@ -470,6 +471,12 @@ const base::Feature kSignedHTTPExchange{"SignedHTTPExchange",
const base::Feature kSignedHTTPExchangePingValidity{
"SignedHTTPExchangePingValidity", base::FEATURE_DISABLED_BY_DEFAULT};
+// This is intended as a kill switch for the SMS Receiver feature. To enable
+// this feature, the experimental web platform features flag should be set,
+// or the site should obtain an Origin Trial token.
+const base::Feature kSmsReceiver{"SmsReceiver",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
// Controls whether SpareRenderProcessHostManager tries to always have a warm
// spare renderer process around for the most recently requested BrowserContext.
// This feature is only consulted in site-per-process mode.
@@ -481,6 +488,11 @@ const base::Feature kSpareRendererForSitePerProcess{
const base::Feature kStaleWhileRevalidate{"StaleWhileRevalidate",
base::FEATURE_ENABLED_BY_DEFAULT};
+// Controls whether site isolation should use origins instead of scheme and
+// eTLD+1.
+const base::Feature kStrictOriginIsolation{"StrictOriginIsolation",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Dispatch touch events to "SyntheticGestureController" for events from
// Devtool Protocol Input.dispatchTouchEvent to simulate touch events close to
// real OS events.
@@ -526,9 +538,6 @@ const base::Feature kUserAgentClientHint{"UserAgentClientHint",
const base::Feature kV8LowMemoryModeForSubframes{
"V8LowMemoryModeForSubframes", base::FEATURE_DISABLED_BY_DEFAULT};
-// Enables to use the V8 Orinoco garbage collector.
-const base::Feature kV8Orinoco{"V8Orinoco", base::FEATURE_ENABLED_BY_DEFAULT};
-
// Enables future V8 VM features
const base::Feature kV8VmFuture{"V8VmFuture",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -547,6 +556,15 @@ const base::Feature kWebAssemblyBaseline{"WebAssemblyBaseline",
#endif
};
+// Enable garbage collection of WebAssembly code.
+const base::Feature kWebAssemblyCodeGC{"WebAssemblyCodeGC",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enable WebAssembly SIMD
+// https://github.com/WebAssembly/Simd
+const base::Feature kWebAssemblySimd{"WebAssemblySimd",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enable WebAssembly threads.
// https://github.com/WebAssembly/threads
const base::Feature kWebAssemblyThreads {
@@ -572,7 +590,7 @@ const base::Feature kWebAssemblyTrapHandler{"WebAssemblyTrapHandler",
// disabled, an occluded WebContents behaves exactly like a VISIBLE WebContents.
const base::Feature kWebContentsOcclusion {
"WebContentsOcclusion",
-#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS) || defined(OS_WIN)
base::FEATURE_ENABLED_BY_DEFAULT
#else
base::FEATURE_DISABLED_BY_DEFAULT
@@ -674,6 +692,10 @@ const base::Feature kWebXr{"WebXR", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kWebXrHitTest{"WebXRHitTest",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables access to planes detected in the user's environment.
+const base::Feature kWebXrPlaneDetection{"WebXRPlaneDetection",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Wipe corrupt v2 IndexedDB databases.
const base::Feature kWipeCorruptV2IDBDatabases{
"WipeCorruptV2IDBDatabases", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -711,21 +733,12 @@ const base::Feature kForce60HzRefreshRate{"Force60HzRefreshRate",
const base::Feature kWebNfc{"WebNFC", base::FEATURE_DISABLED_BY_DEFAULT};
#endif // defined(OS_ANDROID)
-#if !defined(OS_ANDROID)
-// Makes all WebUI that uses Polymer use 2.x version.
-// TODO(dpapad): Remove this once Polymer 2 migration is done,
-// https://crbug.com/738611.
-const base::Feature kWebUIPolymer2{"WebUIPolymer2",
- base::FEATURE_ENABLED_BY_DEFAULT};
-#endif // !defined(OS_ANDROID)
-
#if defined(OS_CHROMEOS)
// If this flag is enabled, Web UI pages can call DisablePolymer2() on the
-// shared resource during setup in order to use Polymer 1, regardless of the
-// state of the WebUIPolymer2 flag. Note: Currently, this only supports one Web
-// UI page disabling Polymer 2.
-// TODO(dpapad): Remove this once Polymer 2 migration is done,
-// https://crbug.com/738611.
+// shared resource during setup in order to use Polymer 1. Note: Currently, this
+// only supports one Web UI page disabling Polymer 2.
+// TODO(crbug.com/955194): Remove this once chrome://oobe migrates off of
+// Polymer 1.
const base::Feature kWebUIPolymer2Exceptions{"WebUIPolymer2Exceptions",
base::FEATURE_ENABLED_BY_DEFAULT};
#endif // defined(OS_CHROMEOS)
diff --git a/chromium/content/public/common/content_features.h b/chromium/content/public/common/content_features.h
index c883c8b95fb..d9a63af4f73 100644
--- a/chromium/content/public/common/content_features.h
+++ b/chromium/content/public/common/content_features.h
@@ -26,19 +26,19 @@ CONTENT_EXPORT extern const base::Feature kAppCacheIncludePaddingInQuota;
CONTENT_EXPORT extern const base::Feature kAudioServiceAudioStreams;
CONTENT_EXPORT extern const base::Feature kAudioServiceLaunchOnStartup;
CONTENT_EXPORT extern const base::Feature kAudioServiceOutOfProcess;
-CONTENT_EXPORT extern const base::Feature kAwaitOptimization;
CONTENT_EXPORT extern const base::Feature kBackgroundFetch;
CONTENT_EXPORT extern const base::Feature kBackForwardCache;
CONTENT_EXPORT extern const base::Feature kBlinkHeapIncrementalMarking;
+CONTENT_EXPORT extern const base::Feature kBlinkHeapUnifiedGCScheduling;
CONTENT_EXPORT extern const base::Feature kBloatedRendererDetection;
CONTENT_EXPORT extern const base::Feature kBlockCredentialedSubresources;
-CONTENT_EXPORT extern const base::Feature kBrotliEncoding;
+CONTENT_EXPORT extern const base::Feature kBundledHTTPExchanges;
CONTENT_EXPORT extern const base::Feature kCacheInlineScriptCode;
CONTENT_EXPORT extern const base::Feature kCanvas2DImageChromium;
CONTENT_EXPORT extern const base::Feature kCompositeOpaqueFixedPosition;
CONTENT_EXPORT extern const base::Feature kCompositeOpaqueScrollers;
+CONTENT_EXPORT extern const base::Feature kCookieDeprecationMessages;
CONTENT_EXPORT extern const base::Feature kCrashReporting;
-CONTENT_EXPORT extern const base::Feature kCSSFragmentIdentifiers;
CONTENT_EXPORT extern const base::Feature kDataSaverHoldback;
CONTENT_EXPORT extern const base::Feature kDesktopCaptureChangeSource;
CONTENT_EXPORT extern const base::Feature kExperimentalAccessibilityLabels;
@@ -46,9 +46,7 @@ CONTENT_EXPORT extern const base::Feature kExperimentalProductivityFeatures;
CONTENT_EXPORT extern const base::Feature kExpensiveBackgroundTimerThrottling;
CONTENT_EXPORT extern const base::Feature kExtendedMouseButtons;
CONTENT_EXPORT extern const base::Feature kFeaturePolicyForSandbox;
-CONTENT_EXPORT extern const base::Feature kFontCacheScaling;
CONTENT_EXPORT extern const base::Feature kFontSrcLocalMatching;
-CONTENT_EXPORT extern const base::Feature kFreezeFramesOnVisibility;
CONTENT_EXPORT extern const base::Feature kGuestViewCrossProcessFrames;
CONTENT_EXPORT extern const base::Feature kHeapCompaction;
CONTENT_EXPORT extern const base::Feature kHistoryManipulationIntervention;
@@ -72,24 +70,27 @@ CONTENT_EXPORT extern const base::Feature kMojoVideoCapture;
CONTENT_EXPORT extern const base::Feature kMojoVideoCaptureSecondary;
CONTENT_EXPORT extern const base::Feature kNetworkQualityEstimatorWebHoldback;
CONTENT_EXPORT extern const base::Feature kNetworkServiceInProcess;
-CONTENT_EXPORT extern const base::Feature kNewAccessibilitySelection;
CONTENT_EXPORT extern const base::Feature kNotificationContentImage;
CONTENT_EXPORT extern const base::Feature kNotificationTriggers;
CONTENT_EXPORT extern const base::Feature kOriginPolicy;
CONTENT_EXPORT extern const base::Feature kOriginTrials;
CONTENT_EXPORT extern const base::Feature kOverscrollHistoryNavigation;
-CONTENT_EXPORT extern const base::Feature kPageLifecycle;
CONTENT_EXPORT extern const base::Feature kPassiveDocumentEventListeners;
CONTENT_EXPORT extern const base::Feature kPassiveDocumentWheelEventListeners;
CONTENT_EXPORT extern const base::Feature kPassiveEventListenersDueToFling;
+CONTENT_EXPORT extern const base::Feature
+ kPauseExecutionContextOnBackgroundFreeze;
CONTENT_EXPORT extern const base::Feature kPaymentRequestHasEnrolledInstrument;
CONTENT_EXPORT extern const base::Feature kPdfIsolation;
+CONTENT_EXPORT extern const base::Feature kPeriodicBackgroundSync;
CONTENT_EXPORT extern const base::Feature kPerNavigationMojoInterface;
CONTENT_EXPORT extern const base::Feature kPepper3DImageChromium;
CONTENT_EXPORT extern const base::Feature kPrioritizeBootstrapTasks;
CONTENT_EXPORT extern const base::Feature
kProcessSharingWithStrictSiteInstances;
CONTENT_EXPORT extern const base::Feature kRasterInducingScroll;
+CONTENT_EXPORT extern const base::Feature kReducedReferrerGranularity;
+CONTENT_EXPORT extern const base::Feature kReloadHiddenTabsWithCrashedSubframes;
CONTENT_EXPORT extern const base::Feature kRenderDocumentForMainFrame;
CONTENT_EXPORT extern const base::Feature kRenderDocumentForSubframe;
CONTENT_EXPORT extern const base::Feature kRenderingPipelineThrottling;
@@ -100,7 +101,6 @@ CONTENT_EXPORT extern const base::Feature
CONTENT_EXPORT extern const base::Feature kScrollAnchorSerialization;
CONTENT_EXPORT extern const base::Feature
kSendBeaconThrowForBlobWithNonSimpleType;
-CONTENT_EXPORT extern const base::Feature kServiceWorkerForegroundPriority;
CONTENT_EXPORT extern const base::Feature kServiceWorkerLongRunningMessage;
CONTENT_EXPORT extern const base::Feature kServiceWorkerPaymentApps;
CONTENT_EXPORT extern const base::Feature kSharedArrayBuffer;
@@ -109,8 +109,10 @@ CONTENT_EXPORT extern const base::Feature
CONTENT_EXPORT extern const base::Feature kSignedExchangeSubresourcePrefetch;
CONTENT_EXPORT extern const base::Feature kSignedHTTPExchange;
CONTENT_EXPORT extern const base::Feature kSignedHTTPExchangePingValidity;
+CONTENT_EXPORT extern const base::Feature kSmsReceiver;
CONTENT_EXPORT extern const base::Feature kSpareRendererForSitePerProcess;
CONTENT_EXPORT extern const base::Feature kStaleWhileRevalidate;
+CONTENT_EXPORT extern const base::Feature kStrictOriginIsolation;
CONTENT_EXPORT extern const base::Feature kSyntheticPointerActions;
CONTENT_EXPORT extern const base::Feature kTimerThrottlingForHiddenFrames;
CONTENT_EXPORT extern const base::Feature kTouchpadAsyncPinchEvents;
@@ -120,10 +122,11 @@ CONTENT_EXPORT extern const base::Feature kUserActivationSameOriginVisibility;
CONTENT_EXPORT extern const base::Feature kUserActivationV2;
CONTENT_EXPORT extern const base::Feature kUserAgentClientHint;
CONTENT_EXPORT extern const base::Feature kV8LowMemoryModeForSubframes;
-CONTENT_EXPORT extern const base::Feature kV8Orinoco;
CONTENT_EXPORT extern const base::Feature kV8VmFuture;
CONTENT_EXPORT extern const base::Feature kWebAssembly;
CONTENT_EXPORT extern const base::Feature kWebAssemblyBaseline;
+CONTENT_EXPORT extern const base::Feature kWebAssemblyCodeGC;
+CONTENT_EXPORT extern const base::Feature kWebAssemblySimd;
CONTENT_EXPORT extern const base::Feature kWebAssemblyThreads;
CONTENT_EXPORT extern const base::Feature kWebAssemblyTrapHandler;
CONTENT_EXPORT extern const base::Feature kWebAuth;
@@ -143,6 +146,7 @@ CONTENT_EXPORT extern const base::Feature kWebRtcHideLocalIpsWithMdns;
CONTENT_EXPORT extern const base::Feature kWebUsb;
CONTENT_EXPORT extern const base::Feature kWebXr;
CONTENT_EXPORT extern const base::Feature kWebXrHitTest;
+CONTENT_EXPORT extern const base::Feature kWebXrPlaneDetection;
CONTENT_EXPORT extern const base::Feature kWipeCorruptV2IDBDatabases;
CONTENT_EXPORT extern const base::Feature kScriptStreamingOnPreload;
@@ -156,10 +160,6 @@ CONTENT_EXPORT extern const base::Feature kWarmUpNetworkProcess;
CONTENT_EXPORT extern const base::Feature kWebNfc;
#endif // defined(OS_ANDROID)
-#if !defined(OS_ANDROID)
-CONTENT_EXPORT extern const base::Feature kWebUIPolymer2;
-#endif // !defined(OS_ANDROID)
-
#if defined(OS_CHROMEOS)
CONTENT_EXPORT extern const base::Feature kWebUIPolymer2Exceptions;
#endif
diff --git a/chromium/content/public/common/content_switches.cc b/chromium/content/public/common/content_switches.cc
index e2c3e6d7a36..6ec9ea90df1 100644
--- a/chromium/content/public/common/content_switches.cc
+++ b/chromium/content/public/common/content_switches.cc
@@ -216,13 +216,6 @@ const char kDisableNotifications[] = "disable-notifications";
// the use of persistent gpu memory buffers.
const char kDisablePartialRaster[] = "disable-partial-raster";
-// By default, in devtools_session.cc, we use CBOR for protocol messages
-// except for sending JSON to clients that request it.
-// This switch undoes this default. We plan to remove it after after transition
-// to binary is sufficiently complete (2019-04-15).
-const char kDisableInternalDevToolsBinaryProtocol[] =
- "disable-internal-devtools-binary-protocol";
-
// Enable partial raster in the renderer.
const char kEnablePartialRaster[] = "enable-partial-raster";
@@ -326,11 +319,9 @@ const char kDomAutomationController[] = "dom-automation";
// Disable antialiasing on 2d canvas clips
const char kDisable2dCanvasClipAntialiasing[] = "disable-2d-canvas-clip-aa";
-// Disable partially decoding jpeg images using the GPU.
-// At least YUV decoding will be accelerated when not using this flag.
+// Disable YUV image decoding for those formats and cases where it's supported.
// Has no effect unless GPU rasterization is enabled.
-const char kDisableAcceleratedJpegDecoding[] =
- "disable-accelerated-jpeg-decoding";
+const char kDisableYUVImageDecoding[] = "disable-yuv-image-decoding";
// Logs Runtime Call Stats for Blink. --single-process also needs to be
// used along with this for the stats to be logged.
@@ -533,11 +524,6 @@ const char kGpuSandboxStartEarly[] = "gpu-sandbox-start-early";
// Causes the GPU process to display a dialog on launch.
const char kGpuStartupDialog[] = "gpu-startup-dialog";
-// Don't allow content to arbitrarily append to the back/forward list.
-// The page must prcoess a user gesture before an entry can be added.
-const char kHistoryEntryRequiresUserGesture[] =
- "history-entry-requires-user-gesture";
-
// Start the renderer with an initial virtual time override specified in
// seconds since the epoch.
const char kInitialVirtualTime[] = "initial-virtual-time";
@@ -580,6 +566,10 @@ const char kLogFile[] = "log-file";
const char kMainFrameResizesAreOrientationChanges[] =
"main-frame-resizes-are-orientation-changes";
+// Allows user to override maximum number of active WebGL contexts per
+// renderer process.
+const char kMaxActiveWebGLContexts[] = "max-active-webgl-contexts";
+
// Sets the maximium decoded image size limitation.
const char kMaxDecodedImageSizeMb[] = "max-decoded-image-size-mb";
@@ -590,6 +580,10 @@ const char kMaxUntiledLayerWidth[] = "max-untiled-layer-width";
// Indicates the utility process should run with a message loop type of UI.
const char kMessageLoopTypeUi[] = "message-loop-type-ui";
+// Set the default result for MockCertVerifier. This only works in test code.
+const char kMockCertVerifierDefaultResultForTesting[] =
+ "mock-cert-verifier-default-result-for-testing";
+
// Use a Mojo-based LocalStorage implementation.
const char kMojoLocalStorage[] = "mojo-local-storage";
@@ -619,12 +613,6 @@ const char kNumRasterThreads[] = "num-raster-threads";
const char kOverridePluginPowerSaverForTesting[] =
"override-plugin-power-saver-for-testing";
-// Controls the value of the threshold to start horizontal overscroll relative
-// to the default value.
-// E.g. set the value to '133' to have the overscroll start threshold be 133%
-// of the default threshold.
-const char kOverscrollStartThreshold[] = "overscroll-start-threshold";
-
// Override the default value for the 'passive' field in javascript
// addEventListener calls. Values are defined as:
// 'documentonlytrue' to set the default be true only for document level nodes.
@@ -722,16 +710,13 @@ const char kRendererProcessLimit[] = "renderer-process-limit";
// that's needed to show a dialog.
const char kRendererStartupDialog[] = "renderer-startup-dialog";
-// Reduce the default `referer` header's granularity.
-const char kReducedReferrerGranularity[] =
- "reduced-referrer-granularity";
-
-// Enables native memory sampling profiler with a given rate (default 128 KiB).
-const char kSamplingHeapProfiler[] = "sampling-heap-profiler";
-
// Causes the process to run as a sandbox IPC subprocess.
const char kSandboxIPCProcess[] = "sandbox-ipc";
+// Visibly render a border around layout shift rects in the web page to help
+// debug and study layout shifts.
+const char kShowLayoutShiftRegions[] = "show-layout-shift-regions";
+
// Visibly render a border around paint rects in the web page to help debug
// and study painting behavior.
const char kShowPaintRects[] = "show-paint-rects";
@@ -769,11 +754,6 @@ const char kSitePerProcess[] = "site-per-process";
// backcompatibility of chrome://flags.
const char kDisableSiteIsolation[] = "disable-site-isolation-trials";
-// Just like kDisableSiteIsolation, but doesn't show the "stability and security
-// will suffer" butter bar warning.
-const char kDisableSiteIsolationForPolicy[] =
- "disable-site-isolation-for-policy";
-
// Specifies if the browser should start in fullscreen mode, like if the user
// had pressed F11 right after startup.
const char kStartFullscreen[] = "start-fullscreen";
@@ -851,6 +831,13 @@ const char kValidateInputEventStream[] = "validate-input-event-stream";
// kWaitForDebugger flag passed on or not.
const char kWaitForDebuggerChildren[] = "wait-for-debugger-children";
+// Set the antialiasing method used for webgl. (none, explicit, implicit, or
+// screenspace)
+const char kWebglAntialiasingMode[] = "webgl-antialiasing-mode";
+
+// Set a default sample count for webgl if msaa is enabled.
+const char kWebglMSAASampleCount[] = "webgl-msaa-sample-count";
+
// Disables encryption of RTP Media for WebRTC. When Chrome embeds Content, it
// ignores this switch on its stable and beta channels.
const char kDisableWebRtcEncryption[] = "disable-webrtc-encryption";
@@ -868,6 +855,7 @@ const char kEnableWebRtcSrtpAesGcm[] = "enable-webrtc-srtp-aes-gcm";
// Enables negotiation of encrypted header extensions from RFC 6904 for SRTP
// in WebRTC.
// See https://tools.ietf.org/html/rfc6904 for further information.
+// TODO(https://crbug.com/954201): Remove this.
const char kEnableWebRtcSrtpEncryptedHeaders[] =
"enable-webrtc-srtp-encrypted-headers";
@@ -917,6 +905,11 @@ const char kDisablePullToRefreshEffect[] = "disable-pull-to-refresh-effect";
// Disable the locking feature of the screen orientation API.
const char kDisableScreenOrientationLock[] = "disable-screen-orientation-lock";
+// Just like kDisableSiteIsolation, but doesn't show the "stability and security
+// will suffer" butter bar warning.
+const char kDisableSiteIsolationForPolicy[] =
+ "disable-site-isolation-for-policy";
+
// Disable timeouts that may cause the browser to die when running slowly. This
// is useful if running with profiling (such as debug malloc).
const char kDisableTimeoutsForProfiling[] = "disable-timeouts-for-profiling";
@@ -938,9 +931,6 @@ const char kRemoteDebuggingSocketName[] = "remote-debugging-socket-name";
// Block ChildProcessMain thread of the renderer's ChildProcessService until a
// Java debugger is attached.
const char kRendererWaitForJavaDebugger[] = "renderer-wait-for-java-debugger";
-
-// Enables overscrolling for the OSK on Android.
-const char kEnableOSKOverscroll[] = "enable-osk-overscroll";
#endif
// Enable the experimental Accessibility Object Model APIs in development.
@@ -997,10 +987,6 @@ const char kDeviceScaleFactor[] = "device-scale-factor";
// Disable the Legacy Window which corresponds to the size of the WebContents.
const char kDisableLegacyIntermediateWindow[] = "disable-legacy-window";
-// Enables experimental hardware acceleration for VP8/VP9 video decoding.
-// Bitmask - 0x1=Microsoft, 0x2=AMD, 0x03=Try all.
-const char kEnableAcceleratedVpxDecode[] = "enable-accelerated-vpx-decode";
-
// Enables H264 HW decode acceleration for WebRtc on Win 7.
const char kEnableWin7WebRtcHWH264Decoding[] =
"enable-win7-webrtc-hw-h264-decoding";
@@ -1009,12 +995,6 @@ const char kEnableWin7WebRtcHWH264Decoding[] =
// This switch allows us to pass the shared memory handle to the renderer.
const char kFontCacheSharedHandle[] = "font-cache-shared-handle";
-// Sets the free memory thresholds below which the system is considered to be
-// under moderate and critical memory pressure. Used in the browser process,
-// and ignored if invalid. Specified as a pair of comma separated integers.
-// See base/win/memory_pressure_monitor.cc for defaults.
-const char kMemoryPressureThresholdsMb[] = "memory-pressure-thresholds-mb";
-
// The boolean value (0/1) of FontRenderParams::antialiasing to be passed to
// Ppapi processes.
const char kPpapiAntialiasedTextEnabled[] = "ppapi-antialiased-text-enabled";
diff --git a/chromium/content/public/common/content_switches.h b/chromium/content/public/common/content_switches.h
index 62294da39b0..0fcad456fd0 100644
--- a/chromium/content/public/common/content_switches.h
+++ b/chromium/content/public/common/content_switches.h
@@ -32,7 +32,7 @@ CONTENT_EXPORT extern const char kDisable2dCanvasAntialiasing[];
CONTENT_EXPORT extern const char kDisable2dCanvasImageChromium[];
CONTENT_EXPORT extern const char kDisable3DAPIs[];
CONTENT_EXPORT extern const char kDisableAccelerated2dCanvas[];
-CONTENT_EXPORT extern const char kDisableAcceleratedJpegDecoding[];
+CONTENT_EXPORT extern const char kDisableYUVImageDecoding[];
CONTENT_EXPORT extern const char kDisableAcceleratedVideoDecode[];
CONTENT_EXPORT extern const char kDisableAcceleratedVideoEncode[];
extern const char kDisableBackingStoreLimit[];
@@ -73,7 +73,6 @@ CONTENT_EXPORT extern const char kDisableNewContentRenderingTimeout[];
CONTENT_EXPORT extern const char kDisableNotifications[];
CONTENT_EXPORT extern const char kDisableOriginTrialControlledBlinkFeatures[];
CONTENT_EXPORT extern const char kDisablePartialRaster[];
-CONTENT_EXPORT extern const char kDisableInternalDevToolsBinaryProtocol[];
CONTENT_EXPORT extern const char kEnablePartialRaster[];
extern const char kDisablePepper3d[];
CONTENT_EXPORT extern const char kDisablePepper3DImageChromium[];
@@ -160,8 +159,6 @@ extern const char kGpuLauncher[];
CONTENT_EXPORT extern const char kGpuProcess[];
CONTENT_EXPORT extern const char kGpuSandboxStartEarly[];
CONTENT_EXPORT extern const char kGpuStartupDialog[];
-CONTENT_EXPORT extern const char kSamplingHeapProfiler[];
-CONTENT_EXPORT extern const char kHistoryEntryRequiresUserGesture[];
CONTENT_EXPORT extern const char kInitialVirtualTime[];
CONTENT_EXPORT extern const char kInProcessGPU[];
CONTENT_EXPORT extern const char kIPCConnectionTimeout[];
@@ -172,6 +169,7 @@ CONTENT_EXPORT extern const char kLogGpuControlListDecisions[];
CONTENT_EXPORT extern const char kLoggingLevel[];
CONTENT_EXPORT extern const char kLogFile[];
CONTENT_EXPORT extern const char kMainFrameResizesAreOrientationChanges[];
+extern const char kMaxActiveWebGLContexts[];
extern const char kMaxDecodedImageSizeMb[];
extern const char kMaxUntiledLayerHeight[];
extern const char kMaxUntiledLayerWidth[];
@@ -179,6 +177,7 @@ CONTENT_EXPORT extern const char kMessageLoopTypeUi[];
CONTENT_EXPORT extern const char kMHTMLGeneratorOption[];
CONTENT_EXPORT extern const char kMHTMLSkipNostoreMain[];
CONTENT_EXPORT extern const char kMHTMLSkipNostoreAll[];
+CONTENT_EXPORT extern const char kMockCertVerifierDefaultResultForTesting[];
CONTENT_EXPORT extern const char kMojoLocalStorage[];
CONTENT_EXPORT extern const char kNetworkQuietTimeout[];
CONTENT_EXPORT extern const char kNoZygote[];
@@ -187,7 +186,6 @@ CONTENT_EXPORT extern const char kEnableAppContainer[];
CONTENT_EXPORT extern const char kDisableAppContainer[];
CONTENT_EXPORT extern const char kNumRasterThreads[];
CONTENT_EXPORT extern const char kOverridePluginPowerSaverForTesting[];
-CONTENT_EXPORT extern const char kOverscrollStartThreshold[];
CONTENT_EXPORT extern const char kPassiveListenersDefault[];
CONTENT_EXPORT extern const char kPpapiBrokerProcess[];
CONTENT_EXPORT extern const char kPpapiFlashArgs[];
@@ -210,11 +208,11 @@ CONTENT_EXPORT extern const char kRendererProcess[];
CONTENT_EXPORT extern const char kRendererProcessLimit[];
CONTENT_EXPORT extern const char kRendererStartupDialog[];
extern const char kSandboxIPCProcess[];
+extern const char kShowLayoutShiftRegions[];
extern const char kShowPaintRects[];
CONTENT_EXPORT extern const char kSingleProcess[];
CONTENT_EXPORT extern const char kSitePerProcess[];
CONTENT_EXPORT extern const char kDisableSiteIsolation[];
-CONTENT_EXPORT extern const char kDisableSiteIsolationForPolicy[];
CONTENT_EXPORT extern const char kStartFullscreen[];
CONTENT_EXPORT extern const char kStatsCollectionController[];
extern const char kSkiaFontCacheLimitMb[];
@@ -236,6 +234,8 @@ CONTENT_EXPORT extern const char kUtilityStartupDialog[];
CONTENT_EXPORT extern const char kV8CacheOptions[];
CONTENT_EXPORT extern const char kValidateInputEventStream[];
CONTENT_EXPORT extern const char kWaitForDebuggerChildren[];
+extern const char kWebglAntialiasingMode[];
+extern const char kWebglMSAASampleCount[];
CONTENT_EXPORT extern const char kDisableWebRtcEncryption[];
CONTENT_EXPORT extern const char kDisableWebRtcHWDecoding[];
@@ -255,13 +255,13 @@ CONTENT_EXPORT extern const char kDisableMediaSessionAPI[];
CONTENT_EXPORT extern const char kDisableOverscrollEdgeEffect[];
CONTENT_EXPORT extern const char kDisablePullToRefreshEffect[];
CONTENT_EXPORT extern const char kDisableScreenOrientationLock[];
+CONTENT_EXPORT extern const char kDisableSiteIsolationForPolicy[];
CONTENT_EXPORT extern const char kDisableTimeoutsForProfiling[];
CONTENT_EXPORT extern const char kEnableAdaptiveSelectionHandleOrientation[];
CONTENT_EXPORT extern const char kEnableLongpressDragSelection[];
extern const char kNetworkCountryIso[];
CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[];
CONTENT_EXPORT extern const char kRendererWaitForJavaDebugger[];
-CONTENT_EXPORT extern const char kEnableOSKOverscroll[];
#endif
#if defined(OS_CHROMEOS)
@@ -282,11 +282,9 @@ CONTENT_EXPORT extern const char kPrefetchArgumentOther[];
// like renderers, etc.
CONTENT_EXPORT extern const char kDeviceScaleFactor[];
CONTENT_EXPORT extern const char kDisableLegacyIntermediateWindow[];
-CONTENT_EXPORT extern const char kEnableAcceleratedVpxDecode[];
CONTENT_EXPORT extern const char kEnableWin7WebRtcHWH264Decoding[];
// Switch to pass the font cache shared memory handle to the renderer.
CONTENT_EXPORT extern const char kFontCacheSharedHandle[];
-CONTENT_EXPORT extern const char kMemoryPressureThresholdsMb[];
CONTENT_EXPORT extern const char kPpapiAntialiasedTextEnabled[];
CONTENT_EXPORT extern const char kPpapiSubpixelRenderingSetting[];
#endif
diff --git a/chromium/content/public/common/navigation_policy.cc b/chromium/content/public/common/navigation_policy.cc
index 2bfec2c1066..2fea9a0f8eb 100644
--- a/chromium/content/public/common/navigation_policy.cc
+++ b/chromium/content/public/common/navigation_policy.cc
@@ -5,12 +5,27 @@
#include "content/public/common/navigation_policy.h"
#include "base/command_line.h"
+#include "base/metrics/histogram_macros.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "services/network/public/cpp/features.h"
namespace content {
+namespace {
+
+void LogPerPolicyApplied(NavigationDownloadType type) {
+ UMA_HISTOGRAM_ENUMERATION("Navigation.DownloadPolicy.LogPerPolicyApplied",
+ type);
+}
+
+void LogArbitraryPolicyPerDownload(NavigationDownloadType type) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Navigation.DownloadPolicy.LogArbitraryPolicyPerDownload", type);
+}
+
+} // namespace
+
bool IsPerNavigationMojoInterfaceEnabled() {
return base::FeatureList::IsEnabled(features::kPerNavigationMojoInterface);
}
@@ -19,4 +34,67 @@ bool IsBackForwardCacheEnabled() {
return base::FeatureList::IsEnabled(features::kBackForwardCache);
}
+NavigationDownloadPolicy::NavigationDownloadPolicy() = default;
+NavigationDownloadPolicy::~NavigationDownloadPolicy() = default;
+NavigationDownloadPolicy::NavigationDownloadPolicy(
+ const NavigationDownloadPolicy&) = default;
+
+void NavigationDownloadPolicy::SetAllowed(NavigationDownloadType type) {
+ DCHECK(type != NavigationDownloadType::kDefaultAllow);
+ observed_types.set(static_cast<size_t>(type));
+}
+
+void NavigationDownloadPolicy::SetDisallowed(NavigationDownloadType type) {
+ DCHECK(type != NavigationDownloadType::kDefaultAllow);
+ observed_types.set(static_cast<size_t>(type));
+ disallowed_types.set(static_cast<size_t>(type));
+}
+
+bool NavigationDownloadPolicy::IsType(NavigationDownloadType type) const {
+ DCHECK(type != NavigationDownloadType::kDefaultAllow);
+ return observed_types.test(static_cast<size_t>(type));
+}
+
+ResourceInterceptPolicy NavigationDownloadPolicy::GetResourceInterceptPolicy()
+ const {
+ if (disallowed_types.test(
+ static_cast<size_t>(NavigationDownloadType::kSandboxNoGesture)) ||
+ disallowed_types.test(
+ static_cast<size_t>(NavigationDownloadType::kOpenerCrossOrigin)) ||
+ disallowed_types.test(
+ static_cast<size_t>(NavigationDownloadType::kAdFrameNoGesture)) ||
+ disallowed_types.test(
+ static_cast<size_t>(NavigationDownloadType::kAdFrameGesture))) {
+ return ResourceInterceptPolicy::kAllowPluginOnly;
+ }
+ return disallowed_types.any() ? ResourceInterceptPolicy::kAllowNone
+ : ResourceInterceptPolicy::kAllowAll;
+}
+
+bool NavigationDownloadPolicy::IsDownloadAllowed() const {
+ return disallowed_types.none();
+}
+
+void NavigationDownloadPolicy::RecordHistogram() const {
+ if (observed_types.none()) {
+ LogPerPolicyApplied(NavigationDownloadType::kDefaultAllow);
+ LogArbitraryPolicyPerDownload(NavigationDownloadType::kDefaultAllow);
+ return;
+ }
+
+ bool first_type_seen = false;
+ for (size_t i = 0; i < observed_types.size(); ++i) {
+ if (observed_types.test(i)) {
+ NavigationDownloadType policy = static_cast<NavigationDownloadType>(i);
+ DCHECK(policy != NavigationDownloadType::kDefaultAllow);
+ LogPerPolicyApplied(policy);
+ if (!first_type_seen) {
+ LogArbitraryPolicyPerDownload(policy);
+ first_type_seen = true;
+ }
+ }
+ }
+ DCHECK(first_type_seen);
+}
+
} // namespace content
diff --git a/chromium/content/public/common/navigation_policy.h b/chromium/content/public/common/navigation_policy.h
index 87fc81bbe91..86ab5c44b22 100644
--- a/chromium/content/public/common/navigation_policy.h
+++ b/chromium/content/public/common/navigation_policy.h
@@ -5,7 +5,10 @@
#ifndef CONTENT_PUBLIC_COMMON_NAVIGATION_POLICY_H_
#define CONTENT_PUBLIC_COMMON_NAVIGATION_POLICY_H_
+#include <bitset>
+
#include "content/common/content_export.h"
+#include "content/public/common/resource_intercept_policy.h"
// A centralized file for base helper methods and policy decisions about
// navigations.
@@ -15,6 +18,76 @@ namespace content {
CONTENT_EXPORT bool IsPerNavigationMojoInterfaceEnabled();
CONTENT_EXPORT bool IsBackForwardCacheEnabled();
+// Navigation type that affects the download decision and relevant metrics to be
+// reported at download-discovery time.
+//
+// This enum backs a histogram. Please keep enums.xml up to date with any
+// changes, and new entries should be appended at the end. Never re-arrange /
+// re-use values.
+enum class NavigationDownloadType {
+ // An entry reserved just for histogram. The client code is not expected to
+ // set or query this type in a policy.
+ kDefaultAllow = 0,
+
+ kViewSource = 1,
+ kInterstitial = 2,
+
+ // The navigation was initiated on a x-origin opener.
+ kOpenerCrossOrigin = 5,
+
+ // The navigation was initiated from or occurred in an iframe with
+ // |WebSandboxFlags::kDownloads| flag set and without user activation.
+ kSandboxNoGesture = 7,
+
+ // The navigation was initiated from or occurred in an ad frame without user
+ // activation.
+ kAdFrameNoGesture = 8,
+
+ // The navigation was initiated from or occurred in an ad frame with user
+ // activation.
+ kAdFrameGesture = 9,
+
+ kMaxValue = kAdFrameGesture
+};
+
+// Stores the navigation types that may be of interest to the download-related
+// metrics to be reported at download-discovery time. Also controls how
+// navigations behave when they turn into downloads. By default, navigation is
+// allowed to become a download.
+struct CONTENT_EXPORT NavigationDownloadPolicy {
+ NavigationDownloadPolicy();
+ ~NavigationDownloadPolicy();
+ NavigationDownloadPolicy(const NavigationDownloadPolicy&);
+
+ // Stores |type| to |observed_types|.
+ void SetAllowed(NavigationDownloadType type);
+
+ // Stores |type| to both |observed_types| and |disallowed_types|.
+ void SetDisallowed(NavigationDownloadType type);
+
+ // Returns if |observed_types| contains |type|.
+ bool IsType(NavigationDownloadType type) const;
+
+ // Get the ResourceInterceptPolicy derived from |disallowed_types|.
+ ResourceInterceptPolicy GetResourceInterceptPolicy() const;
+
+ // Returns if download is allowed based on |disallowed_types|.
+ bool IsDownloadAllowed() const;
+
+ // Record the download policy to histograms from |observed_types|.
+ void RecordHistogram() const;
+
+ // A bitset of navigation types observed that may be of interest to the
+ // download-related metrics to be reported at download-discovery time.
+ std::bitset<static_cast<size_t>(NavigationDownloadType::kMaxValue) + 1>
+ observed_types;
+
+ // A bitset of navigation types observed where if the navigation turns into
+ // a download, the download should be dropped.
+ std::bitset<static_cast<size_t>(NavigationDownloadType::kMaxValue) + 1>
+ disallowed_types;
+};
+
} // namespace content
#endif // CONTENT_PUBLIC_COMMON_NAVIGATION_POLICY_H_
diff --git a/chromium/content/public/common/ns_view_bridge_factory.mojom b/chromium/content/public/common/ns_view_bridge_factory.mojom
deleted file mode 100644
index 29402f35759..00000000000
--- a/chromium/content/public/common/ns_view_bridge_factory.mojom
+++ /dev/null
@@ -1,36 +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.
-
-module content.mojom;
-
-import "content/public/common/web_contents_ns_view_bridge.mojom";
-
-// Empty interface that is used by NSViewBridgeFactory in place of
-// RenderWidgetHostNSViewBridge and RenderWidgetHostNSViewClient (which are the
-// real interface that should be used). The reason that the correct interfaces
-// cannot be used directly is that they have dependencies on content-internal
-// mojo type serialization (in particular, content wrappings of Blink types).
-// TODO(ccameron): Migrate the interfaces RenderWidgetHostNSViewBridge and
-// RenderWidgetHostNSViewClient from content-internal types to ui types, and
-// then move the interfaces to content/public.
-// https://crbug.com/888290
-interface StubInterface {};
-
-interface NSViewBridgeFactory {
- // Create and take ownership of the NSView for a RenderWidgetHostView. The
- // resulting object will be destroyed when the connection is closed.
- CreateRenderWidgetHostNSViewBridge(
- associated StubInterface client,
- associated StubInterface& bridge_request);
-
- // Create and take ownership of the NSView for a WebContentsView. The
- // resulting object will be destroyed when the connection is closed.
- // The value of |view_id| may be used to look up the NSView (e.g, to add
- // child NSViews.
- CreateWebContentsNSViewBridge(
- uint64 view_id,
- associated WebContentsNSViewClient client,
- associated WebContentsNSViewBridge& bridge_request);
-};
-
diff --git a/chromium/content/public/common/previews_state.h b/chromium/content/public/common/previews_state.h
index 60aa7b7da2d..a54af41b69a 100644
--- a/chromium/content/public/common/previews_state.h
+++ b/chromium/content/public/common/previews_state.h
@@ -48,13 +48,20 @@ enum PreviewsTypes {
// image that was deferred by lazyload.
LAZY_IMAGE_AUTO_RELOAD = 1 << 11, // Request the full image after previously
// getting a lazy load placeholder.
- PREVIEWS_STATE_LAST = LAZY_IMAGE_AUTO_RELOAD
+ DEFER_ALL_SCRIPT_ON = 1 << 12, // Request that script execution be deferred
+ // until parsing completes.
+ PREVIEWS_STATE_LAST = DEFER_ALL_SCRIPT_ON
};
// Combination of all previews that are guaranteed not to provide partial
// content.
const PreviewsState PARTIAL_CONTENT_SAFE_PREVIEWS = SERVER_LOFI_ON;
+// Combination of all currently supported previews.
+const PreviewsState ALL_SUPPORTED_PREVIEWS =
+ SERVER_LITE_PAGE_ON | NOSCRIPT_ON | RESOURCE_LOADING_HINTS_ON |
+ OFFLINE_PAGE_ON | LITE_PAGE_REDIRECT_ON;
+
// Ensure that content::PreviewsState and blink::WebURLRequest::PreviewsState
// are kept in sync.
STATIC_ASSERT_PREVIEWS_ENUM(PREVIEWS_UNSPECIFIED,
diff --git a/chromium/content/public/common/push_messaging_status.mojom b/chromium/content/public/common/push_messaging_status.mojom
deleted file mode 100644
index b4a7d957dc3..00000000000
--- a/chromium/content/public/common/push_messaging_status.mojom
+++ /dev/null
@@ -1,244 +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.
-
-module content.mojom;
-
-// Push message event success/error codes for internal use & reporting in UMA.
-// Enum values can be added, but must never be renumbered or deleted and reused.
-enum PushDeliveryStatus {
- // The message was successfully delivered.
- SUCCESS = 0,
-
- // The message could not be delivered because the app id was unknown.
- UNKNOWN_APP_ID = 2,
-
- // The message could not be delivered because origin no longer has permission.
- PERMISSION_DENIED = 3,
-
- // The message could not be delivered because no service worker was found.
- NO_SERVICE_WORKER = 4,
-
- // The message could not be delivered because of a service worker error.
- SERVICE_WORKER_ERROR = 5,
-
- // The message was delivered, but the Service Worker passed a Promise to
- // event.waitUntil that got rejected.
- EVENT_WAITUNTIL_REJECTED = 6,
-
- // The message was delivered, but the Service Worker timed out processing it.
- TIMEOUT = 7,
-
- // NOTE: Do not renumber or delete these as that would confuse interpretation
- // of previously logged data. When making changes, also update the enum list
- // in tools/metrics/histograms/histograms.xml to keep it in sync.
-};
-
-// Push getregistration success/error codes for internal use & reporting in UMA.
-// Enum values can be added, but must never be renumbered or deleted and reused.
-enum PushGetRegistrationStatus {
- // Getting the registration was successful.
- SUCCESS = 0,
-
- // Getting the registration failed because the push service is not available.
- SERVICE_NOT_AVAILABLE = 1,
-
- // Getting the registration failed because we failed to read from storage.
- STORAGE_ERROR = 2,
-
- // Getting the registration failed because there is no push registration.
- REGISTRATION_NOT_FOUND = 3,
-
- // Getting the registration failed because the push service isn't available in
- // incognito, but we tell JS registration not found to not reveal incognito.
- INCOGNITO_REGISTRATION_NOT_FOUND = 4,
-
- // Getting the registration failed because public key could not be retrieved.
- // PUBLIC_KEY_UNAVAILABLE = 5,
-
- // Getting the registration failed because storage was corrupt.
- STORAGE_CORRUPT = 6,
-
- // Getting the registration failed because the renderer was shut down.
- RENDERER_SHUTDOWN = 7,
-
- // Getting the registration failed because there was no live service worker.
- NO_LIVE_SERVICE_WORKER = 8,
-
- // NOTE: Do not renumber or delete these as that would confuse interpretation
- // of previously logged data. When making changes, also update the enum list
- // in tools/metrics/histograms/histograms.xml to keep it in sync.
-};
-
-// Push registration success/error codes for internal use & reporting in UMA.
-// Enum values can be added, but must never be renumbered or deleted and reused.
-enum PushRegistrationStatus {
- // New successful registration (there was not yet a registration cached in
- // Service Worker storage, so the browser successfully registered with the
- // push service. This is likely to be a new push registration, though it's
- // possible that the push service had its own cache (for example if Chrome's
- // app data was cleared, we might have forgotten about a registration that the
- // push service still stores).
- SUCCESS_FROM_PUSH_SERVICE = 0,
-
- // Registration failed because there is no Service Worker.
- NO_SERVICE_WORKER = 1,
-
- // Registration failed because the push service is not available.
- SERVICE_NOT_AVAILABLE = 2,
-
- // Registration failed because the maximum number of registratons has been
- // reached.
- LIMIT_REACHED = 3,
-
- // Registration failed because permission was denied.
- PERMISSION_DENIED = 4,
-
- // Registration failed in the push service implemented by the embedder.
- SERVICE_ERROR = 5,
-
- // Registration failed because no sender id was provided by the page.
- NO_SENDER_ID = 6,
-
- // Registration succeeded, but we failed to persist it.
- STORAGE_ERROR = 7,
-
- // A successful registration was already cached in Service Worker storage.
- SUCCESS_FROM_CACHE = 8,
-
- // Registration failed due to a network error.
- NETWORK_ERROR = 9,
-
- // Registration failed because the push service is not available in incognito,
- // but we tell JS that permission was denied to not reveal incognito.
- INCOGNITO_PERMISSION_DENIED = 10,
-
- // Registration failed because the public key could not be retrieved.
- PUBLIC_KEY_UNAVAILABLE = 11,
-
- // Registration failed because the manifest could not be retrieved or was
- // empty.
- MANIFEST_EMPTY_OR_MISSING = 12,
-
- // Registration failed because a subscription with a different sender id
- // already exists.
- SENDER_ID_MISMATCH = 13,
-
- // Registration failed because storage was corrupt. It will be retried
- // automatically after unsubscribing to fix the corruption.
- STORAGE_CORRUPT = 14,
-
- // Registration failed because the renderer was shut down.
- RENDERER_SHUTDOWN = 15,
-
- // Registration was successful for a subscription that was already known by
- // the cache, but the push service returned a new subscription. This may
- // happen when a subscription is invalidated by the push service.
- SUCCESS_NEW_SUBSCRIPTION_FROM_PUSH_SERVICE = 16,
-
- // NOTE: Do not renumber or delete these as that would confuse interpretation
- // of previously logged data. When making changes, also update the enum list
- // in tools/metrics/histograms/histograms.xml to keep it in sync.
-};
-
-// Push unregistration reason for reporting in UMA. Enum values can be added,
-// but must never be renumbered or deleted and reused.
-enum PushUnregistrationReason {
- // Should never happen.
- UNKNOWN = 0,
-
- // Unregistering because the website called the unsubscribe API.
- JAVASCRIPT_API = 1,
-
- // Unregistering because the user manually revoked permission.
- PERMISSION_REVOKED = 2,
-
- // Automatic - incoming message's app id was unknown.
- DELIVERY_UNKNOWN_APP_ID = 3,
-
- // Automatic - incoming message's origin no longer has permission.
- DELIVERY_PERMISSION_DENIED = 4,
-
- // Automatic - incoming message's service worker was not found.
- DELIVERY_NO_SERVICE_WORKER = 5,
-
- // Automatic - GCM Store reset due to corruption.
- GCM_STORE_RESET = 6,
-
- // Unregistering because the service worker was unregistered.
- SERVICE_WORKER_UNREGISTERED = 7,
-
- // Website called subscribe API and the stored subscription was corrupt, so
- // it is being unsubscribed in order to attempt a clean subscription.
- SUBSCRIBE_STORAGE_CORRUPT = 8,
-
- // Website called getSubscription API and the stored subscription was corrupt.
- GET_SUBSCRIPTION_STORAGE_CORRUPT = 9,
-
- // The Service Worker database got wiped, most likely due to corruption.
- SERVICE_WORKER_DATABASE_WIPED = 10,
-
- // NOTE: Do not renumber or delete these as that would confuse interpretation
- // of previously logged data. When making changes, also update the enum list
- // in tools/metrics/histograms/histograms.xml to keep it in sync.
-};
-
-
-// Push unregistration success/error codes for internal use & reporting in UMA.
-// Enum values can be added, but must never be renumbered or deleted and reused.
-enum PushUnregistrationStatus {
- // The unregistration was successful.
- SUCCESS_UNREGISTERED = 0,
-
- // Unregistration was unnecessary, as the registration was not found.
- SUCCESS_WAS_NOT_REGISTERED = 1,
-
- // The unregistration did not happen because of a network error, but will be
- // retried until it succeeds.
- PENDING_NETWORK_ERROR = 2,
-
- // Unregistration failed because there is no Service Worker.
- NO_SERVICE_WORKER = 3,
-
- // Unregistration failed because the push service is not available.
- SERVICE_NOT_AVAILABLE = 4,
-
- // Unregistration failed in the push service implemented by the embedder, but
- // will be retried until it succeeds.
- PENDING_SERVICE_ERROR = 5,
-
- // Unregistration succeeded, but we failed to clear Service Worker storage.
- STORAGE_ERROR = 6,
-
- // Unregistration failed due to a network error.
- NETWORK_ERROR = 7,
-
- // NOTE: Do not renumber or delete these as that would confuse interpretation
- // of previously logged data. When making changes, also update the enum list
- // in tools/metrics/histograms/histograms.xml to keep it in sync.
-};
-
-// Push message user visible tracking for reporting in UMA. Enum values can be
-// added, but must never be renumbered or deleted and reused.
-enum PushUserVisibleStatus {
- // A notification was required and one (or more) were shown.
- REQUIRED_AND_SHOWN = 0,
-
- // A notification was not required, but one (or more) were shown anyway.
- NOT_REQUIRED_BUT_SHOWN = 1,
-
- // A notification was not required and none were shown.
- NOT_REQUIRED_AND_NOT_SHOWN = 2,
-
- // A notification was required, but none were shown. Fortunately, the site has
- // been well behaved recently so it was glossed over.
- REQUIRED_BUT_NOT_SHOWN_USED_GRACE = 3,
-
- // A notification was required, but none were shown. Unfortunately, the site
- // has run out of grace, so we had to show the user a generic notification.
- REQUIRED_BUT_NOT_SHOWN_GRACE_EXCEEDED = 4,
-
- // NOTE: Do not renumber or delete these as that would confuse interpretation
- // of previously logged data. When making changes, also update the enum list
- // in tools/metrics/histograms/histograms.xml to keep it in sync.
-};
diff --git a/chromium/content/public/common/push_subscription_options.h b/chromium/content/public/common/push_subscription_options.h
deleted file mode 100644
index 1a2da0a9e4c..00000000000
--- a/chromium/content/public/common/push_subscription_options.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_COMMON_PUSH_SUBSCRIPTION_OPTIONS_H_
-#define CONTENT_PUBLIC_COMMON_PUSH_SUBSCRIPTION_OPTIONS_H_
-
-#include <string>
-
-#include "content/common/content_export.h"
-
-namespace content {
-
-// Structure to hold the options provided from the web app developer as
-// part of asking for a new push subscription.
-struct CONTENT_EXPORT PushSubscriptionOptions {
- PushSubscriptionOptions() {}
- ~PushSubscriptionOptions() {}
-
- // Whether or not the app developer agrees to provide user visible
- // notifications whenever they receive a push message.
- bool user_visible_only = false;
-
- // The unique identifier of the application service which is used to
- // verify the push message before delivery. This could either be an ID
- // assigned by the developer console or the app server's public key.
- std::string sender_info;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_CONTENT_PUSH_SUBSCRIPTION_OPTIONS_H_
diff --git a/chromium/content/public/common/referrer.cc b/chromium/content/public/common/referrer.cc
index d1128fce1dc..de7849686d0 100644
--- a/chromium/content/public/common/referrer.cc
+++ b/chromium/content/public/common/referrer.cc
@@ -7,7 +7,7 @@
#include <string>
#include "base/command_line.h"
-#include "content/public/common/content_switches.h"
+#include "content/public/common/content_features.h"
#include "services/network/loader_util.h"
namespace content {
@@ -17,8 +17,7 @@ Referrer Referrer::SanitizeForRequest(const GURL& request,
const Referrer& referrer) {
Referrer sanitized_referrer(referrer.url.GetAsReferrer(), referrer.policy);
if (sanitized_referrer.policy == network::mojom::ReferrerPolicy::kDefault) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kReducedReferrerGranularity)) {
+ if (base::FeatureList::IsEnabled(features::kReducedReferrerGranularity)) {
sanitized_referrer.policy = network::mojom::ReferrerPolicy::
kNoReferrerWhenDowngradeOriginWhenCrossOrigin;
} else {
@@ -113,8 +112,7 @@ net::URLRequest::ReferrerPolicy Referrer::ReferrerPolicyForUrlRequest(
return net::URLRequest::
ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
case network::mojom::ReferrerPolicy::kDefault:
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kReducedReferrerGranularity)) {
+ if (base::FeatureList::IsEnabled(features::kReducedReferrerGranularity)) {
return net::URLRequest::
REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN;
}
@@ -156,8 +154,7 @@ network::mojom::ReferrerPolicy Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
}
net::URLRequest::ReferrerPolicy Referrer::GetDefaultReferrerPolicy() {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kReducedReferrerGranularity)) {
+ if (base::FeatureList::IsEnabled(features::kReducedReferrerGranularity)) {
return net::URLRequest::
REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN;
}
diff --git a/chromium/content/public/common/screen_info.cc b/chromium/content/public/common/screen_info.cc
index 488e3681027..3789daea236 100644
--- a/chromium/content/public/common/screen_info.cc
+++ b/chromium/content/public/common/screen_info.cc
@@ -14,7 +14,8 @@ bool ScreenInfo::operator==(const ScreenInfo& other) const {
return device_scale_factor == other.device_scale_factor &&
color_space == other.color_space && depth == other.depth &&
depth_per_component == other.depth_per_component &&
- is_monochrome == other.is_monochrome && rect == other.rect &&
+ is_monochrome == other.is_monochrome &&
+ display_frequency == other.display_frequency && rect == other.rect &&
available_rect == other.available_rect &&
orientation_type == other.orientation_type &&
orientation_angle == other.orientation_angle;
diff --git a/chromium/content/public/common/screen_info.h b/chromium/content/public/common/screen_info.h
index 4ed8427b6b2..c7dfd7a9681 100644
--- a/chromium/content/public/common/screen_info.h
+++ b/chromium/content/public/common/screen_info.h
@@ -38,6 +38,10 @@ struct CONTENT_EXPORT ScreenInfo {
// This can be true for black and white printers
bool is_monochrome = false;
+ // The display frequency in Hz of the monitor. Set to 0 if it fails in the
+ // monitor frequency query.
+ int display_frequency = 0;
+
// The display monitor rectangle in virtual-screen coordinates. Note that
// this may be negative.
gfx::Rect rect;
diff --git a/chromium/content/public/common/service_names.mojom b/chromium/content/public/common/service_names.mojom
index 86cf8c5ee3a..d51243a55d4 100644
--- a/chromium/content/public/common/service_names.mojom
+++ b/chromium/content/public/common/service_names.mojom
@@ -4,8 +4,15 @@
module content.mojom;
-// The default service name the browser identifies as when connecting to
-// the Service Manager.
+// The name of the global singleton service hosted within the Content browser
+// process. This service is generally granted unfettered access to arbitrary
+// capabilities. Its global instance can be used to access other services by
+// using the |ServiceManagerConnection::GetForProcess()| API.
+const string kSystemServiceName = "content_system";
+
+// The name for service instances spawned per BrowserContext in a unique
+// instance group, to isolate incoming interface requests from renderers spawned
+// for that BrowserContext.
const string kBrowserServiceName = "content_browser";
// The default service name used to identify the gpu process when connecting it
diff --git a/chromium/content/public/common/url_constants.cc b/chromium/content/public/common/url_constants.cc
index bd65fff8366..c0cce598606 100644
--- a/chromium/content/public/common/url_constants.cc
+++ b/chromium/content/public/common/url_constants.cc
@@ -9,7 +9,7 @@ namespace content {
// Before adding new chrome schemes please check with security@chromium.org.
// There are security implications associated with introducing new schemes.
-const char kChromeDevToolsScheme[] = "chrome-devtools";
+const char kChromeDevToolsScheme[] = "devtools";
const char kChromeErrorScheme[] = "chrome-error";
const char kChromeUIScheme[] = "chrome";
const char kGuestScheme[] = "chrome-guest";
diff --git a/chromium/content/public/common/url_loader_throttle.cc b/chromium/content/public/common/url_loader_throttle.cc
index 22af4268fb4..6c8489a1d29 100644
--- a/chromium/content/public/common/url_loader_throttle.cc
+++ b/chromium/content/public/common/url_loader_throttle.cc
@@ -60,6 +60,10 @@ void URLLoaderThrottle::WillOnCompleteWithError(
const network::URLLoaderCompletionStatus& status,
bool* defer) {}
+bool URLLoaderThrottle::makes_unsafe_redirect() const {
+ return false;
+}
+
URLLoaderThrottle::URLLoaderThrottle() {}
} // namespace content
diff --git a/chromium/content/public/common/url_loader_throttle.h b/chromium/content/public/common/url_loader_throttle.h
index 6ca56381203..f6a70946c67 100644
--- a/chromium/content/public/common/url_loader_throttle.h
+++ b/chromium/content/public/common/url_loader_throttle.h
@@ -113,8 +113,7 @@ class CONTENT_EXPORT URLLoaderThrottle {
// asynchronously touching the pointer in defer case is not valid)
// When |request->url| is modified it will make an internal redirect, which
// might have some side-effects: drop upload streams data might be dropped,
- // redirect count may be reached, and cross-origin redirect are not supported
- // (at least until we have the demand).
+ // redirect count may be reached.
//
// Implementations should be aware that throttling can happen multiple times
// for the same |request|, even after one instance of the same throttle
@@ -167,6 +166,11 @@ class CONTENT_EXPORT URLLoaderThrottle {
const network::URLLoaderCompletionStatus& status,
bool* defer);
+ // Must return true if the throttle may make cross-scheme redirects
+ // (which is usually considered unsafe, so allowed only if the setting
+ // is made very explicitly).
+ virtual bool makes_unsafe_redirect() const;
+
void set_delegate(Delegate* delegate) { delegate_ = delegate; }
protected:
diff --git a/chromium/content/public/common/url_utils_unittest.cc b/chromium/content/public/common/url_utils_unittest.cc
index 2205b9a9dc9..3921c6cc47b 100644
--- a/chromium/content/public/common/url_utils_unittest.cc
+++ b/chromium/content/public/common/url_utils_unittest.cc
@@ -5,6 +5,7 @@
#include "content/public/common/url_utils.h"
#include "build/build_config.h"
+#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -31,8 +32,8 @@ TEST(UrlUtilsTest, IsURLHandledByNetworkStack) {
}
TEST(UrlUtilsTest, IsSafeRedirectTarget) {
- EXPECT_FALSE(
- IsSafeRedirectTarget(GURL(), CreateValidURL("chrome://foo/bar.html")));
+ EXPECT_FALSE(IsSafeRedirectTarget(
+ GURL(), CreateValidURL(GetWebUIURLString("foo/bar.html"))));
EXPECT_TRUE(
IsSafeRedirectTarget(GURL(), CreateValidURL("http://foo/bar.html")));
EXPECT_FALSE(
diff --git a/chromium/content/public/common/user_agent.h b/chromium/content/public/common/user_agent.h
index 651fcbd050e..930fb5f71bd 100644
--- a/chromium/content/public/common/user_agent.h
+++ b/chromium/content/public/common/user_agent.h
@@ -7,11 +7,29 @@
#include <string>
+#include "base/strings/string_piece.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
+#include "third_party/blink/public/mojom/user_agent/user_agent_metadata.mojom.h"
namespace content {
+namespace frozen_user_agent_strings {
+
+const char kDesktop[] =
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, "
+ "like Gecko) Chrome/75.0.3764.0 Safari/537.36";
+const char kAndroid[] =
+ "Mozilla/5.0 (Linux; Android 9; Unspecified Device) "
+ "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3764.0 "
+ "Safari/537.36";
+const char kAndroidMobile[] =
+ "Mozilla/5.0 (Linux; Android 9; Unspecified Device) "
+ "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3764.0 Mobile "
+ "Safari/537.36";
+
+} // namespace frozen_user_agent_strings
+
// Returns the WebKit version, in the form "major.minor (branch@revision)".
CONTENT_EXPORT std::string GetWebKitVersion();
@@ -22,6 +40,10 @@ CONTENT_EXPORT std::string GetWebKitRevision();
// as an argument.
CONTENT_EXPORT std::string BuildOSCpuInfo(bool include_android_build_number);
+// Returns the frozen User-agent string for
+// https://github.com/WICG/ua-client-hints.
+CONTENT_EXPORT base::StringPiece GetFrozenUserAgent(bool mobile);
+
// Helper function to generate a full user agent string from a short
// product name.
CONTENT_EXPORT std::string BuildUserAgentFromProduct(
diff --git a/chromium/content/public/common/web_preferences.cc b/chromium/content/public/common/web_preferences.cc
index 1822036e406..e2f3d5b5e1f 100644
--- a/chromium/content/public/common/web_preferences.cc
+++ b/chromium/content/public/common/web_preferences.cc
@@ -87,7 +87,6 @@ WebPreferences::WebPreferences()
databases_enabled(false),
application_cache_enabled(false),
tabs_to_links(true),
- history_entry_requires_user_gesture(false),
disable_ipc_flooding_protection(false),
hyperlink_auditing_enabled(true),
allow_universal_access_from_file_urls(false),
@@ -182,6 +181,7 @@ WebPreferences::WebPreferences()
#else
double_tap_to_zoom_enabled(false),
#endif
+ fullscreen_supported(true),
#if !defined(OS_ANDROID)
text_autosizing_enabled(false),
#else
@@ -189,13 +189,11 @@ WebPreferences::WebPreferences()
font_scale_factor(1.0f),
device_scale_adjustment(1.0f),
force_enable_zoom(false),
- fullscreen_supported(true),
support_deprecated_target_density_dpi(false),
use_legacy_background_size_shorthand_behavior(false),
wide_viewport_quirk(false),
use_wide_viewport(true),
force_zero_layout_height(false),
- viewport_meta_layout_size_quirk(false),
viewport_meta_merge_content_quirk(false),
viewport_meta_non_user_scalable_quirk(false),
viewport_meta_zero_values_quirk(false),
diff --git a/chromium/content/public/common/web_preferences.h b/chromium/content/public/common/web_preferences.h
index a83015f3629..f9a996476d5 100644
--- a/chromium/content/public/common/web_preferences.h
+++ b/chromium/content/public/common/web_preferences.h
@@ -110,7 +110,6 @@ struct CONTENT_EXPORT WebPreferences {
bool databases_enabled;
bool application_cache_enabled;
bool tabs_to_links;
- bool history_entry_requires_user_gesture;
bool disable_ipc_flooding_protection;
bool hyperlink_auditing_enabled;
bool allow_universal_access_from_file_urls;
@@ -226,6 +225,8 @@ struct CONTENT_EXPORT WebPreferences {
bool double_tap_to_zoom_enabled;
+ bool fullscreen_supported;
+
bool text_autosizing_enabled;
// Representation of the Web App Manifest scope if any.
@@ -235,14 +236,12 @@ struct CONTENT_EXPORT WebPreferences {
float font_scale_factor;
float device_scale_adjustment;
bool force_enable_zoom;
- bool fullscreen_supported;
GURL default_video_poster_url;
bool support_deprecated_target_density_dpi;
bool use_legacy_background_size_shorthand_behavior;
bool wide_viewport_quirk;
bool use_wide_viewport;
bool force_zero_layout_height;
- bool viewport_meta_layout_size_quirk;
bool viewport_meta_merge_content_quirk;
bool viewport_meta_non_user_scalable_quirk;
bool viewport_meta_zero_values_quirk;
@@ -270,7 +269,6 @@ struct CONTENT_EXPORT WebPreferences {
// WebView sets this to false to retain old documentElement behaviour
// (http://crbug.com/761016).
bool scroll_top_left_interop_enabled;
-#else // defined(OS_ANDROID)
#endif // defined(OS_ANDROID)
// Enable forcibly modifying content rendering to result in a light on dark
diff --git a/chromium/content/public/renderer/BUILD.gn b/chromium/content/public/renderer/BUILD.gn
index bc03d93d80f..1f3e181fb46 100644
--- a/chromium/content/public/renderer/BUILD.gn
+++ b/chromium/content/public/renderer/BUILD.gn
@@ -40,7 +40,6 @@ target(link_target_type, "renderer_sources") {
"context_menu_client.h",
"document_state.cc",
"document_state.h",
- "media_stream_utils.h",
"pepper_plugin_instance.h",
"plugin_instance_throttler.h",
"render_accessibility.h",
diff --git a/chromium/content/public/renderer/associated_resource_fetcher.h b/chromium/content/public/renderer/associated_resource_fetcher.h
index 8cbf01a1458..eef6b924984 100644
--- a/chromium/content/public/renderer/associated_resource_fetcher.h
+++ b/chromium/content/public/renderer/associated_resource_fetcher.h
@@ -31,9 +31,9 @@ class CONTENT_EXPORT AssociatedResourceFetcher {
// successfully or not. If there is a failure, response and data will both be
// empty. |response| and |data| are both valid until the URLFetcher instance
// is destroyed.
- typedef base::Callback<void(const blink::WebURLResponse& response,
- const std::string& data)>
- Callback;
+ using StartCallback =
+ base::OnceCallback<void(const blink::WebURLResponse& response,
+ const std::string& data)>;
// Creates a AssociatedResourceFetcher for the specified resource. Caller
// takes
@@ -63,7 +63,7 @@ class CONTENT_EXPORT AssociatedResourceFetcher {
blink::mojom::RequestContextType request_context,
network::mojom::FetchRequestMode fetch_request_mode,
network::mojom::FetchCredentialsMode fetch_credentials_mode,
- const Callback& callback) = 0;
+ StartCallback callback) = 0;
// Manually cancel the request.
virtual void Cancel() = 0;
diff --git a/chromium/content/public/renderer/content_renderer_client.cc b/chromium/content/public/renderer/content_renderer_client.cc
index 0a6af92b088..1ac134ac613 100644
--- a/chromium/content/public/renderer/content_renderer_client.cc
+++ b/chromium/content/public/renderer/content_renderer_client.cc
@@ -23,7 +23,7 @@ SkBitmap* ContentRendererClient::GetSadWebViewBitmap() {
return nullptr;
}
-bool ContentRendererClient::MaybeCreateMimeHandlerView(
+bool ContentRendererClient::IsPluginHandledExternally(
RenderFrame* embedder_frame,
const blink::WebElement& owner_element,
const GURL& original_url,
@@ -236,11 +236,6 @@ GURL ContentRendererClient::OverrideFlashEmbedWithHTML(const GURL& url) {
return GURL();
}
-std::unique_ptr<base::ThreadPool::InitParams>
-ContentRendererClient::GetThreadPoolInitParams() {
- return nullptr;
-}
-
bool ContentRendererClient::IsIdleMediaSuspendEnabled() {
return true;
}
@@ -267,4 +262,14 @@ bool ContentRendererClient::IsSafeRedirectTarget(const GURL& url) {
void ContentRendererClient::DidSetUserAgent(const std::string& user_agent) {}
+bool ContentRendererClient::RequiresHtmlImports(const GURL& url) {
+ return false;
+}
+
+base::Optional<::media::AudioRendererAlgorithmParameters>
+ContentRendererClient::GetAudioRendererAlgorithmParameters(
+ media::AudioParameters audio_parameters) {
+ return base::nullopt;
+}
+
} // namespace content
diff --git a/chromium/content/public/renderer/content_renderer_client.h b/chromium/content/public/renderer/content_renderer_client.h
index fad5f104f01..31fcd7d89bf 100644
--- a/chromium/content/public/renderer/content_renderer_client.h
+++ b/chromium/content/public/renderer/content_renderer_client.h
@@ -22,6 +22,7 @@
#include "content/public/common/content_client.h"
#include "content/public/renderer/url_loader_throttle_provider.h"
#include "content/public/renderer/websocket_handshake_throttle_provider.h"
+#include "media/base/audio_parameters.h"
#include "media/base/supported_types.h"
#include "services/service_manager/public/mojom/service.mojom.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
@@ -86,17 +87,17 @@ class CONTENT_EXPORT ContentRendererClient {
// none.
virtual SkBitmap* GetSadWebViewBitmap();
- // Returns true if the embedder renders the contents of the |plugin_element|
- // in a cross-process frame using MimeHandlerView.
- virtual bool MaybeCreateMimeHandlerView(
+ // Returns true if the embedder renders the contents of the |plugin_element|,
+ // using external handlers, in a cross-process frame.
+ virtual bool IsPluginHandledExternally(
RenderFrame* embedder_frame,
const blink::WebElement& plugin_element,
const GURL& original_url,
const std::string& original_mime_type);
// Returns a scriptable object which implements custom javascript API for the
- // given element. This is used for MimeHandlerView in providing API such as
- // |postMessage| for <embed> and <object>.
+ // given element. This is used for external plugin handlers for providing
+ // custom API such as|postMessage| for <embed> and <object>.
virtual v8::Local<v8::Object> GetScriptableObject(
const blink::WebElement& plugin_element,
v8::Isolate* isolate);
@@ -336,6 +337,11 @@ class CONTENT_EXPORT ContentRendererClient {
// started.
virtual void SetRuntimeFeaturesDefaultsBeforeBlinkInitialization() {}
+ // Notifies that a service worker context is going to be initialized. No
+ // meaningful task has run on the worker thread at this point. This
+ // function is called from the worker thread.
+ virtual void WillInitializeServiceWorkerContextOnWorkerThread() {}
+
// Notifies that a service worker context has been created. This function
// is called from the worker thread.
virtual void DidInitializeServiceWorkerContextOnWorkerThread(
@@ -387,11 +393,6 @@ class CONTENT_EXPORT ContentRendererClient {
// An empty URL is returned if the URL is not overriden.
virtual GURL OverrideFlashEmbedWithHTML(const GURL& url);
- // Provides parameters for initializing the global thread pool. Default
- // params are used if this returns nullptr.
- virtual std::unique_ptr<base::ThreadPool::InitParams>
- GetThreadPoolInitParams();
-
// Whether the renderer allows idle media players to be automatically
// suspended after a period of inactivity.
virtual bool IsIdleMediaSuspendEnabled();
@@ -425,6 +426,17 @@ class CONTENT_EXPORT ContentRendererClient {
// The user agent string is given from the browser process. This is called at
// most once.
virtual void DidSetUserAgent(const std::string& user_agent);
+
+ // Returns true if |url| still requires native HTML imports. Used for Web UI
+ // pages.
+ // TODO(https://crbug.com/937747): Remove this function, when all WebUIs have
+ // been migrated to use the HTML Imports Polyfill.
+ virtual bool RequiresHtmlImports(const GURL& url);
+
+ // Optionally returns audio renderer algorithm parameters.
+ virtual base::Optional<::media::AudioRendererAlgorithmParameters>
+ GetAudioRendererAlgorithmParameters(
+ ::media::AudioParameters audio_parameters);
};
} // namespace content
diff --git a/chromium/content/public/renderer/media_stream_utils.h b/chromium/content/public/renderer/media_stream_utils.h
deleted file mode 100644
index 29100dbfcd4..00000000000
--- a/chromium/content/public/renderer/media_stream_utils.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_UTILS_H_
-#define CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_UTILS_H_
-
-#include <memory>
-
-#include "content/common/content_export.h"
-#include "media/capture/video_capture_types.h"
-
-namespace blink {
-class WebMediaStream;
-}
-
-namespace media {
-class VideoCapturerSource;
-}
-
-namespace content {
-// This method creates a WebMediaStreamSource + MediaStreamSource pair with the
-// provided video capturer source. A new WebMediaStreamTrack +
-// MediaStreamTrack pair is created, connected to the source and is plugged into
-// the WebMediaStream (|web_media_stream|).
-// |is_remote| should be true if the source of the data is not a local device.
-// |is_readonly| should be true if the format of the data cannot be changed by
-// MediaTrackConstraints.
-CONTENT_EXPORT bool AddVideoTrackToMediaStream(
- std::unique_ptr<media::VideoCapturerSource> video_source,
- bool is_remote,
- blink::WebMediaStream* web_media_stream);
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_UTILS_H_
diff --git a/chromium/content/public/renderer/render_frame.h b/chromium/content/public/renderer/render_frame.h
index 3e239418df4..36b2f871e6e 100644
--- a/chromium/content/public/renderer/render_frame.h
+++ b/chromium/content/public/renderer/render_frame.h
@@ -189,7 +189,7 @@ class CONTENT_EXPORT RenderFrame : public IPC::Listener,
// |unthrottle_callback| will be called.
virtual void RegisterPeripheralPlugin(
const url::Origin& content_origin,
- const base::Closure& unthrottle_callback) = 0;
+ base::OnceClosure unthrottle_callback) = 0;
// Returns the peripheral content heuristic decision.
//
diff --git a/chromium/content/public/renderer/render_frame_observer.h b/chromium/content/public/renderer/render_frame_observer.h
index 8935697155f..015386282c6 100644
--- a/chromium/content/public/renderer/render_frame_observer.h
+++ b/chromium/content/public/renderer/render_frame_observer.h
@@ -32,8 +32,8 @@ class GURL;
namespace blink {
class WebDocumentLoader;
+class WebElement;
class WebFormElement;
-class WebNode;
class WebString;
struct WebURLError;
class WebWorkerFetchContext;
@@ -116,7 +116,6 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
virtual void WillReleaseScriptContext(v8::Local<v8::Context> context,
int world_id) {}
virtual void DidClearWindowObject() {}
- virtual void DidChangeManifest() {}
virtual void DidChangeScrollOffset() {}
virtual void WillSendSubmitEvent(const blink::WebFormElement& form) {}
virtual void WillSubmitForm(const blink::WebFormElement& form) {}
@@ -169,8 +168,11 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
// Reports that visible elements in the frame shifted (bit.ly/lsm-explainer).
// This is called once for each janking animation frame, with the jank
// fraction for that frame. The cumulative jank score can be inferred by
- // summing the jank fractions.
- virtual void DidObserveLayoutJank(double jank_fraction) {}
+ // summing the jank fractions. |after_input_or_scroll| indicates whether the
+ // given |jank_fraction| was observed after an input or scroll occurred in the
+ // associated document.
+ virtual void DidObserveLayoutJank(double jank_fraction,
+ bool after_input_or_scroll) {}
// Reports lazy loaded behavior when the frame or image is fully deferred or
// if the frame or image is loaded after being deferred by lazy load.
@@ -202,8 +204,8 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
virtual void DidReceiveTransferSizeUpdate(int resource_id,
int received_data_length) {}
- // Called when the focused node has changed to |node|.
- virtual void FocusedNodeChanged(const blink::WebNode& node) {}
+ // Called when the focused element has changed to |element|.
+ virtual void FocusedElementChanged(const blink::WebElement& element) {}
// Called when accessibility is enabled or disabled.
virtual void AccessibilityModeChanged() {}
diff --git a/chromium/content/public/renderer/render_thread.h b/chromium/content/public/renderer/render_thread.h
index 921a9e87865..f59318b8050 100644
--- a/chromium/content/public/renderer/render_thread.h
+++ b/chromium/content/public/renderer/render_thread.h
@@ -81,6 +81,9 @@ class CONTENT_EXPORT RenderThread : virtual public ChildThread {
virtual void SetResourceDispatcherDelegate(
ResourceDispatcherDelegate* delegate) = 0;
+ // DEPRECATED: Use mojo::Create*SharedMemoryRegion (see
+ // mojo/public/cpp/base/shared_memory_utils.h) instead.
+ //
// Asks the host to create a block of shared memory for the renderer.
// The shared memory allocated by the host is returned back.
virtual std::unique_ptr<base::SharedMemory> HostAllocateSharedMemoryBuffer(
@@ -90,7 +93,8 @@ class CONTENT_EXPORT RenderThread : virtual public ChildThread {
virtual void RegisterExtension(std::unique_ptr<v8::Extension> extension) = 0;
// Post task to all worker threads. Returns number of workers.
- virtual int PostTaskToAllWebWorkers(const base::Closure& closure) = 0;
+ virtual int PostTaskToAllWebWorkers(
+ const base::RepeatingClosure& closure) = 0;
// Resolve the proxy servers to use for a given url. On success true is
// returned and |proxy_list| is set to a PAC string containing a list of
diff --git a/chromium/content/public/renderer/render_view.h b/chromium/content/public/renderer/render_view.h
index dee1d18ce1a..b454d8a8753 100644
--- a/chromium/content/public/renderer/render_view.h
+++ b/chromium/content/public/renderer/render_view.h
@@ -19,7 +19,6 @@
namespace blink {
class WebElement;
-class WebFrameWidget;
class WebView;
struct WebRect;
} // namespace blink
@@ -83,9 +82,6 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
// Returns the associated WebView. May return NULL when the view is closing.
virtual blink::WebView* GetWebView() = 0;
- // Returns the associated WebFrameWidget.
- virtual blink::WebFrameWidget* GetWebFrameWidget() = 0;
-
// Whether content state (such as form state, scroll position and page
// contents) should be sent to the browser immediately. This is normally
// false, but set to true by some tests.
diff --git a/chromium/content/public/renderer/render_view_observer.h b/chromium/content/public/renderer/render_view_observer.h
index 3eb08a31072..4119177809b 100644
--- a/chromium/content/public/renderer/render_view_observer.h
+++ b/chromium/content/public/renderer/render_view_observer.h
@@ -11,12 +11,9 @@
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
-class GURL;
-
namespace blink {
class WebGestureEvent;
class WebLocalFrame;
-struct WebURLError;
}
namespace content {
@@ -35,10 +32,6 @@ class CONTENT_EXPORT RenderViewObserver : public IPC::Listener,
virtual void OnDestruct() = 0;
// These match the WebKit API notifications
- virtual void DidFailProvisionalLoad(blink::WebLocalFrame* frame,
- const blink::WebURLError& error) {}
- virtual void DidCommitProvisionalLoad(blink::WebLocalFrame* frame,
- bool is_new_navigation) {}
virtual void DidClearWindowObject(blink::WebLocalFrame* frame) {}
virtual void DidCommitCompositorFrame() {}
virtual void DidUpdateMainFrameLayout() {}
@@ -46,9 +39,6 @@ class CONTENT_EXPORT RenderViewObserver : public IPC::Listener,
// These match the RenderView methods.
virtual void DidHandleGestureEvent(const blink::WebGestureEvent& event) {}
- // These match incoming IPCs.
- virtual void Navigate(const GURL& url) {}
-
virtual void OnZoomLevelChanged() {}
// IPC::Listener implementation.
diff --git a/chromium/content/public/renderer/resource_fetcher.h b/chromium/content/public/renderer/resource_fetcher.h
index d764940f096..ffd1eb8e756 100644
--- a/chromium/content/public/renderer/resource_fetcher.h
+++ b/chromium/content/public/renderer/resource_fetcher.h
@@ -41,7 +41,7 @@ namespace content {
// canceled, and the callback will not be called.
class CONTENT_EXPORT ResourceFetcher {
public:
- using Callback =
+ using StartCallback =
base::OnceCallback<void(const blink::WebURLResponse& response,
const std::string& data)>;
@@ -69,7 +69,7 @@ class CONTENT_EXPORT ResourceFetcher {
blink::mojom::RequestContextType request_context,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const net::NetworkTrafficAnnotationTag& annotation_tag,
- Callback callback,
+ StartCallback callback,
size_t maximum_download_size = kDefaultMaximumDownloadSize) = 0;
// Sets how long to wait for the server to reply. By default, there is no
diff --git a/chromium/content/public/renderer/v8_value_converter.h b/chromium/content/public/renderer/v8_value_converter.h
index 85538b83e15..1e402e2a295 100644
--- a/chromium/content/public/renderer/v8_value_converter.h
+++ b/chromium/content/public/renderer/v8_value_converter.h
@@ -30,10 +30,6 @@ class CONTENT_EXPORT V8ValueConverter {
// Extends the default behaviour of V8ValueConverter.
class CONTENT_EXPORT Strategy {
public:
- typedef base::Callback<std::unique_ptr<base::Value>(v8::Local<v8::Value>,
- v8::Isolate* isolate)>
- FromV8ValueCallback;
-
virtual ~Strategy() {}
// If false is returned, V8ValueConverter proceeds with the default
@@ -42,8 +38,7 @@ class CONTENT_EXPORT V8ValueConverter {
// the ValueConverter's internal checks for depth and cycles.
virtual bool FromV8Object(v8::Local<v8::Object> value,
std::unique_ptr<base::Value>* out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback);
+ v8::Isolate* isolate);
// If false is returned, V8ValueConverter proceeds with the default
// behavior.
@@ -51,8 +46,7 @@ class CONTENT_EXPORT V8ValueConverter {
// the ValueConverter's internal checks for depth and cycles.
virtual bool FromV8Array(v8::Local<v8::Array> value,
std::unique_ptr<base::Value>* out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback);
+ v8::Isolate* isolate);
// If false is returned, V8ValueConverter proceeds with the default
// behavior. v8::Object is passed as ArrayBuffer and ArrayBufferView
diff --git a/chromium/content/public/utility/content_utility_client.h b/chromium/content/public/utility/content_utility_client.h
index 30a0869a39a..09a11906f53 100644
--- a/chromium/content/public/utility/content_utility_client.h
+++ b/chromium/content/public/utility/content_utility_client.h
@@ -10,6 +10,7 @@
#include "base/callback_forward.h"
#include "content/public/common/content_client.h"
+#include "services/service_manager/public/cpp/binder_map.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/service.h"
#include "services/service_manager/public/mojom/service.mojom.h"
@@ -44,8 +45,7 @@ class CONTENT_EXPORT ContentUtilityClient {
virtual void RegisterNetworkBinders(
service_manager::BinderRegistry* registry) {}
- virtual void RegisterAudioBinders(service_manager::BinderRegistry* registry) {
- }
+ virtual void RegisterAudioBinders(service_manager::BinderMap* binders) {}
};
} // namespace content
diff --git a/chromium/content/renderer/BUILD.gn b/chromium/content/renderer/BUILD.gn
index 3b3080e9bf8..b266299e86f 100644
--- a/chromium/content/renderer/BUILD.gn
+++ b/chromium/content/renderer/BUILD.gn
@@ -28,6 +28,7 @@ target(link_target_type, "renderer") {
"//content/app:*",
"//content/public/renderer:renderer_sources",
"//content/renderer:audio_decoder_fuzzer",
+ "//chromecast/media/audio:*",
]
sources = [
@@ -41,15 +42,11 @@ target(link_target_type, "renderer") {
"accessibility/blink_ax_tree_source.h",
"accessibility/render_accessibility_impl.cc",
"accessibility/render_accessibility_impl.h",
- "android/renderer_date_time_picker.cc",
- "android/renderer_date_time_picker.h",
"android/synchronous_compositor_proxy.cc",
"android/synchronous_compositor_proxy.h",
"android/synchronous_compositor_registry.h",
"android/synchronous_layer_tree_frame_sink.cc",
"android/synchronous_layer_tree_frame_sink.h",
- "appcache/web_application_cache_host_impl.cc",
- "appcache/web_application_cache_host_impl.h",
"blob_storage/webblobregistry_impl.cc",
"blob_storage/webblobregistry_impl.h",
"browser_plugin/browser_plugin.cc",
@@ -114,14 +111,10 @@ target(link_target_type, "renderer") {
"history_entry.h",
"history_serialization.cc",
"history_serialization.h",
- "image_capture/image_capture_frame_grabber.cc",
- "image_capture/image_capture_frame_grabber.h",
"image_downloader/image_downloader_base.cc",
"image_downloader/image_downloader_base.h",
"image_downloader/image_downloader_impl.cc",
"image_downloader/image_downloader_impl.h",
- "image_downloader/single_image_downloader.cc",
- "image_downloader/single_image_downloader.h",
"ime_event_guard.cc",
"ime_event_guard.h",
"in_process_renderer_thread.cc",
@@ -146,8 +139,6 @@ target(link_target_type, "renderer") {
"input/widget_input_handler_impl.h",
"input/widget_input_handler_manager.cc",
"input/widget_input_handler_manager.h",
- "installedapp/related_apps_fetcher.cc",
- "installedapp/related_apps_fetcher.h",
"internal_document_state_data.cc",
"internal_document_state_data.h",
"java/gin_java_bridge_dispatcher.cc",
@@ -182,8 +173,6 @@ target(link_target_type, "renderer") {
"loader/tracked_child_url_loader_factory_bundle.h",
"loader/url_loader_client_impl.cc",
"loader/url_loader_client_impl.h",
- "loader/web_data_consumer_handle_impl.cc",
- "loader/web_data_consumer_handle_impl.h",
"loader/web_url_loader_impl.cc",
"loader/web_url_loader_impl.h",
"loader/web_url_request_util.cc",
@@ -192,12 +181,8 @@ target(link_target_type, "renderer") {
"loader/web_worker_fetch_context_impl.h",
"low_memory_mode_controller.cc",
"low_memory_mode_controller.h",
- "manifest/manifest_change_notifier.cc",
- "manifest/manifest_change_notifier.h",
- "manifest/manifest_manager.cc",
- "manifest/manifest_manager.h",
- "manifest/manifest_uma_util.cc",
- "manifest/manifest_uma_util.h",
+ "media/android/flinging_renderer_client.cc",
+ "media/android/flinging_renderer_client.h",
"media/android/flinging_renderer_client_factory.cc",
"media/android/flinging_renderer_client_factory.h",
"media/android/media_player_renderer_client.cc",
@@ -321,8 +306,6 @@ target(link_target_type, "renderer") {
"media/webrtc/rtc_rtp_transceiver.h",
"media/webrtc/rtc_stats.cc",
"media/webrtc/rtc_stats.h",
- "media/webrtc/rtc_video_decoder.cc",
- "media/webrtc/rtc_video_decoder.h",
"media/webrtc/rtc_video_decoder_adapter.cc",
"media/webrtc/rtc_video_decoder_adapter.h",
"media/webrtc/rtc_video_decoder_factory.cc",
@@ -367,12 +350,8 @@ target(link_target_type, "renderer") {
"media/webrtc_local_audio_source_provider.h",
"media/webrtc_logging.cc",
"media/webrtc_logging.h",
- "media_capture_from_element/canvas_capture_handler.cc",
- "media_capture_from_element/canvas_capture_handler.h",
"media_capture_from_element/html_audio_element_capturer_source.cc",
"media_capture_from_element/html_audio_element_capturer_source.h",
- "media_capture_from_element/html_video_element_capturer_source.cc",
- "media_capture_from_element/html_video_element_capturer_source.h",
"media_recorder/audio_track_encoder.cc",
"media_recorder/audio_track_encoder.h",
"media_recorder/audio_track_opus_encoder.cc",
@@ -389,7 +368,6 @@ target(link_target_type, "renderer") {
"media_recorder/video_track_recorder.h",
"media_recorder/vpx_encoder.cc",
"media_recorder/vpx_encoder.h",
- "media_stream_utils.cc",
"menu_item_builder.cc",
"menu_item_builder.h",
"mhtml_handle_writer.cc",
@@ -434,8 +412,8 @@ target(link_target_type, "renderer") {
"peripheral_content_heuristic.h",
"push_messaging/push_messaging_client.cc",
"push_messaging/push_messaging_client.h",
- "push_messaging/push_provider.cc",
- "push_messaging/push_provider.h",
+ "push_messaging/push_messaging_utils.cc",
+ "push_messaging/push_messaging_utils.h",
"queue_message_swap_promise.cc",
"queue_message_swap_promise.h",
"render_frame_impl.cc",
@@ -470,8 +448,6 @@ target(link_target_type, "renderer") {
"renderer_main_platform_delegate_linux.cc",
"renderer_main_platform_delegate_mac.mm",
"renderer_main_platform_delegate_win.cc",
- "renderer_webapplicationcachehost_impl.cc",
- "renderer_webapplicationcachehost_impl.h",
"renderer_webcookiejar_impl.cc",
"renderer_webcookiejar_impl.h",
"resource_timing_info_conversions.cc",
@@ -484,8 +460,6 @@ target(link_target_type, "renderer") {
"seccomp_sandbox_status_android.h",
"service_worker/controller_service_worker_connector.cc",
"service_worker/controller_service_worker_connector.h",
- "service_worker/controller_service_worker_impl.cc",
- "service_worker/controller_service_worker_impl.h",
"service_worker/embedded_worker_instance_client_impl.cc",
"service_worker/embedded_worker_instance_client_impl.h",
"service_worker/navigation_preload_request.cc",
@@ -504,12 +478,8 @@ target(link_target_type, "renderer") {
"service_worker/service_worker_provider_state_for_client.h",
"service_worker/service_worker_subresource_loader.cc",
"service_worker/service_worker_subresource_loader.h",
- "service_worker/service_worker_timeout_timer.cc",
- "service_worker/service_worker_timeout_timer.h",
"service_worker/service_worker_type_converters.cc",
"service_worker/service_worker_type_converters.h",
- "service_worker/service_worker_type_util.cc",
- "service_worker/service_worker_type_util.h",
"service_worker/web_service_worker_provider_impl.cc",
"service_worker/web_service_worker_provider_impl.h",
"skia_benchmarking_extension.cc",
@@ -536,8 +506,6 @@ target(link_target_type, "renderer") {
"web_ui_extension_data.h",
"webgraphicscontext3d_provider_impl.cc",
"webgraphicscontext3d_provider_impl.h",
- "worker/application_cache_host_for_shared_worker.cc",
- "worker/application_cache_host_for_shared_worker.h",
"worker/dedicated_worker_host_factory_client.cc",
"worker/dedicated_worker_host_factory_client.h",
"worker/embedded_shared_worker_stub.cc",
@@ -602,13 +570,12 @@ target(link_target_type, "renderer") {
"//device/base/synchronization",
"//device/gamepad/public/cpp:shared_with_blink",
"//device/gamepad/public/mojom",
- "//device/usb/public/mojom",
"//gin",
"//gpu",
"//gpu/command_buffer/client:gles2_interface",
"//gpu/command_buffer/client:raster_interface",
"//gpu/command_buffer/client:webgpu_interface",
- "//jingle:jingle_glue",
+ "//jingle:webrtc_glue",
"//media",
"//media:media_buildflags",
"//media/blink",
@@ -632,6 +599,7 @@ target(link_target_type, "renderer") {
"//services/device/public/cpp/generic_sensor",
"//services/device/public/mojom",
"//services/device/public/mojom:constants",
+ "//services/device/public/mojom:usb",
"//services/image_annotation/public/cpp:cpp",
"//services/image_annotation/public/mojom:mojom",
"//services/metrics/public/cpp:metrics_cpp",
@@ -643,7 +611,6 @@ target(link_target_type, "renderer") {
"//storage/common",
"//third_party/blink/public:blink",
"//third_party/blink/public:buildflags",
- "//third_party/blink/public:mojo_bindings",
"//third_party/blink/public/common",
"//third_party/boringssl",
"//third_party/icu",
@@ -651,7 +618,7 @@ target(link_target_type, "renderer") {
"//third_party/libyuv",
"//third_party/opus",
"//third_party/sqlite",
- "//third_party/webrtc/api:create_peerconnection_factory",
+ "//third_party/webrtc/api:callfactory_api",
"//third_party/webrtc/api:libjingle_logging_api",
"//third_party/webrtc/api:libjingle_peerconnection_api",
"//third_party/webrtc/api:rtc_stats_api",
@@ -668,14 +635,18 @@ target(link_target_type, "renderer") {
"//third_party/webrtc/api/audio_codecs/g722:audio_encoder_g722",
"//third_party/webrtc/api/audio_codecs/isac:audio_decoder_isac",
"//third_party/webrtc/api/audio_codecs/isac:audio_encoder_isac",
+ "//third_party/webrtc/api/audio_codecs/opus:audio_decoder_multiopus",
"//third_party/webrtc/api/audio_codecs/opus:audio_decoder_opus",
+ "//third_party/webrtc/api/audio_codecs/opus:audio_encoder_multiopus",
"//third_party/webrtc/api/audio_codecs/opus:audio_encoder_opus",
+ "//third_party/webrtc/api/rtc_event_log:rtc_event_log_factory",
"//third_party/webrtc/api/video:video_bitrate_allocation",
"//third_party/webrtc/api/video:video_frame",
"//third_party/webrtc/api/video:video_frame_i420",
"//third_party/webrtc/api/video_codecs:rtc_software_fallback_wrappers",
"//third_party/webrtc/api/video_codecs:video_codecs_api",
"//third_party/webrtc/common_video:common_video",
+ "//third_party/webrtc/media:rtc_audio_video",
"//third_party/webrtc/media:rtc_internal_video_codecs",
"//third_party/webrtc/media:rtc_media",
"//third_party/webrtc/media:rtc_media_base",
@@ -726,12 +697,6 @@ target(link_target_type, "renderer") {
]
allow_circular_includes_from = []
- if (use_aura) {
- public_deps += [ "//content/renderer/mus" ]
- allow_circular_includes_from += [ "//content/renderer/mus" ]
- deps += [ "//services/ws/public/cpp" ]
- }
-
if (use_external_popup_menu) {
sources += [
"external_popup_menu.cc",
diff --git a/chromium/content/renderer/DEPS b/chromium/content/renderer/DEPS
index c6c43f5c4d9..3b0f954cce9 100644
--- a/chromium/content/renderer/DEPS
+++ b/chromium/content/renderer/DEPS
@@ -15,7 +15,6 @@ include_rules = [
"+device/base/synchronization",
"+device/gamepad/public/cpp",
"+device/gamepad/public/mojom",
- "+device/usb/public",
"+gin",
"+jingle/glue",
"+mojo",
diff --git a/chromium/content/renderer/accessibility/aom_content_ax_tree.cc b/chromium/content/renderer/accessibility/aom_content_ax_tree.cc
index a23339d1679..16b588f3a43 100644
--- a/chromium/content/renderer/accessibility/aom_content_ax_tree.cc
+++ b/chromium/content/renderer/accessibility/aom_content_ax_tree.cc
@@ -258,10 +258,10 @@ bool AomContentAxTree::GetParentIdForAXNode(int32_t ax_id, int32_t* out_param) {
bool AomContentAxTree::GetFirstChildIdForAXNode(int32_t ax_id,
int32_t* out_param) {
ui::AXNode* node = tree_.GetFromId(ax_id);
- if (!node || !node->child_count())
+ if (!node || node->children().empty())
return false;
- ui::AXNode* child = node->ChildAtIndex(0);
+ ui::AXNode* child = node->children().front();
DCHECK(child);
*out_param = child->id();
return true;
@@ -270,10 +270,10 @@ bool AomContentAxTree::GetFirstChildIdForAXNode(int32_t ax_id,
bool AomContentAxTree::GetLastChildIdForAXNode(int32_t ax_id,
int32_t* out_param) {
ui::AXNode* node = tree_.GetFromId(ax_id);
- if (!node || !node->child_count())
+ if (!node || node->children().empty())
return false;
- ui::AXNode* child = node->ChildAtIndex(node->child_count() - 1);
+ ui::AXNode* child = node->children().back();
DCHECK(child);
*out_param = child->id();
return true;
@@ -284,14 +284,14 @@ bool AomContentAxTree::GetPreviousSiblingIdForAXNode(int32_t ax_id,
ui::AXNode* node = tree_.GetFromId(ax_id);
if (!node)
return false;
- int index_in_parent = node->index_in_parent();
+ size_t index_in_parent = node->index_in_parent();
// Assumption: only when this node is the first child, does it not have a
// previous sibling.
if (index_in_parent == 0)
return false;
- ui::AXNode* sibling = node->parent()->ChildAtIndex(index_in_parent - 1);
+ ui::AXNode* sibling = node->parent()->children()[index_in_parent - 1];
DCHECK(sibling);
*out_param = sibling->id();
return true;
@@ -302,14 +302,14 @@ bool AomContentAxTree::GetNextSiblingIdForAXNode(int32_t ax_id,
ui::AXNode* node = tree_.GetFromId(ax_id);
if (!node)
return false;
- int index_in_parent = node->index_in_parent();
+ size_t next_index_in_parent = node->index_in_parent() + 1;
// Assumption: When this node is the last child, it does not have a next
// sibling.
- if (index_in_parent == (node->parent()->child_count() - 1))
+ if (next_index_in_parent == node->parent()->children().size())
return false;
- ui::AXNode* sibling = node->parent()->ChildAtIndex(index_in_parent + 1);
+ ui::AXNode* sibling = node->parent()->children()[next_index_in_parent];
DCHECK(sibling);
*out_param = sibling->id();
return true;
diff --git a/chromium/content/renderer/accessibility/ax_image_annotator.cc b/chromium/content/renderer/accessibility/ax_image_annotator.cc
index 06a8fb95f6c..be98889d62c 100644
--- a/chromium/content/renderer/accessibility/ax_image_annotator.cc
+++ b/chromium/content/renderer/accessibility/ax_image_annotator.cc
@@ -206,10 +206,12 @@ AXImageAnnotator::ImageInfo::GetImageProcessor() {
bool AXImageAnnotator::ImageInfo::HasAnnotation() const {
switch (status_) {
case ax::mojom::ImageAnnotationStatus::kNone:
+ case ax::mojom::ImageAnnotationStatus::kWillNotAnnotateDueToScheme:
case ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation:
// The user hasn't requested an annotation yet, or a previously pending
// annotation request had been cancelled.
case ax::mojom::ImageAnnotationStatus::kEligibleForAnnotation:
+ case ax::mojom::ImageAnnotationStatus::kSilentlyEligibleForAnnotation:
case ax::mojom::ImageAnnotationStatus::kAnnotationPending:
return false;
case ax::mojom::ImageAnnotationStatus::kAnnotationSucceeded:
@@ -254,9 +256,14 @@ void AXImageAnnotator::OnImageAnnotated(
DLOG(WARNING) << "Image annotation error.";
switch (result->get_error_code()) {
case image_annotation::mojom::AnnotateImageError::kCanceled:
+ // By marking the image as having an annotation status of
+ // kSilentlyEligibleForAnnotation and not one of
+ // kEligibleForAnnotation:, the user will not be asked to visit the
+ // context menu to turn on automatic image labels, because there is no
+ // way to repeat the operation from that menu yet.
image_annotations_.at(image.AxID())
- .set_status(
- ax::mojom::ImageAnnotationStatus::kEligibleForAnnotation);
+ .set_status(ax::mojom::ImageAnnotationStatus::
+ kSilentlyEligibleForAnnotation);
break;
case image_annotation::mojom::AnnotateImageError::kFailure:
image_annotations_.at(image.AxID())
diff --git a/chromium/content/renderer/accessibility/ax_image_annotator.h b/chromium/content/renderer/accessibility/ax_image_annotator.h
index 7cd5feccabc..9626e2672d5 100644
--- a/chromium/content/renderer/accessibility/ax_image_annotator.h
+++ b/chromium/content/renderer/accessibility/ax_image_annotator.h
@@ -93,7 +93,7 @@ class CONTENT_EXPORT AXImageAnnotator : public base::CheckedObserver {
virtual ContentClient* GetContentClient() const;
// Given a WebImage, it uses the URL of the main document and the src
- // attribute of the image, generates a unique identifier for the image that
+ // attribute of the image, to generate a unique identifier for the image that
// could be provided to the image annotation service.
//
// This method is virtual to allow overriding it from tests.
diff --git a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
index cca4b0d75dd..023b6035738 100644
--- a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
+++ b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
@@ -31,6 +31,11 @@ void AXStateFromBlink(const blink::WebAXObject& o, ui::AXNodeData* dst) {
if (o.IsDefault())
dst->AddState(ax::mojom::State::kDefault);
+ // aria-grabbed is deprecated in WAI-ARIA 1.1.
+ if (o.IsGrabbed() != blink::kWebAXGrabbedStateUndefined)
+ dst->AddBoolAttribute(ax::mojom::BoolAttribute::kGrabbed,
+ o.IsGrabbed() == blink::kWebAXGrabbedStateTrue);
+
if (o.IsHovered())
dst->AddState(ax::mojom::State::kHovered);
diff --git a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
index 79797f00f3d..37fc22b9106 100644
--- a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -44,6 +44,8 @@
#include "ui/accessibility/ax_enum_util.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/gfx/geometry/vector2d_f.h"
+#include "url/gurl.h"
+#include "url/url_constants.h"
using base::ASCIIToUTF16;
using base::UTF16ToUTF8;
@@ -384,14 +386,9 @@ bool BlinkAXTreeSource::GetTreeData(AXContentTreeData* tree_data) const {
WebAXObject anchor_object, focus_object;
int anchor_offset, focus_offset;
ax::mojom::TextAffinity anchor_affinity, focus_affinity;
- if (base::FeatureList::IsEnabled(features::kNewAccessibilitySelection)) {
root().Selection(is_selection_backward, anchor_object, anchor_offset,
anchor_affinity, focus_object, focus_offset,
focus_affinity);
- } else {
- root().SelectionDeprecated(anchor_object, anchor_offset, anchor_affinity,
- focus_object, focus_offset, focus_affinity);
- }
if (!anchor_object.IsNull() && !focus_object.IsNull() && anchor_offset >= 0 &&
focus_offset >= 0) {
int32_t anchor_id = anchor_object.AxID();
@@ -660,11 +657,6 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
src.FontWeight());
}
- if (src.HasPopup() != ax::mojom::HasPopup::kFalse)
- dst->SetHasPopup(src.HasPopup());
- else if (src.Role() == ax::mojom::Role::kPopUpButton)
- dst->SetHasPopup(ax::mojom::HasPopup::kMenu);
-
if (src.AriaCurrentState() != ax::mojom::AriaCurrentState::kNone) {
dst->AddIntAttribute(ax::mojom::IntAttribute::kAriaCurrentState,
static_cast<int32_t>(src.AriaCurrentState()));
@@ -1037,18 +1029,10 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
if (src.IsControl() && !src.IsRichlyEditable()) {
// Only for simple input controls -- rich editable areas use AXTreeData.
- if (base::FeatureList::IsEnabled(
- features::kNewAccessibilitySelection)) {
dst->AddIntAttribute(ax::mojom::IntAttribute::kTextSelStart,
src.SelectionStart());
dst->AddIntAttribute(ax::mojom::IntAttribute::kTextSelEnd,
src.SelectionEnd());
- } else {
- dst->AddIntAttribute(ax::mojom::IntAttribute::kTextSelStart,
- src.SelectionStartDeprecated());
- dst->AddIntAttribute(ax::mojom::IntAttribute::kTextSelEnd,
- src.SelectionEndDeprecated());
- }
}
}
@@ -1122,6 +1106,15 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
dst->AddStringAttribute(ax::mojom::StringAttribute::kImageDataUrl,
src.ImageDataUrl(max_image_data_size_).Utf8());
}
+
+ // aria-dropeffect is deprecated in WAI-ARIA 1.1.
+ WebVector<ax::mojom::Dropeffect> src_dropeffects;
+ src.Dropeffects(src_dropeffects);
+ if (!src_dropeffects.empty()) {
+ for (auto&& dropeffect : src_dropeffects) {
+ dst->AddDropeffect(dropeffect);
+ }
+ }
}
blink::WebDocument BlinkAXTreeSource::GetMainDocument() const {
@@ -1157,7 +1150,7 @@ void BlinkAXTreeSource::TruncateAndAddStringAttribute(
}
}
-void BlinkAXTreeSource::AddImageAnnotations(blink::WebAXObject src,
+void BlinkAXTreeSource::AddImageAnnotations(blink::WebAXObject& src,
AXContentNodeData* dst) const {
if (!base::FeatureList::IsEnabled(features::kExperimentalAccessibilityLabels))
return;
@@ -1214,7 +1207,6 @@ void BlinkAXTreeSource::AddImageAnnotations(blink::WebAXObject src,
// Skip images that are too small to label. This also catches
// unloaded images where the size is unknown.
-
WebAXObject offset_container;
WebFloatRect bounds;
SkMatrix44 container_transform;
@@ -1228,9 +1220,25 @@ void BlinkAXTreeSource::AddImageAnnotations(blink::WebAXObject src,
return;
}
- if (!image_annotator_) {
+ // Skip images in documents which are not http, https, file and data schemes.
+ GURL gurl = document().Url();
+ if (!(gurl.SchemeIsHTTPOrHTTPS() || gurl.SchemeIsFile() ||
+ gurl.SchemeIs(url::kDataScheme))) {
dst->SetImageAnnotationStatus(
- ax::mojom::ImageAnnotationStatus::kEligibleForAnnotation);
+ ax::mojom::ImageAnnotationStatus::kWillNotAnnotateDueToScheme);
+ return;
+ }
+
+ if (!image_annotator_) {
+ if (!first_unlabeled_image_id_.has_value() ||
+ first_unlabeled_image_id_.value() == src.AxID()) {
+ dst->SetImageAnnotationStatus(
+ ax::mojom::ImageAnnotationStatus::kEligibleForAnnotation);
+ first_unlabeled_image_id_ = src.AxID();
+ } else {
+ dst->SetImageAnnotationStatus(
+ ax::mojom::ImageAnnotationStatus::kSilentlyEligibleForAnnotation);
+ }
return;
}
diff --git a/chromium/content/renderer/accessibility/blink_ax_tree_source.h b/chromium/content/renderer/accessibility/blink_ax_tree_source.h
index 49dfc2667b5..5d05648674a 100644
--- a/chromium/content/renderer/accessibility/blink_ax_tree_source.h
+++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.h
@@ -9,6 +9,7 @@
#include <set>
+#include "base/optional.h"
#include "content/common/ax_content_node_data.h"
#include "third_party/blink/public/web/web_ax_object.h"
#include "third_party/blink/public/web/web_document.h"
@@ -76,9 +77,14 @@ class BlinkAXTreeSource
// The following methods add or remove an image annotator which is used to
// provide automatic labels for images.
void AddImageAnnotator(AXImageAnnotator* const annotator) {
+ DCHECK_EQ(image_annotator_, nullptr);
+ DCHECK(!first_unlabeled_image_id_.has_value());
image_annotator_ = annotator;
}
- void RemoveImageAnnotator() { image_annotator_ = nullptr; }
+ void RemoveImageAnnotator() {
+ image_annotator_ = nullptr;
+ first_unlabeled_image_id_ = base::nullopt;
+ }
// Query or update a set of IDs for which we should load inline text boxes.
bool ShouldLoadInlineTextBoxes(const blink::WebAXObject& obj) const;
@@ -129,8 +135,8 @@ class BlinkAXTreeSource
const std::string& value,
uint32_t max_len = kMaxStringAttributeLength) const;
- void AddImageAnnotations(blink::WebAXObject node,
- AXContentNodeData* out_data) const;
+ void AddImageAnnotations(blink::WebAXObject& src,
+ AXContentNodeData* dst) const;
RenderFrameImpl* render_frame_;
@@ -147,12 +153,19 @@ class BlinkAXTreeSource
gfx::Size max_image_data_size_;
+ // The class instance that retrieves and manages automatic labels for images.
AXImageAnnotator* image_annotator_ = nullptr;
// Whether we should highlight annotation results visually on the page
// for debugging.
bool image_annotation_debugging_ = false;
+ // The AxID of the first unlabeled image we have encountered in this tree.
+ //
+ // Used to ensure that the tutor message that explains to screen reader users
+ // how to turn on automatic image labels is provided only once.
+ mutable base::Optional<int32_t> first_unlabeled_image_id_ = base::nullopt;
+
// These are updated when calling |Freeze|.
bool frozen_ = false;
blink::WebDocument document_;
diff --git a/chromium/content/renderer/accessibility/render_accessibility_impl.cc b/chromium/content/renderer/accessibility/render_accessibility_impl.cc
index ffec479467c..f36d88a1457 100644
--- a/chromium/content/renderer/accessibility/render_accessibility_impl.cc
+++ b/chromium/content/renderer/accessibility/render_accessibility_impl.cc
@@ -139,7 +139,6 @@ RenderAccessibilityImpl::RenderAccessibilityImpl(RenderFrameImpl* render_frame,
last_scroll_offset_(gfx::Size()),
ack_pending_(false),
reset_token_(0),
- during_action_(false),
weak_factory_(this) {
ack_token_ = g_next_ack_token++;
WebView* web_view = render_frame_->GetRenderView()->GetWebView();
@@ -253,7 +252,6 @@ void RenderAccessibilityImpl::AccessibilityModeChanged() {
bool RenderAccessibilityImpl::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
- during_action_ = true;
IPC_BEGIN_MESSAGE_MAP(RenderAccessibilityImpl, message)
IPC_MESSAGE_HANDLER(AccessibilityMsg_PerformAction, OnPerformAction)
@@ -263,7 +261,6 @@ bool RenderAccessibilityImpl::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(AccessibilityMsg_FatalError, OnFatalError)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
- during_action_ = false;
return handled;
}
@@ -276,15 +273,16 @@ void RenderAccessibilityImpl::NotifyUpdate(
void RenderAccessibilityImpl::HandleWebAccessibilityEvent(
const WebAXObject& obj,
- ax::mojom::Event event) {
- HandleAXEvent(obj, event);
+ ax::mojom::Event event,
+ ax::mojom::EventFrom event_from) {
+ HandleAXEvent(obj, event, event_from);
}
void RenderAccessibilityImpl::MarkWebAXObjectDirty(const WebAXObject& obj,
bool subtree) {
DirtyObject dirty_object;
dirty_object.obj = obj;
- dirty_object.event_from = GetEventFrom();
+ dirty_object.event_from = ax::mojom::EventFrom::kAction;
dirty_objects_.push_back(dirty_object);
if (subtree)
@@ -310,13 +308,13 @@ void RenderAccessibilityImpl::HandleAccessibilityFindInPageResult(
Send(new AccessibilityHostMsg_FindInPageResult(routing_id(), params));
}
-void RenderAccessibilityImpl::AccessibilityFocusedNodeChanged(
- const WebNode& node) {
+void RenderAccessibilityImpl::AccessibilityFocusedElementChanged(
+ const WebElement& element) {
const WebDocument& document = GetMainDocument();
if (document.IsNull())
return;
- if (node.IsNull()) {
+ if (element.IsNull()) {
// When focus is cleared, implicitly focus the document.
// TODO(dmazzoni): Make Blink send this notification instead.
HandleAXEvent(WebAXObject::FromWebDocument(document),
@@ -326,6 +324,7 @@ void RenderAccessibilityImpl::AccessibilityFocusedNodeChanged(
void RenderAccessibilityImpl::HandleAXEvent(const WebAXObject& obj,
ax::mojom::Event event,
+ ax::mojom::EventFrom event_from,
int action_request_id) {
const WebDocument& document = GetMainDocument();
if (document.IsNull())
@@ -342,7 +341,8 @@ void RenderAccessibilityImpl::HandleAXEvent(const WebAXObject& obj,
last_scroll_offset_ = scroll_offset;
auto webax_object = WebAXObject::FromWebDocument(document);
if (!obj.Equals(webax_object)) {
- HandleAXEvent(webax_object, ax::mojom::Event::kLayoutComplete);
+ HandleAXEvent(webax_object, ax::mojom::Event::kLayoutComplete,
+ event_from);
}
}
}
@@ -380,7 +380,7 @@ void RenderAccessibilityImpl::HandleAXEvent(const WebAXObject& obj,
ui::AXEvent acc_event;
acc_event.id = obj.AxID();
acc_event.event_type = event;
- acc_event.event_from = GetEventFrom();
+ acc_event.event_from = event_from;
acc_event.action_request_id = action_request_id;
// Discard duplicate accessibility events.
@@ -416,18 +416,6 @@ void RenderAccessibilityImpl::ScheduleSendAccessibilityEventsIfNeeded() {
}
}
-ax::mojom::EventFrom RenderAccessibilityImpl::GetEventFrom() {
- if (blink::WebUserGestureIndicator::IsProcessingUserGesture(
- render_frame_->GetWebFrame())) {
- return ax::mojom::EventFrom::kUser;
- }
-
- if (during_action_)
- return ax::mojom::EventFrom::kAction;
-
- return ax::mojom::EventFrom::kPage;
-}
-
int RenderAccessibilityImpl::GenerateAXID() {
WebAXObject root = tree_source_.GetRoot();
return root.GenerateAXID();
@@ -562,6 +550,21 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() {
dirty_objects.push_back(dirty_object);
}
+ // Popups have a document lifecycle managed separately from the main document
+ // but we need to return a combined accessibility tree for both.
+ // We ensured layout validity for the main document in the loop above; if a
+ // popup is open, do the same for it.
+ WebDocument popup_document = GetPopupDocument();
+ if (!popup_document.IsNull()) {
+ WebAXObject popup_root_obj = WebAXObject::FromWebDocument(popup_document);
+ if (!popup_root_obj.UpdateLayoutAndCheckValidity()) {
+ // If a popup is open but we can't ensure its validity, return without
+ // sending an update bundle, the same as we would for a node in the main
+ // document.
+ return;
+ }
+ }
+
// Keep track of if the host node for a plugin has been invalidated,
// because if so, the plugin subtree will need to be re-serialized.
bool invalidate_plugin_subtree = false;
@@ -574,7 +577,9 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() {
std::set<int32_t> already_serialized_ids;
for (size_t i = 0; i < dirty_objects.size(); i++) {
auto obj = dirty_objects[i].obj;
- if (obj.IsDetached())
+ // Dirty objects can be added using MarkWebAXObjectDirty(obj) from other
+ // parts of the code as well, so we need to ensure the object still exists.
+ if (!obj.UpdateLayoutAndCheckValidity())
continue;
if (already_serialized_ids.find(obj.AxID()) != already_serialized_ids.end())
continue;
@@ -749,13 +754,8 @@ void RenderAccessibilityImpl::OnPerformAction(
WebPoint(data.target_point.x(), data.target_point.y()));
break;
case ax::mojom::Action::kSetSelection:
- if (base::FeatureList::IsEnabled(features::kNewAccessibilitySelection)) {
anchor.SetSelection(anchor, data.anchor_offset, focus,
data.focus_offset);
- } else {
- anchor.SetSelectionDeprecated(anchor, data.anchor_offset, focus,
- data.focus_offset);
- }
HandleAXEvent(root, ax::mojom::Event::kLayoutComplete);
break;
case ax::mojom::Action::kSetSequentialFocusNavigationStartingPoint:
@@ -852,7 +852,8 @@ void RenderAccessibilityImpl::OnHitTest(const gfx::Point& point,
}
// Otherwise, send an event on the node that was hit.
- HandleAXEvent(obj, event_to_fire, action_request_id);
+ HandleAXEvent(obj, event_to_fire, ax::mojom::EventFrom::kAction,
+ action_request_id);
}
void RenderAccessibilityImpl::OnLoadInlineTextBoxes(const WebAXObject& obj) {
@@ -1145,8 +1146,10 @@ void RenderAccessibilityImpl::AddImageAnnotationDebuggingAttributes(
bool should_set_attributes = false;
switch (status) {
case ax::mojom::ImageAnnotationStatus::kNone:
+ case ax::mojom::ImageAnnotationStatus::kWillNotAnnotateDueToScheme:
case ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation:
case ax::mojom::ImageAnnotationStatus::kEligibleForAnnotation:
+ case ax::mojom::ImageAnnotationStatus::kSilentlyEligibleForAnnotation:
break;
case ax::mojom::ImageAnnotationStatus::kAnnotationPending:
case ax::mojom::ImageAnnotationStatus::kAnnotationAdult:
@@ -1201,4 +1204,12 @@ void RenderAccessibilityImpl::AddImageAnnotationDebuggingAttributes(
}
}
+blink::WebDocument RenderAccessibilityImpl::GetPopupDocument() {
+ blink::WebPagePopup* popup =
+ render_frame_->GetRenderView()->GetWebView()->GetPagePopup();
+ if (popup)
+ return popup->GetDocument();
+ return WebDocument();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/accessibility/render_accessibility_impl.h b/chromium/content/renderer/accessibility/render_accessibility_impl.h
index 3a84790a911..852b99810c8 100644
--- a/chromium/content/renderer/accessibility/render_accessibility_impl.h
+++ b/chromium/content/renderer/accessibility/render_accessibility_impl.h
@@ -26,7 +26,6 @@
namespace blink {
class WebDocument;
-class WebNode;
} // namespace blink
namespace ui {
@@ -93,7 +92,8 @@ class CONTENT_EXPORT RenderAccessibilityImpl
// Called when an accessibility notification occurs in Blink.
void HandleWebAccessibilityEvent(const blink::WebAXObject& obj,
- ax::mojom::Event event);
+ ax::mojom::Event event,
+ ax::mojom::EventFrom event_from);
void MarkWebAXObjectDirty(const blink::WebAXObject& obj, bool subtree);
// Called when a new find in page result is highlighted.
@@ -105,11 +105,13 @@ class CONTENT_EXPORT RenderAccessibilityImpl
const blink::WebAXObject& end_object,
int end_offset);
- void AccessibilityFocusedNodeChanged(const blink::WebNode& node);
+ void AccessibilityFocusedElementChanged(const blink::WebElement& element);
- void HandleAXEvent(const blink::WebAXObject& obj,
- ax::mojom::Event event,
- int action_request_id = -1);
+ void HandleAXEvent(
+ const blink::WebAXObject& obj,
+ ax::mojom::Event event,
+ ax::mojom::EventFrom event_from = ax::mojom::EventFrom::kNone,
+ int action_request_id = -1);
// Returns the main top-level document for this page, or NULL if there's
// no view or frame.
@@ -162,12 +164,14 @@ class CONTENT_EXPORT RenderAccessibilityImpl
void Scroll(const blink::WebAXObject& target,
ax::mojom::Action scroll_action);
void ScrollPlugin(int id_to_make_visible);
- ax::mojom::EventFrom GetEventFrom();
void ScheduleSendAccessibilityEventsIfNeeded();
void RecordImageMetrics(AXContentTreeUpdate* update);
void AddImageAnnotationDebuggingAttributes(
const std::vector<AXContentTreeUpdate>& updates);
+ // Returns the document for the active popup if any.
+ blink::WebDocument GetPopupDocument();
+
// The RenderFrameImpl that owns us.
RenderFrameImpl* render_frame_;
@@ -221,9 +225,6 @@ class CONTENT_EXPORT RenderAccessibilityImpl
// We need to return this token in the next IPC.
int reset_token_;
- // Whether we are processing a client-initiated action.
- bool during_action_;
-
// Token to send with event messages so we know when they're acknowledged.
int ack_token_;
diff --git a/chromium/content/renderer/android/renderer_date_time_picker.cc b/chromium/content/renderer/android/renderer_date_time_picker.cc
deleted file mode 100644
index d5371437c5e..00000000000
--- a/chromium/content/renderer/android/renderer_date_time_picker.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/android/renderer_date_time_picker.h"
-
-#include <stddef.h>
-
-#include "base/strings/string_util.h"
-#include "content/common/date_time_suggestion.h"
-#include "content/common/view_messages.h"
-#include "content/renderer/render_view_impl.h"
-#include "third_party/blink/public/web/web_date_time_chooser_completion.h"
-#include "third_party/blink/public/web/web_date_time_chooser_params.h"
-#include "third_party/blink/public/web/web_date_time_input_type.h"
-#include "third_party/blink/public/web/web_date_time_suggestion.h"
-#include "ui/base/ime/text_input_type.h"
-
-using blink::WebString;
-
-namespace content {
-
-namespace {
-
-// Converts a |blink::WebDateTimeSuggestion| structure to |DateTimeSuggestion|.
-DateTimeSuggestion ToDateTimeSuggestion(
- const blink::WebDateTimeSuggestion& suggestion) {
- DateTimeSuggestion result;
- result.value = suggestion.value;
- result.localized_value = suggestion.localized_value.Utf16();
- result.label = suggestion.label.Utf16();
- return result;
-}
-
-} // namespace
-
-static ui::TextInputType ToTextInputType(int type) {
- switch (type) {
- case blink::kWebDateTimeInputTypeDate:
- return ui::TEXT_INPUT_TYPE_DATE;
- break;
- case blink::kWebDateTimeInputTypeDateTime:
- return ui::TEXT_INPUT_TYPE_DATE_TIME;
- break;
- case blink::kWebDateTimeInputTypeDateTimeLocal:
- return ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL;
- break;
- case blink::kWebDateTimeInputTypeMonth:
- return ui::TEXT_INPUT_TYPE_MONTH;
- break;
- case blink::kWebDateTimeInputTypeTime:
- return ui::TEXT_INPUT_TYPE_TIME;
- break;
- case blink::kWebDateTimeInputTypeWeek:
- return ui::TEXT_INPUT_TYPE_WEEK;
- break;
- case blink::kWebDateTimeInputTypeNone:
- default:
- return ui::TEXT_INPUT_TYPE_NONE;
- }
-}
-
-RendererDateTimePicker::RendererDateTimePicker(
- RenderViewImpl* sender,
- const blink::WebDateTimeChooserParams& params,
- blink::WebDateTimeChooserCompletion* completion)
- : RenderViewObserver(sender),
- chooser_params_(params),
- chooser_completion_(completion) {
-}
-
-RendererDateTimePicker::~RendererDateTimePicker() {
-}
-
-bool RendererDateTimePicker::Open() {
- ViewHostMsg_DateTimeDialogValue_Params message;
- message.dialog_type = ToTextInputType(chooser_params_.type);
- message.dialog_value = chooser_params_.double_value;
- message.minimum = chooser_params_.minimum;
- message.maximum = chooser_params_.maximum;
- message.step = chooser_params_.step;
- for (size_t i = 0; i < chooser_params_.suggestions.size(); i++) {
- message.suggestions.push_back(
- ToDateTimeSuggestion(chooser_params_.suggestions[i]));
- }
- return Send(new ViewHostMsg_OpenDateTimeDialog(routing_id(), message));
-}
-
-bool RendererDateTimePicker::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(RendererDateTimePicker, message)
- IPC_MESSAGE_HANDLER(ViewMsg_ReplaceDateTime, OnReplaceDateTime)
- IPC_MESSAGE_HANDLER(ViewMsg_CancelDateTimeDialog, OnCancel)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void RendererDateTimePicker::OnReplaceDateTime(double value) {
- if (chooser_completion_)
- chooser_completion_->DidChooseValue(value);
- static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog();
-}
-
-void RendererDateTimePicker::OnCancel() {
- if (chooser_completion_)
- chooser_completion_->DidCancelChooser();
- static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog();
-}
-
-void RendererDateTimePicker::OnDestruct() {
- delete this;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/android/renderer_date_time_picker.h b/chromium/content/renderer/android/renderer_date_time_picker.h
deleted file mode 100644
index 583619f8de0..00000000000
--- a/chromium/content/renderer/android/renderer_date_time_picker.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_ANDROID_RENDERER_DATE_TIME_PICKER_H_
-#define CONTENT_RENDERER_ANDROID_RENDERER_DATE_TIME_PICKER_H_
-
-#include "base/macros.h"
-#include "content/public/renderer/render_view_observer.h"
-#include "third_party/blink/public/web/web_date_time_chooser_params.h"
-
-namespace blink {
-class WebDateTimeChooserCompletion;
-} // namespace blink
-
-namespace content {
-class RenderViewImpl;
-
-class RendererDateTimePicker : public RenderViewObserver {
- public:
- RendererDateTimePicker(
- RenderViewImpl* sender,
- const blink::WebDateTimeChooserParams& params,
- blink::WebDateTimeChooserCompletion* completion);
- ~RendererDateTimePicker() override;
-
- bool Open();
-
- private:
- void OnReplaceDateTime(double value);
- void OnCancel();
-
- // RenderViewObserver
- bool OnMessageReceived(const IPC::Message& message) override;
- void OnDestruct() override;
-
- blink::WebDateTimeChooserParams chooser_params_;
- blink::WebDateTimeChooserCompletion* chooser_completion_; // Not owned by us
-
- DISALLOW_COPY_AND_ASSIGN(RendererDateTimePicker);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_ANDROID_RENDERER_DATE_TIME_PICKER_H_
diff --git a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc
index e40f9a331c1..3bfc48805bd 100644
--- a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc
+++ b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc
@@ -93,8 +93,8 @@ class SynchronousLayerTreeFrameSink::SoftwareOutputSurface
bool has_alpha,
bool use_stencil) override {}
uint32_t GetFramebufferCopyTextureFormat() override { return 0; }
- viz::OverlayCandidateValidator* GetOverlayCandidateValidator()
- const override {
+ std::unique_ptr<viz::OverlayCandidateValidator>
+ TakeOverlayCandidateValidator() override {
return nullptr;
}
bool IsDisplayedAsOverlayPlane() const override { return false; }
@@ -105,6 +105,12 @@ class SynchronousLayerTreeFrameSink::SoftwareOutputSurface
bool HasExternalStencilTest() const override { return false; }
void ApplyExternalStencil() override {}
unsigned UpdateGpuFence() override { return 0; }
+ void SetUpdateVSyncParametersCallback(
+ viz::UpdateVSyncParametersCallback callback) override {}
+ void SetDisplayTransformHint(gfx::OverlayTransform transform) override {}
+ gfx::OverlayTransform GetDisplayTransform() override {
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ }
};
base::TimeDelta SynchronousLayerTreeFrameSink::StubDisplayClient::
@@ -392,8 +398,8 @@ void SynchronousLayerTreeFrameSink::Invalidate(bool needs_draw) {
if (!fallback_tick_pending_) {
fallback_tick_.Reset(
- base::Bind(&SynchronousLayerTreeFrameSink::FallbackTickFired,
- base::Unretained(this)));
+ base::BindOnce(&SynchronousLayerTreeFrameSink::FallbackTickFired,
+ base::Unretained(this)));
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, fallback_tick_.callback(),
base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
diff --git a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h
index bdbbe3e71e9..a13591607a0 100644
--- a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h
+++ b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h
@@ -164,7 +164,7 @@ class SynchronousLayerTreeFrameSink
bool did_submit_frame_ = false;
scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
- base::CancelableClosure fallback_tick_;
+ base::CancelableOnceClosure fallback_tick_;
bool fallback_tick_pending_ = false;
bool fallback_tick_running_ = false;
diff --git a/chromium/content/renderer/appcache/OWNERS b/chromium/content/renderer/appcache/OWNERS
deleted file mode 100644
index ad46687e8ae..00000000000
--- a/chromium/content/renderer/appcache/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-file://content/browser/appcache/OWNERS
-
-# TEAM: storage-dev@chromium.org
-# COMPONENT: Blink>Storage>AppCache
diff --git a/chromium/content/renderer/appcache/web_application_cache_host_impl.cc b/chromium/content/renderer/appcache/web_application_cache_host_impl.cc
deleted file mode 100644
index 9c3a69dd05c..00000000000
--- a/chromium/content/renderer/appcache/web_application_cache_host_impl.cc
+++ /dev/null
@@ -1,358 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/appcache/web_application_cache_host_impl.h"
-
-#include <stddef.h>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/containers/id_map.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "content/common/appcache_interfaces.h"
-#include "content/public/common/service_names.mojom.h"
-#include "content/public/renderer/render_thread.h"
-#include "content/renderer/render_frame_impl.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/public/platform/web_url_response.h"
-
-using blink::WebApplicationCacheHost;
-using blink::WebApplicationCacheHostClient;
-using blink::WebString;
-using blink::WebURL;
-using blink::WebURLResponse;
-using blink::WebVector;
-
-namespace content {
-
-namespace {
-
-// Note: the order of the elements in this array must match those
-// of the EventID enum in appcache_interfaces.h.
-const char* const kEventNames[] = {
- "Checking", "Error", "NoUpdate", "Downloading", "Progress",
- "UpdateReady", "Cached", "Obsolete"
-};
-
-using HostsMap = base::IDMap<WebApplicationCacheHostImpl*>;
-
-HostsMap* all_hosts() {
- static HostsMap* map = new HostsMap;
- return map;
-}
-
-GURL ClearUrlRef(const GURL& url) {
- if (!url.has_ref())
- return url;
- GURL::Replacements replacements;
- replacements.ClearRef();
- return url.ReplaceComponents(replacements);
-}
-
-} // anon namespace
-
-WebApplicationCacheHostImpl* WebApplicationCacheHostImpl::FromId(int id) {
- return all_hosts()->Lookup(id);
-}
-
-WebApplicationCacheHostImpl::WebApplicationCacheHostImpl(
- WebApplicationCacheHostClient* client,
- int appcache_host_id,
- int render_frame_id,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : binding_(this),
- client_(client),
- status_(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED),
- is_scheme_supported_(false),
- is_get_method_(false),
- is_new_master_entry_(MAYBE_NEW_ENTRY),
- was_select_cache_called_(false) {
- DCHECK(client);
- // PlzNavigate: The browser passes the ID to be used.
- if (appcache_host_id != blink::mojom::kAppCacheNoHostId) {
- all_hosts()->AddWithID(this, appcache_host_id);
- host_id_ = appcache_host_id;
- } else {
- host_id_ = all_hosts()->Add(this);
- }
- DCHECK(host_id_ != blink::mojom::kAppCacheNoHostId);
-
- static const base::NoDestructor<blink::mojom::AppCacheBackendPtr> backend_ptr(
- [] {
- blink::mojom::AppCacheBackendPtr result;
- RenderThread::Get()->GetConnector()->BindInterface(
- mojom::kBrowserServiceName, mojo::MakeRequest(&result));
- return result;
- }());
- backend_ = backend_ptr->get();
-
- blink::mojom::AppCacheFrontendPtr frontend_ptr;
- binding_.Bind(mojo::MakeRequest(&frontend_ptr, task_runner), task_runner);
- backend_->RegisterHost(
- mojo::MakeRequest(&backend_host_, std::move(task_runner)),
- std::move(frontend_ptr), host_id_, render_frame_id);
-}
-
-WebApplicationCacheHostImpl::~WebApplicationCacheHostImpl() {
- all_hosts()->Remove(host_id_);
-}
-
-void WebApplicationCacheHostImpl::CacheSelected(
- blink::mojom::AppCacheInfoPtr info) {
- cache_info_ = *info;
- client_->DidChangeCacheAssociation();
-}
-
-void WebApplicationCacheHostImpl::EventRaised(
- blink::mojom::AppCacheEventID event_id) {
- DCHECK_NE(event_id,
- blink::mojom::AppCacheEventID::
- APPCACHE_PROGRESS_EVENT); // See OnProgressEventRaised.
- DCHECK_NE(event_id,
- blink::mojom::AppCacheEventID::
- APPCACHE_ERROR_EVENT); // See OnErrorEventRaised.
-
- // Emit logging output prior to calling out to script as we can get
- // deleted within the script event handler.
- const char kFormatString[] = "Application Cache %s event";
- std::string message = base::StringPrintf(
- kFormatString, kEventNames[static_cast<int>(event_id)]);
- LogMessage(blink::mojom::ConsoleMessageLevel::kInfo, message);
-
- switch (event_id) {
- case blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT:
- status_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_CHECKING;
- break;
- case blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT:
- status_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_DOWNLOADING;
- break;
- case blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT:
- status_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_UPDATE_READY;
- break;
- case blink::mojom::AppCacheEventID::APPCACHE_CACHED_EVENT:
- case blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT:
- status_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_IDLE;
- break;
- case blink::mojom::AppCacheEventID::APPCACHE_OBSOLETE_EVENT:
- status_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
- break;
- default:
- NOTREACHED();
- break;
- }
-
- client_->NotifyEventListener(event_id);
-}
-
-void WebApplicationCacheHostImpl::ProgressEventRaised(const GURL& url,
- int num_total,
- int num_complete) {
- // Emit logging output prior to calling out to script as we can get
- // deleted within the script event handler.
- const char kFormatString[] = "Application Cache Progress event (%d of %d) %s";
- std::string message = base::StringPrintf(kFormatString, num_complete,
- num_total, url.spec().c_str());
- LogMessage(blink::mojom::ConsoleMessageLevel::kInfo, message);
- status_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_DOWNLOADING;
- client_->NotifyProgressEventListener(url, num_total, num_complete);
-}
-
-void WebApplicationCacheHostImpl::ErrorEventRaised(
- blink::mojom::AppCacheErrorDetailsPtr details) {
- // Emit logging output prior to calling out to script as we can get
- // deleted within the script event handler.
- const char kFormatString[] = "Application Cache Error event: %s";
- std::string full_message =
- base::StringPrintf(kFormatString, details->message.c_str());
- LogMessage(blink::mojom::ConsoleMessageLevel::kError, full_message);
-
- status_ = cache_info_.is_complete
- ? blink::mojom::AppCacheStatus::APPCACHE_STATUS_IDLE
- : blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED;
- if (details->is_cross_origin) {
- // Don't leak detailed information to script for cross-origin resources.
- DCHECK_EQ(blink::mojom::AppCacheErrorReason::APPCACHE_RESOURCE_ERROR,
- details->reason);
- client_->NotifyErrorEventListener(details->reason, details->url, 0,
- WebString());
- } else {
- client_->NotifyErrorEventListener(details->reason, details->url,
- details->status,
- WebString::FromUTF8(details->message));
- }
-}
-
-void WebApplicationCacheHostImpl::WillStartMainResourceRequest(
- const WebURL& url,
- const WebString& method_webstring,
- const WebApplicationCacheHost* spawning_host) {
- original_main_resource_url_ = ClearUrlRef(url);
-
- std::string method = method_webstring.Utf8();
- is_get_method_ = (method == kHttpGETMethod);
- DCHECK(method == base::ToUpperASCII(method));
-
- const WebApplicationCacheHostImpl* spawning_host_impl =
- static_cast<const WebApplicationCacheHostImpl*>(spawning_host);
- if (spawning_host_impl && (spawning_host_impl != this) &&
- (spawning_host_impl->status_ !=
- blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED)) {
- backend_host_->SetSpawningHostId(spawning_host_impl->host_id());
- }
-}
-
-void WebApplicationCacheHostImpl::SelectCacheWithoutManifest() {
- if (was_select_cache_called_)
- return;
- was_select_cache_called_ = true;
-
- status_ =
- (document_response_.AppCacheID() == blink::mojom::kAppCacheNoCacheId)
- ? blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED
- : blink::mojom::AppCacheStatus::APPCACHE_STATUS_CHECKING;
- is_new_master_entry_ = OLD_ENTRY;
- backend_host_->SelectCache(document_url_, document_response_.AppCacheID(),
- GURL());
-}
-
-bool WebApplicationCacheHostImpl::SelectCacheWithManifest(
- const WebURL& manifest_url) {
- if (was_select_cache_called_)
- return true;
- was_select_cache_called_ = true;
-
- GURL manifest_gurl(ClearUrlRef(manifest_url));
-
- // 6.9.6 The application cache selection algorithm
- // Check for new 'master' entries.
- if (document_response_.AppCacheID() == blink::mojom::kAppCacheNoCacheId) {
- if (is_scheme_supported_ && is_get_method_ &&
- (manifest_gurl.GetOrigin() == document_url_.GetOrigin())) {
- status_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_CHECKING;
- is_new_master_entry_ = NEW_ENTRY;
- } else {
- status_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED;
- is_new_master_entry_ = OLD_ENTRY;
- manifest_gurl = GURL();
- }
- backend_host_->SelectCache(document_url_, blink::mojom::kAppCacheNoCacheId,
- manifest_gurl);
- return true;
- }
-
- DCHECK_EQ(OLD_ENTRY, is_new_master_entry_);
-
- // 6.9.6 The application cache selection algorithm
- // Check for 'foreign' entries.
- GURL document_manifest_gurl(document_response_.AppCacheManifestURL());
- if (document_manifest_gurl != manifest_gurl) {
- backend_host_->MarkAsForeignEntry(document_url_,
- document_response_.AppCacheID());
- status_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED;
- return false; // the navigation will be restarted
- }
-
- status_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_CHECKING;
-
- // Its a 'master' entry thats already in the cache.
- backend_host_->SelectCache(document_url_, document_response_.AppCacheID(),
- manifest_gurl);
- return true;
-}
-
-void WebApplicationCacheHostImpl::DidReceiveResponseForMainResource(
- const WebURLResponse& response) {
- document_response_ = response;
- document_url_ = ClearUrlRef(document_response_.CurrentRequestUrl());
- if (document_url_ != original_main_resource_url_)
- is_get_method_ = true; // A redirect was involved.
- original_main_resource_url_ = GURL();
-
- is_scheme_supported_ = IsSchemeSupportedForAppCache(document_url_);
- if ((document_response_.AppCacheID() != blink::mojom::kAppCacheNoCacheId) ||
- !is_scheme_supported_ || !is_get_method_)
- is_new_master_entry_ = OLD_ENTRY;
-}
-
-blink::mojom::AppCacheStatus WebApplicationCacheHostImpl::GetStatus() {
- return status_;
-}
-
-bool WebApplicationCacheHostImpl::StartUpdate() {
- bool result = false;
- backend_host_->StartUpdate(&result);
- if (!result)
- return false;
- if (status_ == blink::mojom::AppCacheStatus::APPCACHE_STATUS_IDLE ||
- status_ == blink::mojom::AppCacheStatus::APPCACHE_STATUS_UPDATE_READY) {
- status_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_CHECKING;
- } else {
- status_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED;
- backend_host_->GetStatus(&status_);
- }
- return true;
-}
-
-bool WebApplicationCacheHostImpl::SwapCache() {
- bool result = false;
- backend_host_->SwapCache(&result);
- if (!result)
- return false;
- backend_host_->GetStatus(&status_);
- return true;
-}
-
-void WebApplicationCacheHostImpl::GetAssociatedCacheInfo(
- WebApplicationCacheHost::CacheInfo* info) {
- info->manifest_url = cache_info_.manifest_url;
- if (!cache_info_.is_complete)
- return;
- info->creation_time = cache_info_.creation_time.ToDoubleT();
- info->update_time = cache_info_.last_update_time.ToDoubleT();
- info->response_sizes = cache_info_.response_sizes;
- info->padding_sizes = cache_info_.padding_sizes;
-}
-
-int WebApplicationCacheHostImpl::GetHostID() const {
- return host_id_;
-}
-
-void WebApplicationCacheHostImpl::GetResourceList(
- WebVector<ResourceInfo>* resources) {
- if (!cache_info_.is_complete)
- return;
- std::vector<blink::mojom::AppCacheResourceInfoPtr> boxed_infos;
- backend_host_->GetResourceList(&boxed_infos);
- std::vector<blink::mojom::AppCacheResourceInfo> resource_infos;
- for (auto& b : boxed_infos) {
- resource_infos.emplace_back(std::move(*b));
- }
-
- WebVector<ResourceInfo> web_resources(resource_infos.size());
- for (size_t i = 0; i < resource_infos.size(); ++i) {
- web_resources[i].response_size = resource_infos[i].response_size;
- web_resources[i].padding_size = resource_infos[i].padding_size;
- web_resources[i].is_master = resource_infos[i].is_master;
- web_resources[i].is_explicit = resource_infos[i].is_explicit;
- web_resources[i].is_manifest = resource_infos[i].is_manifest;
- web_resources[i].is_foreign = resource_infos[i].is_foreign;
- web_resources[i].is_fallback = resource_infos[i].is_fallback;
- web_resources[i].url = resource_infos[i].url;
- }
- resources->Swap(web_resources);
-}
-
-void WebApplicationCacheHostImpl::SelectCacheForSharedWorker(
- long long app_cache_id) {
- backend_host_->SelectCacheForSharedWorker(app_cache_id);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/appcache/web_application_cache_host_impl.h b/chromium/content/renderer/appcache/web_application_cache_host_impl.h
deleted file mode 100644
index 59b48398ecb..00000000000
--- a/chromium/content/renderer/appcache/web_application_cache_host_impl.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
-#define CONTENT_RENDERER_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
-
-#include <string>
-
-#include "mojo/public/cpp/bindings/binding.h"
-#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
-#include "third_party/blink/public/platform/web_application_cache_host.h"
-#include "third_party/blink/public/platform/web_application_cache_host_client.h"
-#include "third_party/blink/public/platform/web_url_response.h"
-#include "third_party/blink/public/platform/web_vector.h"
-#include "url/gurl.h"
-
-namespace content {
-
-class WebApplicationCacheHostImpl : public blink::WebApplicationCacheHost,
- public blink::mojom::AppCacheFrontend {
- public:
- // Returns the host having given id or NULL if there is no such host.
- static WebApplicationCacheHostImpl* FromId(int id);
-
- WebApplicationCacheHostImpl(
- blink::WebApplicationCacheHostClient* client,
- int appcache_host_id,
- int render_frame_id,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- ~WebApplicationCacheHostImpl() override;
-
- int host_id() const { return host_id_; }
- blink::mojom::AppCacheBackend* backend() const { return backend_; }
- blink::WebApplicationCacheHostClient* client() const { return client_; }
-
- // blink::mojom::AppCacheFrontend
- void CacheSelected(blink::mojom::AppCacheInfoPtr info) override;
- void EventRaised(blink::mojom::AppCacheEventID event_id) override;
- void ProgressEventRaised(const GURL& url,
- int32_t num_total,
- int32_t num_complete) override;
- void ErrorEventRaised(blink::mojom::AppCacheErrorDetailsPtr details) override;
-
- // blink::WebApplicationCacheHost:
- void WillStartMainResourceRequest(
- const blink::WebURL& url,
- const blink::WebString& method,
- const WebApplicationCacheHost* spawning_host) override;
- void SelectCacheWithoutManifest() override;
- bool SelectCacheWithManifest(const blink::WebURL& manifestURL) override;
- void DidReceiveResponseForMainResource(const blink::WebURLResponse&) override;
- blink::mojom::AppCacheStatus GetStatus() override;
- bool StartUpdate() override;
- bool SwapCache() override;
- void GetResourceList(blink::WebVector<ResourceInfo>* resources) override;
- void GetAssociatedCacheInfo(CacheInfo* info) override;
- int GetHostID() const override;
-
- void SelectCacheForSharedWorker(long long app_cache_id);
-
- private:
- enum IsNewMasterEntry { MAYBE_NEW_ENTRY, NEW_ENTRY, OLD_ENTRY };
-
- mojo::Binding<blink::mojom::AppCacheFrontend> binding_;
- blink::WebApplicationCacheHostClient* client_;
- blink::mojom::AppCacheBackend* backend_;
- blink::mojom::AppCacheHostPtr backend_host_;
- int host_id_;
- blink::mojom::AppCacheStatus status_;
- blink::WebURLResponse document_response_;
- GURL document_url_;
- bool is_scheme_supported_;
- bool is_get_method_;
- IsNewMasterEntry is_new_master_entry_;
- blink::mojom::AppCacheInfo cache_info_;
- GURL original_main_resource_url_; // Used to detect redirection.
- bool was_select_cache_called_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.cc b/chromium/content/renderer/browser_plugin/browser_plugin.cc
index 5e38e8c2098..5bbfd2f919c 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.cc
@@ -47,14 +47,8 @@
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_plugin_container.h"
#include "third_party/blink/public/web/web_view.h"
-#include "ui/base/ui_base_features.h"
#include "ui/events/keycodes/keyboard_codes.h"
-#if defined(USE_AURA)
-#include "content/renderer/mus/mus_embedded_frame.h"
-#include "content/renderer/mus/renderer_window_tree_client.h"
-#endif
-
using blink::WebPluginContainer;
using blink::WebPoint;
using blink::WebRect;
@@ -136,9 +130,6 @@ bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
OnDidUpdateVisualProperties)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetCursor, OnSetCursor)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMouseLock, OnSetMouseLock)
-#if defined(USE_AURA)
- IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMusEmbedToken, OnSetMusEmbedToken)
-#endif
IPC_MESSAGE_HANDLER(BrowserPluginMsg_ShouldAcceptTouchEvents,
OnShouldAcceptTouchEvents)
IPC_END_MESSAGE_MAP()
@@ -173,14 +164,6 @@ void BrowserPlugin::Attach() {
->GetDocument()
.IsPluginDocument();
}
-#if defined(USE_AURA)
- if (pending_embed_token_) {
- base::Optional<base::UnguessableToken> embed_token =
- std::move(pending_embed_token_);
- CreateMusWindowAndEmbed(*embed_token);
- }
-#endif
-
BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_Attach(
render_frame_routing_id_,
browser_plugin_instance_id_,
@@ -219,28 +202,6 @@ BrowserPlugin::GetLocalSurfaceIdAllocation() const {
.GetCurrentLocalSurfaceIdAllocation();
}
-#if defined(USE_AURA)
-void BrowserPlugin::CreateMusWindowAndEmbed(
- const base::UnguessableToken& embed_token) {
- RenderFrameImpl* render_frame =
- RenderFrameImpl::FromRoutingID(render_frame_routing_id_);
- if (!render_frame) {
- pending_embed_token_ = embed_token;
- return;
- }
- RendererWindowTreeClient* renderer_window_tree_client =
- RendererWindowTreeClient::Get(
- render_frame->GetLocalRootRenderWidget()->routing_id());
- DCHECK(renderer_window_tree_client);
- mus_embedded_frame_ =
- renderer_window_tree_client->CreateMusEmbeddedFrame(this, embed_token);
- if (attached() && GetLocalSurfaceIdAllocation().IsValid()) {
- mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceIdAllocation(),
- FrameRectInPixels());
- }
-}
-#endif
-
void BrowserPlugin::SynchronizeVisualProperties() {
bool size_changed = !sent_visual_properties_ ||
sent_visual_properties_->auto_resize_enabled !=
@@ -311,13 +272,6 @@ void BrowserPlugin::SynchronizeVisualProperties() {
if (visual_properties_changed && attached())
sent_visual_properties_ = pending_visual_properties_;
-
-#if defined(USE_AURA)
- if (features::IsMultiProcessMash() && mus_embedded_frame_) {
- mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceIdAllocation(),
- FrameRectInPixels());
- }
-#endif
}
void BrowserPlugin::OnAdvanceFocus(int browser_plugin_instance_id,
@@ -400,20 +354,6 @@ void BrowserPlugin::OnSetMouseLock(int browser_plugin_instance_id,
}
}
-#if defined(USE_AURA)
-void BrowserPlugin::OnSetMusEmbedToken(
- int instance_id,
- const base::UnguessableToken& embed_token) {
- DCHECK(features::IsMultiProcessMash());
- if (!attached_) {
- pending_embed_token_ = embed_token;
- } else {
- pending_embed_token_.reset();
- CreateMusWindowAndEmbed(embed_token);
- }
-}
-#endif
-
void BrowserPlugin::OnShouldAcceptTouchEvents(int browser_plugin_instance_id,
bool accept) {
if (Container()) {
@@ -423,18 +363,6 @@ void BrowserPlugin::OnShouldAcceptTouchEvents(int browser_plugin_instance_id,
}
}
-gfx::Rect BrowserPlugin::FrameRectInPixels() const {
- const float device_scale_factor = GetDeviceScaleFactor();
- return gfx::Rect(
- gfx::ScaleToFlooredPoint(screen_space_rect().origin(),
- device_scale_factor),
- gfx::ScaleToCeiledSize(screen_space_rect().size(), device_scale_factor));
-}
-
-float BrowserPlugin::GetDeviceScaleFactor() const {
- return pending_visual_properties_.screen_info.device_scale_factor;
-}
-
RenderWidget* BrowserPlugin::GetMainWidget() const {
RenderFrameImpl* frame =
RenderFrameImpl::FromRoutingID(render_frame_routing_id());
@@ -838,15 +766,6 @@ bool BrowserPlugin::HandleMouseLockedInputEvent(
return true;
}
-#if defined(USE_AURA)
-void BrowserPlugin::OnMusEmbeddedFrameSinkIdAllocated(
- const viz::FrameSinkId& frame_sink_id) {
- // RendererWindowTreeClient should only call this when mus is hosting viz.
- DCHECK(features::IsMultiProcessMash());
- OnGuestReady(browser_plugin_instance_id_, frame_sink_id);
-}
-#endif
-
cc::Layer* BrowserPlugin::GetLayer() {
return embedded_layer_.get();
}
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.h b/chromium/content/renderer/browser_plugin/browser_plugin.h
index 89c2b67dc49..a81d50fbcc8 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.h
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.h
@@ -26,14 +26,6 @@
#include "third_party/blink/public/web/web_input_method_controller.h"
#include "third_party/blink/public/web/web_node.h"
-#if defined(USE_AURA)
-#include "content/renderer/mus/mus_embedded_frame_delegate.h"
-#endif
-
-namespace base {
-class UnguessableToken;
-}
-
namespace cc {
class Layer;
class RenderFrameMetadata;
@@ -45,14 +37,7 @@ class BrowserPluginDelegate;
class BrowserPluginManager;
class ChildFrameCompositingHelper;
-#if defined(USE_AURA)
-class MusEmbeddedFrame;
-#endif
-
class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
-#if defined(USE_AURA)
- public MusEmbeddedFrameDelegate,
-#endif
public ChildFrameCompositor,
public MouseLockDispatcher::LockTarget {
public:
@@ -175,8 +160,6 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
const gfx::Rect& screen_space_rect() const {
return pending_visual_properties_.screen_space_rect;
}
- gfx::Rect FrameRectInPixels() const;
- float GetDeviceScaleFactor() const;
RenderWidget* GetMainWidget() const;
const ScreenInfo& screen_info() const {
@@ -185,10 +168,6 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
void UpdateInternalInstanceId();
-#if defined(USE_AURA)
- void CreateMusWindowAndEmbed(const base::UnguessableToken& embed_token);
-#endif
-
// IPC message handlers.
// Please keep in alphabetical order.
void OnAdvanceFocus(int instance_id, bool reverse);
@@ -204,18 +183,8 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
void OnSetContentsOpaque(int instance_id, bool opaque);
void OnSetCursor(int instance_id, const WebCursor& cursor);
void OnSetMouseLock(int instance_id, bool enable);
-#if defined(USE_AURA)
- void OnSetMusEmbedToken(int instance_id,
- const base::UnguessableToken& embed_token);
-#endif
void OnShouldAcceptTouchEvents(int instance_id, bool accept);
-#if defined(USE_AURA)
- // MusEmbeddedFrameDelegate
- void OnMusEmbeddedFrameSinkIdAllocated(
- const viz::FrameSinkId& frame_sink_id) override;
-#endif
-
// ChildFrameCompositor:
cc::Layer* GetLayer() override;
void SetLayer(scoped_refptr<cc::Layer> layer,
@@ -267,13 +236,6 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
// own this. The delegate destroys itself.
base::WeakPtr<BrowserPluginDelegate> delegate_;
-#if defined(USE_AURA)
- // Set if OnSetMusEmbedToken() is called before attached.
- base::Optional<base::UnguessableToken> pending_embed_token_;
-
- std::unique_ptr<MusEmbeddedFrame> mus_embedded_frame_;
-#endif
-
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// Pointer to the RenderWidget that embeds this plugin.
diff --git a/chromium/content/renderer/browser_render_view_browsertest.cc b/chromium/content/renderer/browser_render_view_browsertest.cc
index 73c65dd5d0a..6cda730f2a0 100644
--- a/chromium/content/renderer/browser_render_view_browsertest.cc
+++ b/chromium/content/renderer/browser_render_view_browsertest.cc
@@ -124,10 +124,9 @@ class RenderViewBrowserTest : public ContentBrowserTest {
int* error_code, bool* stale_cache_entry_present) {
bool result = false;
- PostTaskToInProcessRendererAndWait(
- base::Bind(&RenderViewBrowserTest::GetLatestErrorFromRendererClient0,
- renderer_client_, &result, error_code,
- stale_cache_entry_present));
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
+ &RenderViewBrowserTest::GetLatestErrorFromRendererClient0,
+ renderer_client_, &result, error_code, stale_cache_entry_present));
return result;
}
diff --git a/chromium/content/renderer/compositor/layer_tree_view.cc b/chromium/content/renderer/compositor/layer_tree_view.cc
index a76535fcebd..4b2e1d6409b 100644
--- a/chromium/content/renderer/compositor/layer_tree_view.cc
+++ b/chromium/content/renderer/compositor/layer_tree_view.cc
@@ -81,7 +81,7 @@ void LayerTreeView::Initialize(
params.main_task_runner = main_thread_;
params.mutator_host = animation_host_.get();
params.ukm_recorder_factory = std::move(ukm_recorder_factory);
- if (base::ThreadPool::GetInstance()) {
+ if (base::ThreadPoolInstance::Get()) {
// The image worker thread needs to allow waiting since it makes discardable
// shared memory allocations which need to make synchronous calls to the
// IO thread.
@@ -230,8 +230,9 @@ void LayerTreeView::StartDeferringCommits(base::TimeDelta timeout) {
layer_tree_host_->StartDeferringCommits(timeout);
}
-void LayerTreeView::StopDeferringCommits() {
- layer_tree_host_->StopDeferringCommits();
+void LayerTreeView::StopDeferringCommits(
+ cc::PaintHoldingCommitTrigger trigger) {
+ layer_tree_host_->StopDeferringCommits(trigger);
}
int LayerTreeView::LayerTreeId() const {
@@ -462,8 +463,8 @@ void LayerTreeView::AddPresentationCallback(
DCHECK_LE(presentation_callbacks_.size(), 25u);
}
-void LayerTreeView::SetURLForUkm(const GURL& url) {
- layer_tree_host_->SetURLForUkm(url);
+void LayerTreeView::SetSourceURL(ukm::SourceId source_id, const GURL& url) {
+ layer_tree_host_->SetSourceURL(source_id, url);
}
void LayerTreeView::ReleaseLayerTreeFrameSink() {
diff --git a/chromium/content/renderer/compositor/layer_tree_view.h b/chromium/content/renderer/compositor/layer_tree_view.h
index 0fd0f6aa7b8..86435be768b 100644
--- a/chromium/content/renderer/compositor/layer_tree_view.h
+++ b/chromium/content/renderer/compositor/layer_tree_view.h
@@ -118,7 +118,7 @@ class CONTENT_EXPORT LayerTreeView
void RequestNewLocalSurfaceId();
void RequestForceSendMetadata();
void SetViewportVisibleRect(const gfx::Rect& visible_rect);
- void SetURLForUkm(const GURL& url);
+ void SetSourceURL(ukm::SourceId source_id, const GURL& url);
// Call this if the compositor is becoming non-visible in a way that it won't
// be used any longer. In this case, becoming visible is longer but this
// releases more resources (such as its use of the GpuChannel).
@@ -132,7 +132,7 @@ class CONTENT_EXPORT LayerTreeView
std::unique_ptr<cc::ScopedDeferMainFrameUpdate> DeferMainFrameUpdate()
override;
void StartDeferringCommits(base::TimeDelta timeout) override;
- void StopDeferringCommits() override;
+ void StopDeferringCommits(cc::PaintHoldingCommitTrigger) override;
void ForceRecalculateRasterScales() override;
void SetEventListenerProperties(
cc::EventListenerClass eventClass,
@@ -181,8 +181,6 @@ class CONTENT_EXPORT LayerTreeView
const gfx::PresentationFeedback& feedback) override;
void RecordStartOfFrameMetrics() override;
void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override;
- void DidGenerateLocalSurfaceIdAllocation(
- const viz::LocalSurfaceIdAllocation& allocation) override {}
// cc::LayerTreeHostSingleThreadClient implementation.
void DidSubmitCompositorFrame() override;
diff --git a/chromium/content/renderer/dom_serializer_browsertest.cc b/chromium/content/renderer/dom_serializer_browsertest.cc
index f39faacc60e..6d20c9f3d0e 100644
--- a/chromium/content/renderer/dom_serializer_browsertest.cc
+++ b/chromium/content/renderer/dom_serializer_browsertest.cc
@@ -641,7 +641,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests,
// Load the test file.
NavigateToURL(shell(), file_url);
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&MAYBE_DomSerializerTests::SerializeHTMLDOMWithDocTypeOnRenderer,
base::Unretained(this), file_url));
}
@@ -657,7 +657,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests,
// Load the test file.
NavigateToURL(shell(), file_url);
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&MAYBE_DomSerializerTests::SerializeHTMLDOMWithoutDocTypeOnRenderer,
base::Unretained(this), file_url));
}
@@ -686,7 +686,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests,
// Load the test file.
NavigateToURL(shell(), file_url);
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&MAYBE_DomSerializerTests::SerializeXMLDocWithBuiltInEntitiesOnRenderer,
base::Unretained(this), xml_file_url, original_contents));
}
@@ -711,7 +711,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests,
// Load the test file.
NavigateToURL(shell(), file_url);
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&MAYBE_DomSerializerTests::SerializeHTMLDOMWithAddingMOTWOnRenderer,
base::Unretained(this), file_url, original_contents, false));
}
@@ -736,7 +736,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests,
// Load the test file.
NavigateToURL(shell(), file_url);
- PostTaskToInProcessRendererAndWait(base::BindRepeating(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&MAYBE_DomSerializerTests::SerializeHTMLDOMWithAddingMOTWOnRenderer,
base::Unretained(this), file_url, original_contents, true));
}
@@ -758,10 +758,10 @@ IN_PROC_BROWSER_TEST_F(
// Load the test file.
NavigateToURL(shell(), file_url);
- PostTaskToInProcessRendererAndWait(
- base::Bind(&MAYBE_DomSerializerTests::
- SerializeHTMLDOMWithNoMetaCharsetInOriginalDocOnRenderer,
- base::Unretained(this), file_url));
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
+ &MAYBE_DomSerializerTests::
+ SerializeHTMLDOMWithNoMetaCharsetInOriginalDocOnRenderer,
+ base::Unretained(this), file_url));
}
// When serializing DOM, if the original document has multiple META charset
@@ -780,7 +780,7 @@ IN_PROC_BROWSER_TEST_F(
// Load the test file.
NavigateToURL(shell(), file_url);
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&MAYBE_DomSerializerTests::
SerializeHTMLDOMWithMultipleMetaCharsetInOriginalDocOnRenderer,
base::Unretained(this), file_url));
@@ -794,7 +794,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests,
// from non-file scheme.
NavigateToURL(shell(), GetTestUrl(".", "simple_page.html"));
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&MAYBE_DomSerializerTests::SerializeHTMLDOMWithEntitiesInTextOnRenderer,
base::Unretained(this)));
}
@@ -810,9 +810,9 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests,
NavigateToURL(shell(), GetTestUrl(".", "simple_page.html"));
PostTaskToInProcessRendererAndWait(
- base::Bind(&MAYBE_DomSerializerTests::
- SerializeHTMLDOMWithEntitiesInAttributeValueOnRenderer,
- base::Unretained(this)));
+ base::BindOnce(&MAYBE_DomSerializerTests::
+ SerializeHTMLDOMWithEntitiesInAttributeValueOnRenderer,
+ base::Unretained(this)));
}
// Test situation of non-standard HTML entities when serializing HTML DOM.
@@ -826,9 +826,9 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests,
NavigateToURL(shell(), file_url);
PostTaskToInProcessRendererAndWait(
- base::Bind(&MAYBE_DomSerializerTests::
- SerializeHTMLDOMWithNonStandardEntitiesOnRenderer,
- base::Unretained(this), file_url));
+ base::BindOnce(&MAYBE_DomSerializerTests::
+ SerializeHTMLDOMWithNonStandardEntitiesOnRenderer,
+ base::Unretained(this), file_url));
}
// Test situation of BASE tag in original document when serializing HTML DOM.
@@ -851,7 +851,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests, SerializeHTMLDOMWithBaseTag) {
// Load the test file.
NavigateToURL(shell(), file_url);
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&MAYBE_DomSerializerTests::SerializeHTMLDOMWithBaseTagOnRenderer,
base::Unretained(this), file_url, path_dir_url));
}
@@ -864,7 +864,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests,
// from non-file scheme.
NavigateToURL(shell(), GetTestUrl(".", "simple_page.html"));
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&MAYBE_DomSerializerTests::SerializeHTMLDOMWithEmptyHeadOnRenderer,
base::Unretained(this)));
}
@@ -877,9 +877,9 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests,
NavigateToURL(shell(), file_url);
PostTaskToInProcessRendererAndWait(
- base::Bind(&MAYBE_DomSerializerTests::
- SubResourceForElementsInNonHTMLNamespaceOnRenderer,
- base::Unretained(this), file_url));
+ base::BindOnce(&MAYBE_DomSerializerTests::
+ SubResourceForElementsInNonHTMLNamespaceOnRenderer,
+ base::Unretained(this), file_url));
}
} // namespace content
diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area.h b/chromium/content/renderer/dom_storage/dom_storage_cached_area.h
index dacf2da744f..ae1a9454fb4 100644
--- a/chromium/content/renderer/dom_storage/dom_storage_cached_area.h
+++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area.h
@@ -14,7 +14,7 @@
#include "base/memory/weak_ptr.h"
#include "base/strings/nullable_string16.h"
#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/web_scoped_virtual_time_pauser.h"
+#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "url/gurl.h"
namespace blink {
diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_area.h b/chromium/content/renderer/dom_storage/local_storage_cached_area.h
index 9780e7ad402..62b7e83aa95 100644
--- a/chromium/content/renderer/dom_storage/local_storage_cached_area.h
+++ b/chromium/content/renderer/dom_storage/local_storage_cached_area.h
@@ -15,7 +15,7 @@
#include "content/common/possibly_associated_interface_ptr.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
-#include "third_party/blink/public/platform/web_scoped_virtual_time_pauser.h"
+#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "url/gurl.h"
#include "url/origin.h"
diff --git a/chromium/content/renderer/fetchers/associated_resource_fetcher_impl.cc b/chromium/content/renderer/fetchers/associated_resource_fetcher_impl.cc
index daa8c557a78..d4cac5732d4 100644
--- a/chromium/content/renderer/fetchers/associated_resource_fetcher_impl.cc
+++ b/chromium/content/renderer/fetchers/associated_resource_fetcher_impl.cc
@@ -34,8 +34,8 @@ AssociatedResourceFetcher* AssociatedResourceFetcher::Create(const GURL& url) {
class AssociatedResourceFetcherImpl::ClientImpl
: public blink::WebAssociatedURLLoaderClient {
public:
- explicit ClientImpl(const Callback& callback)
- : completed_(false), status_(LOADING), callback_(callback) {}
+ explicit ClientImpl(StartCallback callback)
+ : completed_(false), status_(LOADING), callback_(std::move(callback)) {}
~ClientImpl() override {}
@@ -59,11 +59,7 @@ class AssociatedResourceFetcherImpl::ClientImpl
if (callback_.is_null())
return;
-
- // Take a reference to the callback as running the callback may lead to our
- // destruction.
- Callback callback = callback_;
- std::move(callback).Run(
+ std::move(callback_).Run(
status_ == LOAD_FAILED ? blink::WebURLResponse() : response_,
status_ == LOAD_FAILED ? std::string() : data_);
}
@@ -110,7 +106,7 @@ class AssociatedResourceFetcherImpl::ClientImpl
LoadStatus status_;
// Callback when we're done.
- Callback callback_;
+ StartCallback callback_;
DISALLOW_COPY_AND_ASSIGN(ClientImpl);
};
@@ -157,7 +153,7 @@ void AssociatedResourceFetcherImpl::Start(
blink::mojom::RequestContextType request_context,
network::mojom::FetchRequestMode fetch_request_mode,
network::mojom::FetchCredentialsMode fetch_credentials_mode,
- const Callback& callback) {
+ StartCallback callback) {
DCHECK(!loader_);
DCHECK(!client_);
DCHECK(!request_.IsNull());
@@ -169,7 +165,7 @@ void AssociatedResourceFetcherImpl::Start(
request_.SetFetchRequestMode(fetch_request_mode);
request_.SetFetchCredentialsMode(fetch_credentials_mode);
- client_.reset(new ClientImpl(callback));
+ client_.reset(new ClientImpl(std::move(callback)));
loader_.reset(frame->CreateAssociatedURLLoader(options_));
loader_->LoadAsynchronously(request_, client_.get());
diff --git a/chromium/content/renderer/fetchers/associated_resource_fetcher_impl.h b/chromium/content/renderer/fetchers/associated_resource_fetcher_impl.h
index 2a7dff382f8..0efd75cfeac 100644
--- a/chromium/content/renderer/fetchers/associated_resource_fetcher_impl.h
+++ b/chromium/content/renderer/fetchers/associated_resource_fetcher_impl.h
@@ -36,7 +36,7 @@ class AssociatedResourceFetcherImpl : public AssociatedResourceFetcher {
blink::mojom::RequestContextType request_context,
network::mojom::FetchRequestMode request_mode,
network::mojom::FetchCredentialsMode fetch_credentials_mode,
- const Callback& callback) override;
+ StartCallback callback) override;
private:
friend class AssociatedResourceFetcher;
diff --git a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
index bde6f7296df..4cb03067ec2 100644
--- a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
+++ b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
@@ -4,11 +4,12 @@
#include "content/renderer/fetchers/multi_resolution_image_resource_fetcher.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "content/child/image_decoder.h"
#include "content/public/renderer/associated_resource_fetcher.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_url_response.h"
#include "third_party/blink/public/web/web_associated_url_loader_options.h"
@@ -57,8 +58,8 @@ MultiResolutionImageResourceFetcher::MultiResolutionImageResourceFetcher(
fetcher_->Start(
frame, request_context, network::mojom::FetchRequestMode::kNoCors,
network::mojom::FetchCredentialsMode::kInclude,
- base::Bind(&MultiResolutionImageResourceFetcher::OnURLFetchComplete,
- base::Unretained(this)));
+ base::BindOnce(&MultiResolutionImageResourceFetcher::OnURLFetchComplete,
+ base::Unretained(this)));
}
MultiResolutionImageResourceFetcher::~MultiResolutionImageResourceFetcher() {
@@ -80,15 +81,11 @@ void MultiResolutionImageResourceFetcher::OnURLFetchComplete(
// If we get here, it means no image from server or couldn't decode the
// response as an image. The delegate will see an empty vector.
- // Take local ownership of the callback as running the callback may lead to
- // our destruction.
- base::ResetAndReturn(&callback_).Run(this, bitmaps);
+ std::move(callback_).Run(this, bitmaps);
}
void MultiResolutionImageResourceFetcher::OnRenderFrameDestruct() {
- // Take local ownership of the callback as running the callback may lead to
- // our destruction.
- base::ResetAndReturn(&callback_).Run(this, std::vector<SkBitmap>());
+ std::move(callback_).Run(this, std::vector<SkBitmap>());
}
} // namespace content
diff --git a/chromium/content/renderer/fetchers/resource_fetcher_browsertest.cc b/chromium/content/renderer/fetchers/resource_fetcher_browsertest.cc
index 6b811c2c81b..6bf46794a5a 100644
--- a/chromium/content/renderer/fetchers/resource_fetcher_browsertest.cc
+++ b/chromium/content/renderer/fetchers/resource_fetcher_browsertest.cc
@@ -46,7 +46,7 @@ class FetcherDelegate {
virtual ~FetcherDelegate() {}
- ResourceFetcher::Callback NewCallback() {
+ ResourceFetcher::StartCallback NewCallback() {
return base::BindOnce(&FetcherDelegate::OnURLFetchComplete,
base::Unretained(this));
}
@@ -58,7 +58,7 @@ class FetcherDelegate {
completed_ = true;
timer_.Stop();
if (!timed_out_)
- quit_task_.Run();
+ std::move(quit_task_).Run();
}
bool completed() const { return completed_; }
@@ -84,7 +84,7 @@ class FetcherDelegate {
timed_out_ = true;
if (!completed_)
- quit_task_.Run();
+ std::move(quit_task_).Run();
FAIL() << "fetch timed out";
}
@@ -96,7 +96,7 @@ class FetcherDelegate {
bool timed_out_;
WebURLResponse response_;
std::string data_;
- base::Closure quit_task_;
+ base::OnceClosure quit_task_;
};
FetcherDelegate* FetcherDelegate::instance_ = nullptr;
@@ -309,8 +309,8 @@ IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDownload) {
GURL url(embedded_test_server()->GetURL("/simple_page.html"));
PostTaskToInProcessRendererAndWait(
- base::Bind(&ResourceFetcherTests::ResourceFetcherDownloadOnRenderer,
- base::Unretained(this), url));
+ base::BindOnce(&ResourceFetcherTests::ResourceFetcherDownloadOnRenderer,
+ base::Unretained(this), url));
}
// Test if ResourceFetcher can handle server redirects correctly.
@@ -324,8 +324,8 @@ IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherRedirect) {
embedded_test_server()->GetURL("/server-redirect?" + final_url.spec()));
PostTaskToInProcessRendererAndWait(
- base::Bind(&ResourceFetcherTests::ResourceFetcherRedirectOnRenderer,
- base::Unretained(this), url, final_url));
+ base::BindOnce(&ResourceFetcherTests::ResourceFetcherRedirectOnRenderer,
+ base::Unretained(this), url, final_url));
}
IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcher404) {
@@ -337,8 +337,8 @@ IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcher404) {
GURL url = embedded_test_server()->GetURL("/thisfiledoesntexist.html");
PostTaskToInProcessRendererAndWait(
- base::Bind(&ResourceFetcherTests::ResourceFetcher404OnRenderer,
- base::Unretained(this), url));
+ base::BindOnce(&ResourceFetcherTests::ResourceFetcher404OnRenderer,
+ base::Unretained(this), url));
}
// If this flakes, use http://crbug.com/51622.
@@ -347,8 +347,8 @@ IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDidFail) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
PostTaskToInProcessRendererAndWait(
- base::Bind(&ResourceFetcherTests::ResourceFetcherDidFailOnRenderer,
- base::Unretained(this)));
+ base::BindOnce(&ResourceFetcherTests::ResourceFetcherDidFailOnRenderer,
+ base::Unretained(this)));
}
IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherTimeout) {
@@ -361,8 +361,8 @@ IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherTimeout) {
GURL url(embedded_test_server()->GetURL("/slow?1"));
PostTaskToInProcessRendererAndWait(
- base::Bind(&ResourceFetcherTests::ResourceFetcherTimeoutOnRenderer,
- base::Unretained(this), url));
+ base::BindOnce(&ResourceFetcherTests::ResourceFetcherTimeoutOnRenderer,
+ base::Unretained(this), url));
}
IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDeletedInCallback) {
@@ -374,7 +374,7 @@ IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDeletedInCallback) {
// timeout in 0 sec.
GURL url(embedded_test_server()->GetURL("/slow?1"));
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&ResourceFetcherTests::ResourceFetcherDeletedInCallbackOnRenderer,
base::Unretained(this), url));
}
@@ -388,7 +388,7 @@ IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherPost) {
// Grab a page that echos the POST body.
GURL url(embedded_test_server()->GetURL("/echo"));
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&ResourceFetcherTests::ResourceFetcherPost, base::Unretained(this), url));
}
@@ -402,8 +402,8 @@ IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherSetHeader) {
GURL url(embedded_test_server()->GetURL("/echoheader?header"));
PostTaskToInProcessRendererAndWait(
- base::Bind(&ResourceFetcherTests::ResourceFetcherSetHeader,
- base::Unretained(this), url));
+ base::BindOnce(&ResourceFetcherTests::ResourceFetcherSetHeader,
+ base::Unretained(this), url));
}
} // namespace content
diff --git a/chromium/content/renderer/fetchers/resource_fetcher_impl.cc b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
index 50fda83de29..96faed0ad1d 100644
--- a/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
+++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
@@ -35,7 +35,6 @@
namespace {
constexpr int32_t kRoutingId = 0;
-const char kAccessControlAllowOriginHeader[] = "Access-Control-Allow-Origin";
} // namespace
@@ -53,7 +52,7 @@ std::unique_ptr<ResourceFetcher> ResourceFetcher::Create(const GURL& url) {
class ResourceFetcherImpl::ClientImpl : public network::mojom::URLLoaderClient {
public:
ClientImpl(ResourceFetcherImpl* parent,
- Callback callback,
+ StartCallback callback,
size_t maximum_download_size,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: parent_(parent),
@@ -67,7 +66,7 @@ class ResourceFetcherImpl::ClientImpl : public network::mojom::URLLoaderClient {
callback_(std::move(callback)) {}
~ClientImpl() override {
- callback_ = Callback();
+ callback_.Reset();
Cancel();
}
@@ -197,7 +196,7 @@ class ResourceFetcherImpl::ClientImpl : public network::mojom::URLLoaderClient {
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override {}
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override {}
void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override {
@@ -251,7 +250,7 @@ class ResourceFetcherImpl::ClientImpl : public network::mojom::URLLoaderClient {
blink::WebURLResponse response_;
// Callback when we're done.
- Callback callback_;
+ StartCallback callback_;
DISALLOW_COPY_AND_ASSIGN(ClientImpl);
};
@@ -298,7 +297,7 @@ void ResourceFetcherImpl::Start(
blink::mojom::RequestContextType request_context,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const net::NetworkTrafficAnnotationTag& annotation_tag,
- Callback callback,
+ StartCallback callback,
size_t maximum_download_size) {
DCHECK(!client_);
DCHECK(frame);
@@ -317,7 +316,7 @@ void ResourceFetcherImpl::Start(
if (!frame->GetDocument().GetSecurityOrigin().IsNull()) {
request_.request_initiator =
static_cast<url::Origin>(frame->GetDocument().GetSecurityOrigin());
- SetHeader(kAccessControlAllowOriginHeader,
+ SetHeader(net::HttpRequestHeaders::kOrigin,
blink::WebSecurityOrigin::CreateUnique().ToString().Ascii());
}
request_.resource_type =
diff --git a/chromium/content/renderer/fetchers/resource_fetcher_impl.h b/chromium/content/renderer/fetchers/resource_fetcher_impl.h
index ea32bfaa504..6a3b3a6b6a6 100644
--- a/chromium/content/renderer/fetchers/resource_fetcher_impl.h
+++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.h
@@ -37,7 +37,7 @@ class ResourceFetcherImpl : public ResourceFetcher {
blink::mojom::RequestContextType request_context,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const net::NetworkTrafficAnnotationTag& annotation_tag,
- Callback callback,
+ StartCallback callback,
size_t maximum_download_size) override;
void SetTimeout(const base::TimeDelta& timeout) override;
diff --git a/chromium/content/renderer/frame_swap_message_queue.cc b/chromium/content/renderer/frame_swap_message_queue.cc
index 8a8df1257e2..9c8b0069ff2 100644
--- a/chromium/content/renderer/frame_swap_message_queue.cc
+++ b/chromium/content/renderer/frame_swap_message_queue.cc
@@ -109,7 +109,7 @@ void FrameSwapMessageQueue::DidActivate(int source_frame_number) {
void FrameSwapMessageQueue::DidSwap(int source_frame_number) {}
-void FrameSwapMessageQueue::DidNotSwap(
+cc::SwapPromise::DidNotSwapAction FrameSwapMessageQueue::DidNotSwap(
int source_frame_number,
cc::SwapPromise::DidNotSwapReason reason,
std::vector<std::unique_ptr<IPC::Message>>* messages) {
@@ -119,14 +119,15 @@ void FrameSwapMessageQueue::DidNotSwap(
case cc::SwapPromise::COMMIT_NO_UPDATE:
DrainMessages(messages);
visual_state_queue_->DrainMessages(source_frame_number, messages);
- break;
+ return cc::SwapPromise::DidNotSwapAction::BREAK_PROMISE;
case cc::SwapPromise::COMMIT_FAILS:
+ return cc::SwapPromise::DidNotSwapAction::KEEP_ACTIVE;
case cc::SwapPromise::ACTIVATION_FAILS:
- // Do not queue any responses here. If ACTIVATION_FAILS or
- // COMMIT_FAILS the renderer is shutting down, which will result
+ // Do not queue any responses or return KEEP_ALIVE here. If
+ // ACTIVATION_FAILS the renderer is shutting down, which will result
// in the RenderFrameHostImpl destructor firing the remaining
// response callbacks itself.
- break;
+ return cc::SwapPromise::DidNotSwapAction::BREAK_PROMISE;
}
}
diff --git a/chromium/content/renderer/frame_swap_message_queue.h b/chromium/content/renderer/frame_swap_message_queue.h
index 6f692fab392..4ba79b94b55 100644
--- a/chromium/content/renderer/frame_swap_message_queue.h
+++ b/chromium/content/renderer/frame_swap_message_queue.h
@@ -71,9 +71,10 @@ class CONTENT_EXPORT FrameSwapMessageQueue
// |messages| depending on |reason| it may make sense to deliver certain
// messages asynchronously. This vector will contain those
// messages.
- void DidNotSwap(int source_frame_number,
- cc::SwapPromise::DidNotSwapReason reason,
- std::vector<std::unique_ptr<IPC::Message>>* messages);
+ cc::SwapPromise::DidNotSwapAction DidNotSwap(
+ int source_frame_number,
+ cc::SwapPromise::DidNotSwapReason reason,
+ std::vector<std::unique_ptr<IPC::Message>>* messages);
// A SendMessageScope object must be held by the caller when this method is
// called.
diff --git a/chromium/content/renderer/image_capture/DEPS b/chromium/content/renderer/image_capture/DEPS
deleted file mode 100644
index 1c7383f8195..00000000000
--- a/chromium/content/renderer/image_capture/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+third_party/libyuv",
- '+third_party/skia',
-]
diff --git a/chromium/content/renderer/image_capture/OWNERS b/chromium/content/renderer/image_capture/OWNERS
deleted file mode 100644
index ab8e7bac0ca..00000000000
--- a/chromium/content/renderer/image_capture/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-reillyg@chromium.org
-
-# Original (legacy) owner.
-mcasas@chromium.org
-
-# COMPONENT: Blink>ImageCapture
-# TEAM: webrtc-dev@chromium.org
diff --git a/chromium/content/renderer/image_capture/image_capture_frame_grabber.cc b/chromium/content/renderer/image_capture/image_capture_frame_grabber.cc
deleted file mode 100644
index 8500e38b8ef..00000000000
--- a/chromium/content/renderer/image_capture/image_capture_frame_grabber.cc
+++ /dev/null
@@ -1,169 +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/renderer/image_capture/image_capture_frame_grabber.h"
-
-#include "base/bind.h"
-#include "cc/paint/paint_canvas.h"
-#include "media/base/bind_to_current_loop.h"
-#include "media/base/video_frame.h"
-#include "media/base/video_util.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/blink/public/platform/web_callbacks.h"
-#include "third_party/blink/public/platform/web_media_stream_source.h"
-#include "third_party/blink/public/platform/web_media_stream_track.h"
-#include "third_party/libyuv/include/libyuv.h"
-#include "third_party/skia/include/core/SkImage.h"
-#include "third_party/skia/include/core/SkSurface.h"
-
-namespace content {
-
-using blink::WebImageCaptureGrabFrameCallbacks;
-
-namespace {
-
-void OnError(std::unique_ptr<WebImageCaptureGrabFrameCallbacks> callbacks) {
- callbacks->OnError();
-}
-
-} // anonymous namespace
-
-// Ref-counted class to receive a single VideoFrame on IO thread, convert it and
-// send it to |main_task_runner_|, where this class is created and destroyed.
-class ImageCaptureFrameGrabber::SingleShotFrameHandler
- : public base::RefCountedThreadSafe<SingleShotFrameHandler> {
- public:
- SingleShotFrameHandler() : first_frame_received_(false) {}
-
- // Receives a |frame| and converts its pixels into a SkImage via an internal
- // PaintSurface and SkPixmap. Alpha channel, if any, is copied.
- void OnVideoFrameOnIOThread(SkImageDeliverCB callback,
- const scoped_refptr<media::VideoFrame>& frame,
- base::TimeTicks current_time);
-
- private:
- friend class base::RefCountedThreadSafe<SingleShotFrameHandler>;
- virtual ~SingleShotFrameHandler() {}
-
- // Flag to indicate that the first frames has been processed, and subsequent
- // ones can be safely discarded.
- bool first_frame_received_;
-
- DISALLOW_COPY_AND_ASSIGN(SingleShotFrameHandler);
-};
-
-void ImageCaptureFrameGrabber::SingleShotFrameHandler::OnVideoFrameOnIOThread(
- SkImageDeliverCB callback,
- const scoped_refptr<media::VideoFrame>& frame,
- base::TimeTicks /* current_time */) {
- DCHECK(frame->format() == media::PIXEL_FORMAT_I420 ||
- frame->format() == media::PIXEL_FORMAT_I420A);
-
- if (first_frame_received_)
- return;
- first_frame_received_ = true;
-
- const SkAlphaType alpha = media::IsOpaque(frame->format())
- ? kOpaque_SkAlphaType
- : kPremul_SkAlphaType;
- const SkImageInfo info = SkImageInfo::MakeN32(
- frame->visible_rect().width(), frame->visible_rect().height(), alpha);
-
- sk_sp<SkSurface> surface = SkSurface::MakeRaster(info);
- DCHECK(surface);
-
- SkPixmap pixmap;
- if (!skia::GetWritablePixels(surface->getCanvas(), &pixmap)) {
- DLOG(ERROR) << "Error trying to map SkSurface's pixels";
- std::move(callback).Run(sk_sp<SkImage>());
- return;
- }
-
- const uint32_t destination_pixel_format =
- (kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR
- : libyuv::FOURCC_ARGB;
-
- libyuv::ConvertFromI420(frame->visible_data(media::VideoFrame::kYPlane),
- frame->stride(media::VideoFrame::kYPlane),
- frame->visible_data(media::VideoFrame::kUPlane),
- frame->stride(media::VideoFrame::kUPlane),
- frame->visible_data(media::VideoFrame::kVPlane),
- frame->stride(media::VideoFrame::kVPlane),
- static_cast<uint8_t*>(pixmap.writable_addr()),
- pixmap.width() * 4, pixmap.width(), pixmap.height(),
- destination_pixel_format);
-
- if (frame->format() == media::PIXEL_FORMAT_I420A) {
- DCHECK(!info.isOpaque());
- // This function copies any plane into the alpha channel of an ARGB image.
- libyuv::ARGBCopyYToAlpha(frame->visible_data(media::VideoFrame::kAPlane),
- frame->stride(media::VideoFrame::kAPlane),
- static_cast<uint8_t*>(pixmap.writable_addr()),
- pixmap.width() * 4, pixmap.width(),
- pixmap.height());
- }
-
- std::move(callback).Run(surface->makeImageSnapshot());
-}
-
-ImageCaptureFrameGrabber::ImageCaptureFrameGrabber()
- : frame_grab_in_progress_(false), weak_factory_(this) {}
-
-ImageCaptureFrameGrabber::~ImageCaptureFrameGrabber() {
- DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-void ImageCaptureFrameGrabber::GrabFrame(
- blink::WebMediaStreamTrack* track,
- std::unique_ptr<blink::WebImageCaptureGrabFrameCallbacks> callbacks,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!!callbacks);
-
- DCHECK(track && !track->IsNull() && track->GetPlatformTrack());
- DCHECK_EQ(blink::WebMediaStreamSource::kTypeVideo, track->Source().GetType());
-
- if (frame_grab_in_progress_) {
- // Reject grabFrame()s too close back to back.
- callbacks->OnError();
- return;
- }
-
- auto scoped_callbacks = blink::MakeScopedWebCallbacks(
- std::move(callbacks), base::BindOnce(&OnError));
-
- // A SingleShotFrameHandler is bound and given to the Track to guarantee that
- // only one VideoFrame is converted and delivered to OnSkImage(), otherwise
- // SKImages might be sent to resolved |callbacks| while DisconnectFromTrack()
- // is being processed, which might be further held up if UI is busy, see
- // https://crbug.com/623042.
- frame_grab_in_progress_ = true;
- blink::MediaStreamVideoSink::ConnectToTrack(
- *track,
- base::BindRepeating(
- &SingleShotFrameHandler::OnVideoFrameOnIOThread,
- base::MakeRefCounted<SingleShotFrameHandler>(),
- media::BindToLoop(
- std::move(task_runner),
- base::BindRepeating(&ImageCaptureFrameGrabber::OnSkImage,
- weak_factory_.GetWeakPtr(),
- base::Passed(&scoped_callbacks)))),
- false);
-}
-
-void ImageCaptureFrameGrabber::OnSkImage(
- blink::ScopedWebCallbacks<blink::WebImageCaptureGrabFrameCallbacks>
- callbacks,
- sk_sp<SkImage> image) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- blink::MediaStreamVideoSink::DisconnectFromTrack();
- frame_grab_in_progress_ = false;
- if (image)
- callbacks.PassCallbacks()->OnSuccess(image);
- else
- callbacks.PassCallbacks()->OnError();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/image_capture/image_capture_frame_grabber.h b/chromium/content/renderer/image_capture/image_capture_frame_grabber.h
deleted file mode 100644
index fe2263eed57..00000000000
--- a/chromium/content/renderer/image_capture/image_capture_frame_grabber.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_IMAGE_CAPTURE_IMAGE_CAPTURE_FRAME_GRABBER_H_
-#define CONTENT_RENDERER_IMAGE_CAPTURE_IMAGE_CAPTURE_FRAME_GRABBER_H_
-
-#include <memory>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/scoped_web_callbacks.h"
-#include "third_party/blink/public/platform/web_image_capture_frame_grabber.h"
-#include "third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h"
-
-namespace blink {
-class WebMediaStreamTrack;
-}
-
-namespace content {
-
-// This class grabs Video Frames from a given Media Stream Video Track, binding
-// a method of an ephemeral SingleShotFrameHandler every time grabFrame() is
-// called. This method receives an incoming media::VideoFrame on a background
-// thread and converts it into the appropriate SkBitmap which is sent back to
-// OnSkBitmap(). This class is single threaded throughout.
-class CONTENT_EXPORT ImageCaptureFrameGrabber final
- : public blink::WebImageCaptureFrameGrabber,
- public blink::MediaStreamVideoSink {
- public:
- using SkImageDeliverCB = base::Callback<void(sk_sp<SkImage>)>;
-
- ImageCaptureFrameGrabber();
- ~ImageCaptureFrameGrabber() override;
-
- // blink::WebImageCaptureFrameGrabber implementation.
- void GrabFrame(
- blink::WebMediaStreamTrack* track,
- std::unique_ptr<blink::WebImageCaptureGrabFrameCallbacks> callbacks,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
-
- private:
- // Internal class to receive, convert and forward one frame.
- class SingleShotFrameHandler;
-
- void OnSkImage(blink::ScopedWebCallbacks<
- blink::WebImageCaptureGrabFrameCallbacks> callbacks,
- sk_sp<SkImage> image);
-
- // Flag to indicate that there is a frame grabbing in progress.
- bool frame_grab_in_progress_;
-
- base::ThreadChecker thread_checker_;
- base::WeakPtrFactory<ImageCaptureFrameGrabber> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageCaptureFrameGrabber);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_IMAGE_CAPTURE_IMAGE_CAPTURE_FRAME_GRABBER_H_
diff --git a/chromium/content/renderer/image_downloader/single_image_downloader.cc b/chromium/content/renderer/image_downloader/single_image_downloader.cc
deleted file mode 100644
index 682e3ee491f..00000000000
--- a/chromium/content/renderer/image_downloader/single_image_downloader.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/image_downloader/single_image_downloader.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-
-namespace content {
-
-// Static
-void SingleImageDownloader::DownloadImage(
- base::WeakPtr<RenderFrame> render_frame,
- const GURL& url,
- const DownloadImageCallback& cb) {
- DCHECK(!cb.is_null());
- if (!render_frame) {
- cb.Run(SkBitmap());
- return;
- }
-
- std::unique_ptr<ImageDownloaderBase> image_downloader(
- new ImageDownloaderBase(render_frame.get()));
- ImageDownloaderBase* image_downloader_ptr = image_downloader.get();
- image_downloader_ptr->DownloadImage(
- url, false, false,
- base::BindOnce(&SingleImageDownloader::DidDownloadImage,
- std::move(image_downloader), cb));
-}
-
-// Static
-void SingleImageDownloader::DidDownloadImage(
- std::unique_ptr<ImageDownloaderBase> image_downloader,
- const DownloadImageCallback& callback,
- int http_status_code,
- const std::vector<SkBitmap>& images) {
- DCHECK(!callback.is_null());
- callback.Run(images.empty() ? SkBitmap() : images[0]);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/image_downloader/single_image_downloader.h b/chromium/content/renderer/image_downloader/single_image_downloader.h
deleted file mode 100644
index bc28c9129ce..00000000000
--- a/chromium/content/renderer/image_downloader/single_image_downloader.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_IMAGE_DOWNLOADER_SINGLE_IMAGE_DOWNLOADER_H_
-#define CONTENT_RENDERER_IMAGE_DOWNLOADER_SINGLE_IMAGE_DOWNLOADER_H_
-
-#include "base/memory/weak_ptr.h"
-#include "content/renderer/image_downloader/image_downloader_base.h"
-
-namespace content {
-
-// A one time image downloader that will download a single image. When there are
-// multiple frames, returns the first one. Returns an empty bitmap if
-// downloading fails. This class does not impose size limitation on the image.
-class SingleImageDownloader {
- public:
- using DownloadImageCallback = base::Callback<void(const SkBitmap&)>;
-
- // Called to download the image in given |url|, and run |cb| when done.
- // A new ImageDownloaderBase will be created and used to download the image,
- // and will be destructed when downloading finishes or |render_frame| is
- // destructed.
- static void DownloadImage(base::WeakPtr<RenderFrame> render_frame,
- const GURL& url,
- const DownloadImageCallback& cb);
-
- private:
- // Callback when downloading finishes. |image_downloader| is passed in as a
- // unique_ptr to keep it alive while downloading and destroy it after this
- // callback is called.
- static void DidDownloadImage(
- std::unique_ptr<ImageDownloaderBase> image_downloader,
- const DownloadImageCallback& callback,
- int http_status_code,
- const std::vector<SkBitmap>& images);
-
- DISALLOW_COPY_AND_ASSIGN(SingleImageDownloader);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_IMAGE_DOWNLOADER_SINGLE_IMAGE_DOWNLOADER_H_
diff --git a/chromium/content/renderer/input/frame_input_handler_impl.cc b/chromium/content/renderer/input/frame_input_handler_impl.cc
index 6611df0f055..f7d656c3fbc 100644
--- a/chromium/content/renderer/input/frame_input_handler_impl.cc
+++ b/chromium/content/renderer/input/frame_input_handler_impl.cc
@@ -188,7 +188,7 @@ void FrameInputHandlerImpl::CopyToFindPboard() {
#if defined(OS_MACOSX)
if (!main_thread_task_runner_->BelongsToCurrentThread()) {
RunOnMainThread(
- base::Bind(&FrameInputHandlerImpl::CopyToFindPboard, weak_this_));
+ base::BindOnce(&FrameInputHandlerImpl::CopyToFindPboard, weak_this_));
return;
}
if (!render_frame_)
diff --git a/chromium/content/renderer/input/input_handler_manager_client.h b/chromium/content/renderer/input/input_handler_manager_client.h
deleted file mode 100644
index 6f91e63a338..00000000000
--- a/chromium/content/renderer/input/input_handler_manager_client.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_CLIENT_H_
-#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_CLIENT_H_
-
-#include "base/callback.h"
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "cc/input/touch_action.h"
-#include "content/common/content_export.h"
-#include "content/public/common/input_event_ack_state.h"
-#include "third_party/blink/public/platform/web_input_event_result.h"
-#include "ui/events/blink/web_input_event_traits.h"
-#include "ui/gfx/geometry/vector2d_f.h"
-
-namespace ui {
-class LatencyInfo;
-class SynchronousInputHandlerProxy;
-struct DidOverscrollParams;
-}
-
-namespace content {
-class InputHandlerManager;
-class MainThreadEventQueue;
-
-class CONTENT_EXPORT InputHandlerManagerClient {
- public:
- virtual ~InputHandlerManagerClient() {}
-
- // Called from the main thread.
- virtual void SetInputHandlerManager(InputHandlerManager*) = 0;
-
- // Called from the compositor thread.
- virtual void RegisterRoutingID(
- int routing_id,
- const scoped_refptr<MainThreadEventQueue>& input_event_queue) = 0;
- virtual void UnregisterRoutingID(int routing_id) = 0;
- virtual void RegisterAssociatedRenderFrameRoutingID(
- int render_frame_routing_id,
- int render_view_routing_id) = 0;
- virtual void QueueClosureForMainThreadEventQueue(
- int routing_id,
- const base::Closure& closure) = 0;
-
- // |HandleInputEvent| will respond to overscroll by calling the passed in
- // callback.
- // Otherwise |DidOverscroll| will be fired.
- virtual void DidOverscroll(int routing_id,
- const ui::DidOverscrollParams& params) = 0;
- virtual void DidStartScrollingViewport(int routing_id) = 0;
- virtual void DispatchNonBlockingEventToMainThread(
- int routing_id,
- ui::WebScopedInputEvent event,
- const ui::LatencyInfo& latency_info) = 0;
- virtual void SetWhiteListedTouchAction(int routing_id,
- cc::TouchAction touch_action,
- uint32_t unique_touch_event_id,
- InputEventAckState ack_state) = 0;
-
- protected:
- InputHandlerManagerClient() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(InputHandlerManagerClient);
-};
-
-class CONTENT_EXPORT SynchronousInputHandlerProxyClient {
- public:
- virtual ~SynchronousInputHandlerProxyClient() {}
-
- virtual void DidAddSynchronousHandlerProxy(
- int routing_id,
- ui::SynchronousInputHandlerProxy* synchronous_handler) = 0;
- virtual void DidRemoveSynchronousHandlerProxy(int routing_id) = 0;
-
- protected:
- SynchronousInputHandlerProxyClient() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SynchronousInputHandlerProxyClient);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_CLIENT_H_
diff --git a/chromium/content/renderer/input/main_thread_event_queue.cc b/chromium/content/renderer/input/main_thread_event_queue.cc
index 4a77a0ee11f..cd94fbf354d 100644
--- a/chromium/content/renderer/input/main_thread_event_queue.cc
+++ b/chromium/content/renderer/input/main_thread_event_queue.cc
@@ -68,8 +68,8 @@ class QueuedWebInputEvent : public ScopedWebInputEventWithLatencyInfo,
// There is no pointermove at this point in the queue.
DCHECK(event().GetType() != WebInputEvent::kPointerMove &&
other_event->event().GetType() != WebInputEvent::kPointerMove);
- return event().GetType() == WebInputEvent::kPointerRawMove &&
- other_event->event().GetType() == WebInputEvent::kPointerRawMove;
+ return event().GetType() == WebInputEvent::kPointerRawUpdate &&
+ other_event->event().GetType() == WebInputEvent::kPointerRawUpdate;
}
FilterResult FilterNewEvent(MainThreadEventQueueTask* other_task) override {
@@ -88,7 +88,7 @@ class QueuedWebInputEvent : public ScopedWebInputEventWithLatencyInfo,
if (!ScopedWebInputEventWithLatencyInfo::CanCoalesceWith(*other_event)) {
// Two pointerevents may not be able to coalesce but we should continue
- // looking further down the queue if both of them were rawmove or move
+ // looking further down the queue if both of them were rawupdate or move
// events and only their pointer_type, id, or event_type was different.
if (ArePointerMoveEventTypes(other_event))
return FilterResult::KeepIterating;
@@ -323,10 +323,10 @@ void MainThreadEventQueue::HandleEvent(
event_callback = std::move(callback);
}
- if (has_pointerrawmove_handlers_) {
+ if (has_pointerrawupdate_handlers_) {
if (event->GetType() == WebInputEvent::kMouseMove) {
ui::WebScopedInputEvent raw_event(new blink::WebPointerEvent(
- WebInputEvent::kPointerRawMove,
+ WebInputEvent::kPointerRawUpdate,
*(static_cast<blink::WebMouseEvent*>(event.get()))));
std::unique_ptr<QueuedWebInputEvent> raw_queued_event(
new QueuedWebInputEvent(std::move(raw_event), latency, false,
@@ -341,7 +341,7 @@ void MainThreadEventQueue::HandleEvent(
if (touch_point.state == blink::WebTouchPoint::kStateMoved) {
ui::WebScopedInputEvent raw_event(
new blink::WebPointerEvent(touch_event, touch_point));
- raw_event->SetType(WebInputEvent::kPointerRawMove);
+ raw_event->SetType(WebInputEvent::kPointerRawUpdate);
std::unique_ptr<QueuedWebInputEvent> raw_queued_event(
new QueuedWebInputEvent(std::move(raw_event), latency, false,
HandledEventCallback(), false));
@@ -443,7 +443,7 @@ void MainThreadEventQueue::DispatchEvents() {
if (current_task_index >= queue_size ||
current_task_index >= shared_state_.events_.size())
break;
- if (IsRawMoveEvent(shared_state_.events_.at(current_task_index))) {
+ if (IsRawUpdateEvent(shared_state_.events_.at(current_task_index))) {
task = shared_state_.events_.remove(current_task_index);
--queue_size;
--current_task_index;
@@ -571,17 +571,17 @@ void MainThreadEventQueue::QueueEvent(
SetNeedsMainFrame();
}
-bool MainThreadEventQueue::IsRawMoveEvent(
+bool MainThreadEventQueue::IsRawUpdateEvent(
const std::unique_ptr<MainThreadEventQueueTask>& item) const {
return item->IsWebInputEvent() &&
static_cast<const QueuedWebInputEvent*>(item.get())
->event()
- .GetType() == blink::WebInputEvent::kPointerRawMove;
+ .GetType() == blink::WebInputEvent::kPointerRawUpdate;
}
bool MainThreadEventQueue::ShouldFlushQueue(
const std::unique_ptr<MainThreadEventQueueTask>& item) const {
- if (IsRawMoveEvent(item))
+ if (IsRawUpdateEvent(item))
return false;
return !IsRafAlignedEvent(item);
}
@@ -676,8 +676,8 @@ void MainThreadEventQueue::SetNeedsUnbufferedInputForDebugger(bool unbuffered) {
needs_unbuffered_input_for_debugger_ = unbuffered;
}
-void MainThreadEventQueue::HasPointerRawMoveEventHandlers(bool has_handlers) {
- has_pointerrawmove_handlers_ = has_handlers;
+void MainThreadEventQueue::HasPointerRawUpdateEventHandlers(bool has_handlers) {
+ has_pointerrawupdate_handlers_ = has_handlers;
}
void MainThreadEventQueue::RequestUnbufferedInputEvents() {
diff --git a/chromium/content/renderer/input/main_thread_event_queue.h b/chromium/content/renderer/input/main_thread_event_queue.h
index 161eab619d2..ccb56ead424 100644
--- a/chromium/content/renderer/input/main_thread_event_queue.h
+++ b/chromium/content/renderer/input/main_thread_event_queue.h
@@ -104,7 +104,7 @@ class CONTENT_EXPORT MainThreadEventQueue
void SetNeedsLowLatency(bool low_latency);
void SetNeedsUnbufferedInputForDebugger(bool unbuffered);
- void HasPointerRawMoveEventHandlers(bool has_handlers);
+ void HasPointerRawUpdateEventHandlers(bool has_handlers);
// Request unbuffered input events until next pointerup.
void RequestUnbufferedInputEvents();
@@ -133,7 +133,7 @@ class CONTENT_EXPORT MainThreadEventQueue
const ui::LatencyInfo& latency,
HandledEventCallback handled_callback);
- bool IsRawMoveEvent(
+ bool IsRawUpdateEvent(
const std::unique_ptr<MainThreadEventQueueTask>& item) const;
bool ShouldFlushQueue(
const std::unique_ptr<MainThreadEventQueueTask>& item) const;
@@ -155,7 +155,7 @@ class CONTENT_EXPORT MainThreadEventQueue
bool needs_unbuffered_input_for_debugger_;
bool allow_raf_aligned_input_;
bool needs_low_latency_until_pointer_up_ = false;
- bool has_pointerrawmove_handlers_ = false;
+ bool has_pointerrawupdate_handlers_ = false;
// Contains data to be shared between main thread and compositor thread.
struct SharedState {
diff --git a/chromium/content/renderer/input/main_thread_event_queue_unittest.cc b/chromium/content/renderer/input/main_thread_event_queue_unittest.cc
index 7f794feab24..6dca0c66b30 100644
--- a/chromium/content/renderer/input/main_thread_event_queue_unittest.cc
+++ b/chromium/content/renderer/input/main_thread_event_queue_unittest.cc
@@ -1357,7 +1357,7 @@ TEST_F(MainThreadEventQueueTest, UnbufferedDispatchTouchEvent) {
}
TEST_F(MainThreadEventQueueTest, PointerEventsCoalescing) {
- queue_->HasPointerRawMoveEventHandlers(true);
+ queue_->HasPointerRawUpdateEventHandlers(true);
WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
WebInputEvent::kMouseMove, 10, 10, 0);
SyntheticWebTouchEvent touch_move;
@@ -1385,7 +1385,7 @@ TEST_F(MainThreadEventQueueTest, PointerEventsCoalescing) {
EXPECT_FALSE(needs_main_frame_);
}
-TEST_F(MainThreadEventQueueTest, PointerRawMoveEvents) {
+TEST_F(MainThreadEventQueueTest, PointerRawUpdateEvents) {
WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
WebInputEvent::kMouseMove, 10, 10, 0);
@@ -1402,14 +1402,14 @@ TEST_F(MainThreadEventQueueTest, PointerRawMoveEvents) {
EXPECT_EQ(0u, event_queue().size());
EXPECT_FALSE(needs_main_frame_);
- queue_->HasPointerRawMoveEventHandlers(true);
+ queue_->HasPointerRawUpdateEventHandlers(true);
HandleEvent(mouse_move, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
EXPECT_EQ(2u, event_queue().size());
RunPendingTasksWithSimulatedRaf();
EXPECT_EQ(0u, event_queue().size());
EXPECT_FALSE(needs_main_frame_);
- queue_->HasPointerRawMoveEventHandlers(false);
+ queue_->HasPointerRawUpdateEventHandlers(false);
SyntheticWebTouchEvent touch_move;
touch_move.PressPoint(10, 10);
touch_move.MovePoint(0, 50, 50);
@@ -1419,7 +1419,7 @@ TEST_F(MainThreadEventQueueTest, PointerRawMoveEvents) {
EXPECT_EQ(0u, event_queue().size());
EXPECT_FALSE(needs_main_frame_);
- queue_->HasPointerRawMoveEventHandlers(true);
+ queue_->HasPointerRawUpdateEventHandlers(true);
HandleEvent(touch_move, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
EXPECT_EQ(2u, event_queue().size());
RunPendingTasksWithSimulatedRaf();
diff --git a/chromium/content/renderer/input/render_widget_input_handler.cc b/chromium/content/renderer/input/render_widget_input_handler.cc
index d5815b1d394..e0480bee72c 100644
--- a/chromium/content/renderer/input/render_widget_input_handler.cc
+++ b/chromium/content/renderer/input/render_widget_input_handler.cc
@@ -12,6 +12,7 @@
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
+#include "cc/trees/element_id.h"
#include "cc/trees/swap_promise_monitor.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "content/common/input/input_event_ack.h"
@@ -28,6 +29,7 @@
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_float_point.h"
#include "third_party/blink/public/platform/web_float_size.h"
+#include "third_party/blink/public/platform/web_gesture_device.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
#include "third_party/blink/public/platform/web_keyboard_event.h"
#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
@@ -37,6 +39,7 @@
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_node.h"
+#include "ui/events/blink/event_with_callback.h"
#include "ui/events/blink/web_input_event_traits.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/point_conversions.h"
@@ -211,8 +214,10 @@ RenderWidgetInputHandler::RenderWidgetInputHandler(
widget_(widget),
handling_input_event_(false),
handling_event_overscroll_(nullptr),
+ handling_injected_scroll_params_(nullptr),
handling_event_type_(WebInputEvent::kUndefined),
- suppress_next_char_events_(false) {
+ suppress_next_char_events_(false),
+ last_injected_gesture_was_begin_(false) {
DCHECK(delegate);
DCHECK(widget);
delegate->SetInputHandler(this);
@@ -313,6 +318,14 @@ void RenderWidgetInputHandler::HandleInputEvent(
base::AutoReset<base::Optional<cc::TouchAction>>
handling_touch_action_resetter(&handling_touch_action_, base::nullopt);
+ // Calls into |InjectGestureScrollEvent()| while handling this event
+ // will populate injected_scroll_params.
+ std::unique_ptr<std::vector<InjectScrollGestureParams>>
+ injected_scroll_params;
+ base::AutoReset<std::unique_ptr<std::vector<InjectScrollGestureParams>>*>
+ injected_scroll_resetter(&handling_injected_scroll_params_,
+ &injected_scroll_params);
+
#if defined(OS_ANDROID)
ImeEventGuard guard(widget_);
#endif
@@ -425,6 +438,15 @@ void RenderWidgetInputHandler::HandleInputEvent(
? INPUT_EVENT_ACK_STATE_NOT_CONSUMED
: INPUT_EVENT_ACK_STATE_CONSUMED;
+ // The handling of some input events on the main thread may require injecting
+ // scroll gestures back into blink, e.g., a mousedown on a scrollbar. We
+ // do this here so that we can attribute lateny information from the mouse as
+ // a scroll interaction, instead of just classifying as mouse input.
+ if (injected_scroll_params && injected_scroll_params->size()) {
+ HandleInjectedScrollGestures(*injected_scroll_params, input_event,
+ latency_info);
+ }
+
// Send gesture scroll events and their dispositions to the compositor thread,
// so that they can be used to produce the elastic overscroll effect on Mac.
if (input_event.GetType() == WebInputEvent::kGestureScrollBegin ||
@@ -503,6 +525,148 @@ void RenderWidgetInputHandler::DidOverscrollFromBlink(
delegate_->OnDidOverscroll(*params);
}
+void RenderWidgetInputHandler::InjectGestureScrollEvent(
+ blink::WebGestureDevice device,
+ const blink::WebFloatSize& delta,
+ ui::input_types::ScrollGranularity granularity,
+ cc::ElementId scrollable_area_element_id,
+ WebInputEvent::Type injected_type) {
+ DCHECK(ui::IsGestureScroll(injected_type));
+ // If we're currently handling an input event, cache the appropriate
+ // parameters so we can dispatch the events directly once blink finishes
+ // handling the event.
+ // Otherwise, queue the event on the main thread event queue.
+ // The latter may occur when scrollbar scrolls are injected due to
+ // autoscroll timer - i.e. not within the handling of a mouse event.
+ // We don't always just enqueue events, since events queued to the
+ // MainThreadEventQueue in the middle of dispatch (which we are) won't
+ // be dispatched until the next time the queue gets to run. The side effect
+ // of that would be an extra frame of latency if we're injecting a scroll
+ // during the handling of a rAF aligned input event, such as mouse move.
+ if (handling_injected_scroll_params_) {
+ // Multiple gestures may be injected during the dispatch of a single
+ // input event (e.g. Begin/Update). Create a vector and append to the
+ // end of it - the gestures will subsequently be injected in order.
+ if (!*handling_injected_scroll_params_) {
+ *handling_injected_scroll_params_ =
+ std::make_unique<std::vector<InjectScrollGestureParams>>();
+ }
+
+ InjectScrollGestureParams params{device, delta, granularity,
+ scrollable_area_element_id, injected_type};
+ (*handling_injected_scroll_params_)->push_back(params);
+ } else {
+ base::TimeTicks now = base::TimeTicks::Now();
+ std::unique_ptr<WebGestureEvent> gesture_event =
+ ui::GenerateInjectedScrollGesture(injected_type, now, device,
+ WebFloatPoint(0, 0), delta,
+ granularity);
+ if (injected_type == WebInputEvent::Type::kGestureScrollBegin) {
+ gesture_event->data.scroll_begin.scrollable_area_element_id =
+ scrollable_area_element_id.GetInternalValue();
+ }
+
+ ui::LatencyInfo latency_info;
+ ui::WebScopedInputEvent web_scoped_gesture_event(gesture_event.release());
+
+ // We have an empty callback since sending gestures through the
+ // system can generate overscroll params - if the user holds down the
+ // mouse on one of the arrows the autoscroll timer continues to fire to
+ // support infinite scrollers.
+ // For scrollbar, we ignore overscroll params, as scrollbar doesn't
+ // participate in overscroll.
+ // TODO(dlibby): Change blink to not propagate overscroll for scrollbar
+ // gestures and remove this callback. Currently non-blocking events are
+ // set up such that the callback is not propagated into the event queue,
+ // and we DCHECK when overscroll data is passed to the event handler.
+ HandledEventCallback handled_event = base::BindOnce(
+ [](InputEventAckState, const ui::LatencyInfo& latency_info,
+ std::unique_ptr<ui::DidOverscrollParams> overscroll_params,
+ base::Optional<cc::TouchAction> touch_action) {});
+ widget_->GetInputEventQueue()->HandleEvent(
+ std::move(web_scoped_gesture_event), latency_info,
+ DISPATCH_TYPE_BLOCKING, INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
+ std::move(handled_event));
+ }
+}
+
+void RenderWidgetInputHandler::HandleInjectedScrollGestures(
+ std::vector<InjectScrollGestureParams> injected_scroll_params,
+ const WebInputEvent& input_event,
+ const ui::LatencyInfo& original_latency_info) {
+ DCHECK(injected_scroll_params.size());
+
+ base::TimeTicks original_timestamp;
+ bool found_original_component = original_latency_info.FindLatency(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, &original_timestamp);
+ DCHECK(found_original_component);
+
+ WebFloatPoint position = ui::PositionInWidgetFromInputEvent(input_event);
+ for (const InjectScrollGestureParams& params : injected_scroll_params) {
+ // Set up a new LatencyInfo for the injected scroll - this is the original
+ // LatencyInfo for the input event that was being handled when the scroll
+ // was injected. This new LatencyInfo will have a modified type, and an
+ // additional scroll update component. Also set up a SwapPromiseMonitor that
+ // will cause the LatencyInfo to be sent up with the compositor frame, if
+ // the GSU causes a commit. This allows end to end latency to be logged for
+ // the injected scroll, annotated with the correct type.
+ ui::LatencyInfo scrollbar_latency_info(original_latency_info);
+
+ // Currently only scrollbar is supported - if this DCHECK hits due to a
+ // new type being injected, please modify the type passed to
+ // |set_source_event_type()|.
+ DCHECK(params.device == blink::WebGestureDevice::kScrollbar);
+ scrollbar_latency_info.set_source_event_type(
+ ui::SourceEventType::SCROLLBAR);
+ scrollbar_latency_info.AddLatencyNumber(
+ ui::LatencyComponentType::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT);
+
+ if (params.type == WebInputEvent::Type::kGestureScrollUpdate) {
+ if (input_event.GetType() != WebInputEvent::Type::kGestureScrollUpdate) {
+ scrollbar_latency_info.AddLatencyNumberWithTimestamp(
+ last_injected_gesture_was_begin_
+ ? ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT
+ : ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
+ original_timestamp, 1);
+ } else {
+ // If we're injecting a GSU in response to a GSU (touch drags of the
+ // scrollbar thumb in Blink handles GSUs, and reverses them with
+ // injected GSUs), the LatencyInfo will already have the appropriate
+ // SCROLL_UPDATE component set.
+ DCHECK(
+ scrollbar_latency_info.FindLatency(
+ ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
+ nullptr) ||
+ scrollbar_latency_info.FindLatency(
+ ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
+ nullptr));
+ }
+ }
+
+ std::unique_ptr<cc::SwapPromiseMonitor> swap_promise_monitor;
+ if (widget_->layer_tree_view()) {
+ swap_promise_monitor =
+ widget_->layer_tree_view()->CreateLatencyInfoSwapPromiseMonitor(
+ &scrollbar_latency_info);
+ }
+
+ std::unique_ptr<WebGestureEvent> gesture_event =
+ ui::GenerateInjectedScrollGesture(
+ params.type, input_event.TimeStamp(), params.device, position,
+ params.scroll_delta, params.granularity);
+ if (params.type == WebInputEvent::Type::kGestureScrollBegin) {
+ gesture_event->data.scroll_begin.scrollable_area_element_id =
+ params.scrollable_area_element_id.GetInternalValue();
+ last_injected_gesture_was_begin_ = true;
+ } else {
+ last_injected_gesture_was_begin_ = false;
+ }
+
+ widget_->GetWebWidget()->HandleInputEvent(
+ blink::WebCoalescedInputEvent(*gesture_event.get()));
+ }
+}
+
bool RenderWidgetInputHandler::DidChangeCursor(const WebCursor& cursor) {
if (current_cursor_.has_value() && current_cursor_.value() == cursor)
return false;
diff --git a/chromium/content/renderer/input/render_widget_input_handler.h b/chromium/content/renderer/input/render_widget_input_handler.h
index 3c945eb0ce9..919fbfdfd74 100644
--- a/chromium/content/renderer/input/render_widget_input_handler.h
+++ b/chromium/content/renderer/input/render_widget_input_handler.h
@@ -16,6 +16,7 @@
#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "ui/base/ui_base_types.h"
#include "ui/events/blink/did_overscroll_params.h"
+#include "ui/events/types/scroll_types.h"
namespace blink {
struct WebFloatPoint;
@@ -23,6 +24,7 @@ struct WebFloatSize;
} // namespace blink
namespace cc {
+struct ElementId;
struct OverscrollBehavior;
}
@@ -66,6 +68,12 @@ class CONTENT_EXPORT RenderWidgetInputHandler {
const blink::WebFloatSize& velocity,
const cc::OverscrollBehavior& behavior);
+ void InjectGestureScrollEvent(blink::WebGestureDevice device,
+ const blink::WebFloatSize& delta,
+ ui::input_types::ScrollGranularity granularity,
+ cc::ElementId scrollable_area_element_id,
+ blink::WebInputEvent::Type injected_type);
+
bool handling_input_event() const { return handling_input_event_; }
void set_handling_input_event(bool handling_input_event) {
handling_input_event_ = handling_input_event;
@@ -80,9 +88,22 @@ class CONTENT_EXPORT RenderWidgetInputHandler {
bool DidChangeCursor(const WebCursor& cursor);
private:
+ struct InjectScrollGestureParams {
+ blink::WebGestureDevice device;
+ gfx::Vector2dF scroll_delta;
+ ui::input_types::ScrollGranularity granularity;
+ cc::ElementId scrollable_area_element_id;
+ blink::WebInputEvent::Type type;
+ };
+
blink::WebInputEventResult HandleTouchEvent(
const blink::WebCoalescedInputEvent& coalesced_event);
+ void HandleInjectedScrollGestures(
+ std::vector<InjectScrollGestureParams> injected_scroll_params,
+ const WebInputEvent& input_event,
+ const ui::LatencyInfo& original_latency_info);
+
RenderWidgetInputHandlerDelegate* const delegate_;
RenderWidget* const widget_;
@@ -102,12 +123,23 @@ class CONTENT_EXPORT RenderWidgetInputHandler {
base::Optional<cc::TouchAction> handling_touch_action_;
+ // Used to hold a sequence of parameters corresponding to scroll gesture
+ // events that should be injected once the current input event is done
+ // being processed.
+ std::unique_ptr<std::vector<InjectScrollGestureParams>>*
+ handling_injected_scroll_params_;
+
// Type of the input event we are currently handling.
blink::WebInputEvent::Type handling_event_type_;
// Indicates if the next sequence of Char events should be suppressed or not.
bool suppress_next_char_events_;
+ // Whether the last injected scroll gesture was a GestureScrollBegin. Used to
+ // determine which GestureScrollUpdate is the first in a gesture sequence for
+ // latency classification.
+ bool last_injected_gesture_was_begin_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetInputHandler);
};
diff --git a/chromium/content/renderer/input/widget_input_handler_manager.cc b/chromium/content/renderer/input/widget_input_handler_manager.cc
index 6d1c7794f35..1b4e45aded5 100644
--- a/chromium/content/renderer/input/widget_input_handler_manager.cc
+++ b/chromium/content/renderer/input/widget_input_handler_manager.cc
@@ -257,16 +257,8 @@ void WidgetInputHandlerManager::DidStartScrollingViewport() {
void WidgetInputHandlerManager::GenerateScrollBeginAndSendToMainThread(
const blink::WebGestureEvent& update_event) {
DCHECK_EQ(update_event.GetType(), blink::WebInputEvent::kGestureScrollUpdate);
- blink::WebGestureEvent scroll_begin(update_event);
- scroll_begin.SetType(blink::WebInputEvent::kGestureScrollBegin);
- scroll_begin.data.scroll_begin.inertial_phase =
- update_event.data.scroll_update.inertial_phase;
- scroll_begin.data.scroll_begin.delta_x_hint =
- update_event.data.scroll_update.delta_x;
- scroll_begin.data.scroll_begin.delta_y_hint =
- update_event.data.scroll_update.delta_y;
- scroll_begin.data.scroll_begin.delta_hint_units =
- update_event.data.scroll_update.delta_units;
+ blink::WebGestureEvent scroll_begin =
+ ui::ScrollBeginFromScrollUpdate(update_event);
DispatchNonBlockingEventToMainThread(
ui::WebInputEventTraits::Clone(scroll_begin), ui::LatencyInfo());
diff --git a/chromium/content/renderer/installedapp/related_apps_fetcher.cc b/chromium/content/renderer/installedapp/related_apps_fetcher.cc
deleted file mode 100644
index ff62e938c20..00000000000
--- a/chromium/content/renderer/installedapp/related_apps_fetcher.cc
+++ /dev/null
@@ -1,49 +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/renderer/installedapp/related_apps_fetcher.h"
-
-#include "base/bind.h"
-#include "third_party/blink/public/common/manifest/manifest.h"
-#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
-#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
-#include "third_party/blink/public/platform/modules/installedapp/web_related_application.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace content {
-
-RelatedAppsFetcher::RelatedAppsFetcher(
- blink::mojom::ManifestManager* manifest_manager)
- : manifest_manager_(manifest_manager) {}
-
-RelatedAppsFetcher::~RelatedAppsFetcher() {}
-
-void RelatedAppsFetcher::GetManifestRelatedApplications(
- blink::GetManifestRelatedApplicationsCallback completion_callback) {
- manifest_manager_->RequestManifest(
- base::BindOnce(&RelatedAppsFetcher::OnGetManifestForRelatedApplications,
- base::Unretained(this), std::move(completion_callback)));
-}
-
-void RelatedAppsFetcher::OnGetManifestForRelatedApplications(
- blink::GetManifestRelatedApplicationsCallback completion_callback,
- const GURL& /*url*/,
- const blink::Manifest& manifest) {
- std::vector<blink::WebRelatedApplication> related_apps;
- for (const auto& relatedApplication : manifest.related_applications) {
- blink::WebRelatedApplication webRelatedApplication;
- webRelatedApplication.platform =
- blink::WebString::FromUTF16(relatedApplication.platform);
- webRelatedApplication.id =
- blink::WebString::FromUTF16(relatedApplication.id);
- if (!relatedApplication.url.is_empty()) {
- webRelatedApplication.url =
- blink::WebString::FromUTF8(relatedApplication.url.spec());
- }
- related_apps.push_back(std::move(webRelatedApplication));
- }
- std::move(completion_callback).Run(std::move(related_apps));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/installedapp/related_apps_fetcher.h b/chromium/content/renderer/installedapp/related_apps_fetcher.h
deleted file mode 100644
index 186491ab8e0..00000000000
--- a/chromium/content/renderer/installedapp/related_apps_fetcher.h
+++ /dev/null
@@ -1,50 +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_RENDERER_INSTALLEDAPP_RELATED_APPS_FETCHER_H
-#define CONTENT_RENDERER_INSTALLEDAPP_RELATED_APPS_FETCHER_H
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/modules/installedapp/web_related_apps_fetcher.h"
-
-namespace blink {
-struct Manifest;
-namespace mojom {
-class ManifestManager;
-}
-} // namespace blink
-
-namespace content {
-
-class ManifestManager;
-
-class CONTENT_EXPORT RelatedAppsFetcher : public blink::WebRelatedAppsFetcher {
- public:
- explicit RelatedAppsFetcher(blink::mojom::ManifestManager* manifest_manager);
- ~RelatedAppsFetcher() override;
-
- // blink::WebRelatedAppsFetcher overrides:
- void GetManifestRelatedApplications(
- blink::GetManifestRelatedApplicationsCallback completion_callback)
- override;
-
- private:
- // Callback for when the manifest has been fetched, triggered by a call to
- // getManifestRelatedApplications.
- void OnGetManifestForRelatedApplications(
- blink::GetManifestRelatedApplicationsCallback completion_callback,
- const GURL& url,
- const blink::Manifest& manifest);
-
- blink::mojom::ManifestManager* const manifest_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(RelatedAppsFetcher);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_INSTALLEDAPP_RELATED_APPS_FETCHER_H
diff --git a/chromium/content/renderer/java/gin_java_bridge_object.cc b/chromium/content/renderer/java/gin_java_bridge_object.cc
index 03af04d1f4f..cb947c1ae3e 100644
--- a/chromium/content/renderer/java/gin_java_bridge_object.cc
+++ b/chromium/content/renderer/java/gin_java_bridge_object.cc
@@ -38,7 +38,9 @@ GinJavaBridgeObject* GinJavaBridgeObject::InjectNamed(
if (controller.IsEmpty())
return NULL;
- global->Set(gin::StringToV8(isolate, object_name), controller.ToV8());
+ global->Set(context, gin::StringToV8(isolate, object_name), controller.ToV8())
+ .Check();
+
return object;
}
@@ -114,9 +116,10 @@ v8::Local<v8::FunctionTemplate> GinJavaBridgeObject::GetFunctionTemplate(
if (!function_template.IsEmpty())
return function_template;
function_template = gin::CreateFunctionTemplate(
- isolate, base::Bind(&GinJavaFunctionInvocationHelper::Invoke,
- base::Owned(new GinJavaFunctionInvocationHelper(
- name, dispatcher_))));
+ isolate,
+ base::BindRepeating(
+ &GinJavaFunctionInvocationHelper::Invoke,
+ base::Owned(new GinJavaFunctionInvocationHelper(name, dispatcher_))));
template_cache_.Set(name, function_template);
return function_template;
}
diff --git a/chromium/content/renderer/java/gin_java_bridge_value_converter.cc b/chromium/content/renderer/java/gin_java_bridge_value_converter.cc
index 70d11603e5a..6cc073f19ee 100644
--- a/chromium/content/renderer/java/gin_java_bridge_value_converter.cc
+++ b/chromium/content/renderer/java/gin_java_bridge_value_converter.cc
@@ -44,8 +44,7 @@ std::unique_ptr<base::Value> GinJavaBridgeValueConverter::FromV8Value(
bool GinJavaBridgeValueConverter::FromV8Object(
v8::Local<v8::Object> value,
std::unique_ptr<base::Value>* out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback) {
+ v8::Isolate* isolate) {
GinJavaBridgeObject* unwrapped;
if (!gin::ConvertFromV8(isolate, value, &unwrapped)) {
return false;
diff --git a/chromium/content/renderer/java/gin_java_bridge_value_converter.h b/chromium/content/renderer/java/gin_java_bridge_value_converter.h
index 1f42b60cf0b..fabbe7e072f 100644
--- a/chromium/content/renderer/java/gin_java_bridge_value_converter.h
+++ b/chromium/content/renderer/java/gin_java_bridge_value_converter.h
@@ -28,8 +28,7 @@ class GinJavaBridgeValueConverter : public content::V8ValueConverter::Strategy {
// content::V8ValueConverter::Strategy
bool FromV8Object(v8::Local<v8::Object> value,
std::unique_ptr<base::Value>* out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback) override;
+ v8::Isolate* isolate) override;
bool FromV8ArrayBuffer(v8::Local<v8::Object> value,
std::unique_ptr<base::Value>* out,
v8::Isolate* isolate) override;
diff --git a/chromium/content/renderer/loader/child_url_loader_factory_bundle.cc b/chromium/content/renderer/loader/child_url_loader_factory_bundle.cc
index 337d720b577..5457693f5cb 100644
--- a/chromium/content/renderer/loader/child_url_loader_factory_bundle.cc
+++ b/chromium/content/renderer/loader/child_url_loader_factory_bundle.cc
@@ -76,8 +76,8 @@ class URLLoaderRelay : public network::mojom::URLLoaderClient,
std::move(callback));
}
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {
- client_sink_->OnReceiveCachedMetadata(data);
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override {
+ client_sink_->OnReceiveCachedMetadata(std::move(data));
}
void OnTransferSizeUpdated(int32_t transfer_size_diff) override {
diff --git a/chromium/content/renderer/loader/code_cache_loader_impl.cc b/chromium/content/renderer/loader/code_cache_loader_impl.cc
index 99ed960c003..983fc82ca11 100644
--- a/chromium/content/renderer/loader/code_cache_loader_impl.cc
+++ b/chromium/content/renderer/loader/code_cache_loader_impl.cc
@@ -57,7 +57,7 @@ void CodeCacheLoaderImpl::FetchFromCodeCacheSynchronously(
// Set the output data
*response_time_out = response_time_for_sync_load_;
- *data_out = data_for_sync_load_;
+ *data_out = std::move(data_for_sync_load_);
}
void CodeCacheLoaderImpl::FetchFromCodeCache(
@@ -82,11 +82,10 @@ void CodeCacheLoaderImpl::FetchFromCodeCacheImpl(
fetch_event));
}
-void CodeCacheLoaderImpl::OnReceiveCachedCode(
- FetchCodeCacheCallback callback,
- base::WaitableEvent* fetch_event,
- base::Time response_time,
- const std::vector<uint8_t>& data) {
+void CodeCacheLoaderImpl::OnReceiveCachedCode(FetchCodeCacheCallback callback,
+ base::WaitableEvent* fetch_event,
+ base::Time response_time,
+ base::span<const uint8_t> data) {
// The loader would be destroyed once the fetch has completed. On terminate
// the fetch event would be signalled and the fetch should complete and hence
// we should not see this callback anymore.
@@ -97,10 +96,10 @@ void CodeCacheLoaderImpl::OnReceiveCachedCode(
}
void CodeCacheLoaderImpl::ReceiveDataForSynchronousFetch(
- const base::Time& response_time,
- const std::vector<uint8_t>& data) {
+ base::Time response_time,
+ base::span<const uint8_t> data) {
response_time_for_sync_load_ = response_time;
- data_for_sync_load_ = data;
+ data_for_sync_load_.assign(data.begin(), data.end());
}
void CodeCacheLoaderImpl::OnTerminate(base::WaitableEvent* fetch_event,
diff --git a/chromium/content/renderer/loader/code_cache_loader_impl.h b/chromium/content/renderer/loader/code_cache_loader_impl.h
index 33661293dc8..f9d7ad7143e 100644
--- a/chromium/content/renderer/loader/code_cache_loader_impl.h
+++ b/chromium/content/renderer/loader/code_cache_loader_impl.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_LOADER_CODE_CACHE_LOADER_IMPL_H_
#define CONTENT_RENDERER_LOADER_CODE_CACHE_LOADER_IMPL_H_
+#include "base/containers/span.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/waitable_event.h"
#include "base/synchronization/waitable_event_watcher.h"
@@ -44,9 +45,9 @@ class CodeCacheLoaderImpl : public blink::CodeCacheLoader {
void OnReceiveCachedCode(FetchCodeCacheCallback callback,
base::WaitableEvent* event,
base::Time response_time,
- const std::vector<uint8_t>& data);
- void ReceiveDataForSynchronousFetch(const base::Time& response_time,
- const std::vector<uint8_t>& data);
+ base::span<const uint8_t> data);
+ void ReceiveDataForSynchronousFetch(base::Time response_time,
+ base::span<const uint8_t> data);
void OnTerminate(base::WaitableEvent* fetch_event,
base::WaitableEvent* terminate_event);
diff --git a/chromium/content/renderer/loader/navigation_body_loader.cc b/chromium/content/renderer/loader/navigation_body_loader.cc
index 5a3271a468d..6b6a6eaf173 100644
--- a/chromium/content/renderer/loader/navigation_body_loader.cc
+++ b/chromium/content/renderer/loader/navigation_body_loader.cc
@@ -122,14 +122,13 @@ void NavigationBodyLoader::OnUploadProgress(int64_t current_position,
NOTREACHED();
}
-void NavigationBodyLoader::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
+void NavigationBodyLoader::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
// Even if IsolatedCodeCaching is landed, this code is still used by
// ServiceWorker.
// TODO(horo, kinuko): Make a test to cover this function.
// TODO(https://crbug.com/930000): Add support for inline script code caching
// with the service worker service.
- client_->BodyCodeCacheReceived(data);
+ client_->BodyCodeCacheReceived(std::move(data));
}
void NavigationBodyLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
@@ -139,6 +138,8 @@ void NavigationBodyLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
void NavigationBodyLoader::OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle handle) {
+ TRACE_EVENT1("loading", "NavigationBodyLoader::OnStartLoadingResponseBody",
+ "url", resource_load_info_->url.possibly_invalid_spec());
DCHECK(!has_received_body_handle_);
DCHECK(!has_received_completion_);
has_received_body_handle_ = true;
@@ -171,6 +172,8 @@ void NavigationBodyLoader::SetDefersLoading(bool defers) {
void NavigationBodyLoader::StartLoadingBody(
WebNavigationBodyLoader::Client* client,
bool use_isolated_code_cache) {
+ TRACE_EVENT1("loading", "NavigationBodyLoader::StartLoadingBody", "url",
+ resource_load_info_->url.possibly_invalid_spec());
client_ = client;
NotifyResourceResponseReceived(render_frame_id_, resource_load_info_.get(),
@@ -187,8 +190,8 @@ void NavigationBodyLoader::StartLoadingBody(
}
}
-void NavigationBodyLoader::CodeCacheReceived(const base::Time& response_time,
- const std::vector<uint8_t>& data) {
+void NavigationBodyLoader::CodeCacheReceived(base::Time response_time,
+ base::span<const uint8_t> data) {
if (head_.response_time == response_time && client_) {
base::WeakPtr<NavigationBodyLoader> weak_self = weak_factory_.GetWeakPtr();
client_->BodyCodeCacheReceived(data);
@@ -216,6 +219,8 @@ void NavigationBodyLoader::OnConnectionClosed() {
}
void NavigationBodyLoader::OnReadable(MojoResult unused) {
+ TRACE_EVENT1("loading", "NavigationBodyLoader::OnReadable", "url",
+ resource_load_info_->url.possibly_invalid_spec());
if (has_seen_end_of_data_ || is_deferred_ || is_in_on_readable_)
return;
// Protect against reentrancy:
@@ -233,6 +238,8 @@ void NavigationBodyLoader::OnReadable(MojoResult unused) {
}
void NavigationBodyLoader::ReadFromDataPipe() {
+ TRACE_EVENT1("loading", "NavigationBodyLoader::ReadFromDataPipe", "url",
+ resource_load_info_->url.possibly_invalid_spec());
uint32_t num_bytes_consumed = 0;
while (!is_deferred_) {
const void* buffer = nullptr;
diff --git a/chromium/content/renderer/loader/navigation_body_loader.h b/chromium/content/renderer/loader/navigation_body_loader.h
index a9af6ead28f..88b0b4912bc 100644
--- a/chromium/content/renderer/loader/navigation_body_loader.h
+++ b/chromium/content/renderer/loader/navigation_body_loader.h
@@ -109,14 +109,14 @@ class CONTENT_EXPORT NavigationBodyLoader
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle handle) override;
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
- void CodeCacheReceived(const base::Time& response_time,
- const std::vector<uint8_t>& data);
+ void CodeCacheReceived(base::Time response_time,
+ base::span<const uint8_t> data);
void BindURLLoaderAndContinue();
void OnConnectionClosed();
void OnReadable(MojoResult unused);
diff --git a/chromium/content/renderer/loader/request_extra_data.h b/chromium/content/renderer/loader/request_extra_data.h
index 323a14930d5..56995d429b4 100644
--- a/chromium/content/renderer/loader/request_extra_data.h
+++ b/chromium/content/renderer/loader/request_extra_data.h
@@ -77,6 +77,12 @@ class CONTENT_EXPORT RequestExtraData : public blink::WebURLRequest::ExtraData {
scoped_refptr<FrameRequestBlocker> frame_request_blocker() {
return frame_request_blocker_;
}
+ bool allow_cross_origin_auth_prompt() const {
+ return allow_cross_origin_auth_prompt_;
+ }
+ void set_allow_cross_origin_auth_prompt(bool allow_cross_origin_auth_prompt) {
+ allow_cross_origin_auth_prompt_ = allow_cross_origin_auth_prompt;
+ }
void CopyToResourceRequest(network::ResourceRequest* request) const;
@@ -87,6 +93,7 @@ class CONTENT_EXPORT RequestExtraData : public blink::WebURLRequest::ExtraData {
bool block_mixed_plugin_content_ = false;
std::vector<std::unique_ptr<URLLoaderThrottle>> url_loader_throttles_;
scoped_refptr<FrameRequestBlocker> frame_request_blocker_;
+ bool allow_cross_origin_auth_prompt_ = false;
DISALLOW_COPY_AND_ASSIGN(RequestExtraData);
};
diff --git a/chromium/content/renderer/loader/resource_dispatcher.cc b/chromium/content/renderer/loader/resource_dispatcher.cc
index 3d9d92acda0..2438d65be7f 100644
--- a/chromium/content/renderer/loader/resource_dispatcher.cc
+++ b/chromium/content/renderer/loader/resource_dispatcher.cc
@@ -25,6 +25,7 @@
#include "content/common/navigation_params.h"
#include "content/common/throttling_url_loader.h"
#include "content/public/common/navigation_policy.h"
+#include "content/public/common/origin_util.h"
#include "content/public/common/resource_type.h"
#include "content/public/common/url_utils.h"
#include "content/public/renderer/request_peer.h"
@@ -64,7 +65,7 @@ void CheckSchemeForReferrerPolicy(const network::ResourceRequest& request) {
net::URLRequest::
CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE) &&
request.referrer.SchemeIsCryptographic() &&
- !request.url.SchemeIsCryptographic()) {
+ !IsOriginSecure(request.url)) {
LOG(FATAL) << "Trying to send secure referrer for insecure request "
<< "without an appropriate referrer policy.\n"
<< "URL = " << request.url << "\n"
@@ -142,7 +143,7 @@ void ResourceDispatcher::OnUploadProgress(int request_id,
void ResourceDispatcher::OnReceivedResponse(
int request_id,
const network::ResourceResponseHead& response_head) {
- TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedResponse");
+ TRACE_EVENT0("loading", "ResourceDispatcher::OnReceivedResponse");
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (!request_info)
return;
@@ -177,14 +178,14 @@ void ResourceDispatcher::OnReceivedResponse(
void ResourceDispatcher::OnReceivedCachedMetadata(
int request_id,
- const std::vector<uint8_t>& data) {
+ base::span<const uint8_t> data) {
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (!request_info)
return;
if (data.size()) {
request_info->peer->OnReceivedCachedMetadata(
- reinterpret_cast<const char*>(&data.front()), data.size());
+ reinterpret_cast<const char*>(data.data()), data.size());
}
}
@@ -203,7 +204,7 @@ void ResourceDispatcher::OnReceivedRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedRedirect");
+ TRACE_EVENT0("loading", "ResourceDispatcher::OnReceivedRedirect");
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (!request_info)
return;
@@ -267,7 +268,7 @@ void ResourceDispatcher::FollowPendingRedirect(
void ResourceDispatcher::OnRequestComplete(
int request_id,
const network::URLLoaderCompletionStatus& status) {
- TRACE_EVENT0("loader", "ResourceDispatcher::OnRequestComplete");
+ TRACE_EVENT0("loading", "ResourceDispatcher::OnRequestComplete");
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (!request_info)
diff --git a/chromium/content/renderer/loader/resource_dispatcher.h b/chromium/content/renderer/loader/resource_dispatcher.h
index 9fcf738a3c8..7ab20bad499 100644
--- a/chromium/content/renderer/loader/resource_dispatcher.h
+++ b/chromium/content/renderer/loader/resource_dispatcher.h
@@ -228,8 +228,7 @@ class CONTENT_EXPORT ResourceDispatcher {
// Message response handlers, called by the message handler for this process.
void OnUploadProgress(int request_id, int64_t position, int64_t size);
void OnReceivedResponse(int request_id, const network::ResourceResponseHead&);
- void OnReceivedCachedMetadata(int request_id,
- const std::vector<uint8_t>& data);
+ void OnReceivedCachedMetadata(int request_id, base::span<const uint8_t> data);
void OnReceivedRedirect(
int request_id,
const net::RedirectInfo& redirect_info,
diff --git a/chromium/content/renderer/loader/resource_dispatcher_unittest.cc b/chromium/content/renderer/loader/resource_dispatcher_unittest.cc
index e937c1c2593..02f4765a07c 100644
--- a/chromium/content/renderer/loader/resource_dispatcher_unittest.cc
+++ b/chromium/content/renderer/loader/resource_dispatcher_unittest.cc
@@ -34,7 +34,6 @@
#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/public/mojom/request_context_frame_type.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
@@ -121,7 +120,6 @@ class ResourceDispatcherTest : public testing::Test,
request->resource_type = static_cast<int>(ResourceType::kSubResource);
request->priority = net::LOW;
request->fetch_request_mode = network::mojom::FetchRequestMode::kNoCors;
- request->fetch_frame_type = network::mojom::RequestContextFrameType::kNone;
const RequestExtraData extra_data;
extra_data.CopyToResourceRequest(request.get());
diff --git a/chromium/content/renderer/loader/url_loader_client_impl.cc b/chromium/content/renderer/loader/url_loader_client_impl.cc
index 6d68c3788a3..9efa4a31579 100644
--- a/chromium/content/renderer/loader/url_loader_client_impl.cc
+++ b/chromium/content/renderer/loader/url_loader_client_impl.cc
@@ -23,7 +23,8 @@ namespace {
// Determines whether it is safe to redirect from |from_url| to |to_url|.
bool IsRedirectSafe(const GURL& from_url, const GURL& to_url) {
return IsSafeRedirectTarget(from_url, to_url) &&
- GetContentClient()->renderer()->IsSafeRedirectTarget(to_url);
+ (!GetContentClient()->renderer() || // null in unit tests.
+ GetContentClient()->renderer()->IsSafeRedirectTarget(to_url));
}
} // namespace
@@ -98,8 +99,8 @@ class URLLoaderClientImpl::DeferredOnUploadProgress final
class URLLoaderClientImpl::DeferredOnReceiveCachedMetadata final
: public DeferredMessage {
public:
- explicit DeferredOnReceiveCachedMetadata(const std::vector<uint8_t>& data)
- : data_(data) {}
+ explicit DeferredOnReceiveCachedMetadata(mojo_base::BigBuffer data)
+ : data_(std::move(data)) {}
void HandleMessage(ResourceDispatcher* dispatcher, int request_id) override {
dispatcher->OnReceivedCachedMetadata(request_id, data_);
@@ -107,7 +108,7 @@ class URLLoaderClientImpl::DeferredOnReceiveCachedMetadata final
bool IsCompletionMessage() const override { return false; }
private:
- const std::vector<uint8_t> data_;
+ mojo_base::BigBuffer data_;
};
class URLLoaderClientImpl::DeferredOnStartLoadingResponseBody final
@@ -281,10 +282,10 @@ void URLLoaderClientImpl::OnUploadProgress(
std::move(ack_callback).Run();
}
-void URLLoaderClientImpl::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {
+void URLLoaderClientImpl::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
if (NeedsStoringMessage()) {
- StoreAndDispatch(std::make_unique<DeferredOnReceiveCachedMetadata>(data));
+ StoreAndDispatch(
+ std::make_unique<DeferredOnReceiveCachedMetadata>(std::move(data)));
} else {
resource_dispatcher_->OnReceivedCachedMetadata(request_id_, data);
}
@@ -301,6 +302,9 @@ void URLLoaderClientImpl::OnTransferSizeUpdated(int32_t transfer_size_diff) {
void URLLoaderClientImpl::OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) {
+ TRACE_EVENT1("loading", "URLLoaderClientImpl::OnStartLoadingResponseBody",
+ "url", last_loaded_url_.possibly_invalid_spec());
+
DCHECK(has_received_response_head_);
DCHECK(!has_received_response_body_);
has_received_response_body_ = true;
diff --git a/chromium/content/renderer/loader/url_loader_client_impl.h b/chromium/content/renderer/loader/url_loader_client_impl.h
index c7bc4a1b7a9..4cab2f86fbf 100644
--- a/chromium/content/renderer/loader/url_loader_client_impl.h
+++ b/chromium/content/renderer/loader/url_loader_client_impl.h
@@ -77,7 +77,7 @@ class CONTENT_EXPORT URLLoaderClientImpl final
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
diff --git a/chromium/content/renderer/loader/web_data_consumer_handle_impl.cc b/chromium/content/renderer/loader/web_data_consumer_handle_impl.cc
deleted file mode 100644
index c05041f207c..00000000000
--- a/chromium/content/renderer/loader/web_data_consumer_handle_impl.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/loader/web_data_consumer_handle_impl.h"
-
-#include <stdint.h>
-
-#include <limits>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/single_thread_task_runner.h"
-#include "mojo/public/c/system/types.h"
-
-namespace content {
-
-using Result = blink::WebDataConsumerHandle::Result;
-
-class WebDataConsumerHandleImpl::Context
- : public base::RefCountedThreadSafe<Context> {
- public:
- explicit Context(Handle handle) : handle_(std::move(handle)) {}
-
- const Handle& handle() { return handle_; }
-
- private:
- friend class base::RefCountedThreadSafe<Context>;
- ~Context() {}
- Handle handle_;
-
- DISALLOW_COPY_AND_ASSIGN(Context);
-};
-
-WebDataConsumerHandleImpl::ReaderImpl::ReaderImpl(
- scoped_refptr<Context> context,
- Client* client,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : context_(context),
- handle_watcher_(FROM_HERE,
- mojo::SimpleWatcher::ArmingPolicy::MANUAL,
- std::move(task_runner)),
- client_(client) {
- if (client_)
- StartWatching();
-}
-
-WebDataConsumerHandleImpl::ReaderImpl::~ReaderImpl() {
-}
-
-Result WebDataConsumerHandleImpl::ReaderImpl::Read(void* data,
- size_t size,
- Flags flags,
- size_t* read_size) {
- // We need this variable definition to avoid a link error.
- const Flags kNone = kFlagNone;
- DCHECK_EQ(flags, kNone);
- DCHECK_LE(size, std::numeric_limits<uint32_t>::max());
-
- *read_size = 0;
-
- if (!size) {
- // Even if there is unread data available, ReadData() returns
- // FAILED_PRECONDITION when |size| is 0 and the producer handle was closed.
- // But in this case, WebDataConsumerHandle::Reader::read() must return Ok.
- // So we query the signals state directly.
- mojo::HandleSignalsState state = context_->handle()->QuerySignalsState();
- if (state.readable())
- return kOk;
- if (state.never_readable())
- return kDone;
- return kShouldWait;
- }
-
- uint32_t size_to_pass = size;
- MojoReadDataFlags flags_to_pass = MOJO_READ_DATA_FLAG_NONE;
- MojoResult rv =
- context_->handle()->ReadData(data, &size_to_pass, flags_to_pass);
- if (rv == MOJO_RESULT_OK)
- *read_size = size_to_pass;
- if (rv == MOJO_RESULT_SHOULD_WAIT)
- handle_watcher_.ArmOrNotify();
-
- return HandleReadResult(rv);
-}
-
-Result WebDataConsumerHandleImpl::ReaderImpl::BeginRead(const void** buffer,
- Flags flags,
- size_t* available) {
- // We need this variable definition to avoid a link error.
- const Flags kNone = kFlagNone;
- DCHECK_EQ(flags, kNone);
-
- *buffer = nullptr;
- *available = 0;
-
- uint32_t size_to_pass = 0;
- MojoReadDataFlags flags_to_pass = MOJO_READ_DATA_FLAG_NONE;
-
- MojoResult rv =
- context_->handle()->BeginReadData(buffer, &size_to_pass, flags_to_pass);
- if (rv == MOJO_RESULT_OK)
- *available = size_to_pass;
- if (rv == MOJO_RESULT_SHOULD_WAIT)
- handle_watcher_.ArmOrNotify();
- return HandleReadResult(rv);
-}
-
-Result WebDataConsumerHandleImpl::ReaderImpl::EndRead(size_t read_size) {
- MojoResult rv = context_->handle()->EndReadData(read_size);
- return rv == MOJO_RESULT_OK ? kOk : kUnexpectedError;
-}
-
-Result WebDataConsumerHandleImpl::ReaderImpl::HandleReadResult(
- MojoResult mojo_result) {
- switch (mojo_result) {
- case MOJO_RESULT_OK:
- return kOk;
- case MOJO_RESULT_FAILED_PRECONDITION:
- return kDone;
- case MOJO_RESULT_BUSY:
- return kBusy;
- case MOJO_RESULT_SHOULD_WAIT:
- return kShouldWait;
- case MOJO_RESULT_RESOURCE_EXHAUSTED:
- return kResourceExhausted;
- default:
- return kUnexpectedError;
- }
-}
-
-void WebDataConsumerHandleImpl::ReaderImpl::StartWatching() {
- handle_watcher_.Watch(
- context_->handle().get(), MOJO_HANDLE_SIGNAL_READABLE,
- base::Bind(&ReaderImpl::OnHandleGotReadable, base::Unretained(this)));
- handle_watcher_.ArmOrNotify();
-}
-
-void WebDataConsumerHandleImpl::ReaderImpl::OnHandleGotReadable(MojoResult) {
- DCHECK(client_);
- client_->DidGetReadable();
-}
-
-WebDataConsumerHandleImpl::WebDataConsumerHandleImpl(Handle handle)
- : context_(new Context(std::move(handle))) {}
-
-WebDataConsumerHandleImpl::~WebDataConsumerHandleImpl() {
-}
-
-std::unique_ptr<blink::WebDataConsumerHandle::Reader>
-WebDataConsumerHandleImpl::ObtainReader(
- Client* client,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- return base::WrapUnique(
- new ReaderImpl(context_, client, std::move(task_runner)));
-}
-
-const char* WebDataConsumerHandleImpl::DebugName() const {
- return "WebDataConsumerHandleImpl";
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/loader/web_data_consumer_handle_impl.h b/chromium/content/renderer/loader/web_data_consumer_handle_impl.h
deleted file mode 100644
index f79cb797b8e..00000000000
--- a/chromium/content/renderer/loader/web_data_consumer_handle_impl.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_LOADER_WEB_DATA_CONSUMER_HANDLE_IMPL_H_
-#define CONTENT_RENDERER_LOADER_WEB_DATA_CONSUMER_HANDLE_IMPL_H_
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/single_thread_task_runner.h"
-#include "content/common/content_export.h"
-#include "mojo/public/cpp/system/data_pipe.h"
-#include "mojo/public/cpp/system/simple_watcher.h"
-#include "third_party/blink/public/platform/web_data_consumer_handle.h"
-
-namespace content {
-
-class CONTENT_EXPORT WebDataConsumerHandleImpl final
- : public blink::WebDataConsumerHandle {
- typedef mojo::ScopedDataPipeConsumerHandle Handle;
- class Context;
-
- public:
- class CONTENT_EXPORT ReaderImpl final : public Reader {
- public:
- ReaderImpl(scoped_refptr<Context> context,
- Client* client,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- ~ReaderImpl() override;
- Result Read(void* data,
- size_t size,
- Flags flags,
- size_t* readSize) override;
- Result BeginRead(const void** buffer,
- Flags flags,
- size_t* available) override;
- Result EndRead(size_t readSize) override;
-
- private:
- Result HandleReadResult(MojoResult);
- void StartWatching();
- void OnHandleGotReadable(MojoResult);
-
- scoped_refptr<Context> context_;
- mojo::SimpleWatcher handle_watcher_;
- Client* client_;
-
- DISALLOW_COPY_AND_ASSIGN(ReaderImpl);
- };
- std::unique_ptr<Reader> ObtainReader(
- Client* client,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
-
- explicit WebDataConsumerHandleImpl(Handle handle);
- ~WebDataConsumerHandleImpl() override;
-
- private:
- const char* DebugName() const override;
-
- scoped_refptr<Context> context_;
-
- DISALLOW_COPY_AND_ASSIGN(WebDataConsumerHandleImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_LOADER_WEB_DATA_CONSUMER_HANDLE_IMPL_H_
diff --git a/chromium/content/renderer/loader/web_data_consumer_handle_impl_unittest.cc b/chromium/content/renderer/loader/web_data_consumer_handle_impl_unittest.cc
deleted file mode 100644
index 980fe64b63c..00000000000
--- a/chromium/content/renderer/loader/web_data_consumer_handle_impl_unittest.cc
+++ /dev/null
@@ -1,423 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/loader/web_data_consumer_handle_impl.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "mojo/public/cpp/system/data_pipe.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-
-namespace content {
-
-namespace {
-
-using blink::WebDataConsumerHandle;
-
-class ReadDataOperationBase {
- public:
- virtual ~ReadDataOperationBase() {}
- virtual void ReadMore() = 0;
-
- static const WebDataConsumerHandle::Flags kNone =
- WebDataConsumerHandle::kFlagNone;
- static const WebDataConsumerHandle::Result kOk = WebDataConsumerHandle::kOk;
- static const WebDataConsumerHandle::Result kDone =
- WebDataConsumerHandle::kDone;
- static const WebDataConsumerHandle::Result kShouldWait =
- WebDataConsumerHandle::kShouldWait;
-};
-
-class ClientImpl final : public WebDataConsumerHandle::Client {
- public:
- explicit ClientImpl(ReadDataOperationBase* operation)
- : operation_(operation) {}
-
- void DidGetReadable() override {
- blink::scheduler::GetSingleThreadTaskRunnerForTesting()->PostTask(
- FROM_HERE, base::BindOnce(&ReadDataOperationBase::ReadMore,
- base::Unretained(operation_)));
- }
-
- private:
- ReadDataOperationBase* operation_;
-};
-
-class ReadDataOperation : public ReadDataOperationBase {
- public:
- typedef WebDataConsumerHandle::Result Result;
- ReadDataOperation(
- mojo::ScopedDataPipeConsumerHandle handle,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
- const base::Closure& on_done)
- : handle_(new WebDataConsumerHandleImpl(std::move(handle))),
- main_thread_task_runner_(std::move(main_thread_task_runner)),
- on_done_(on_done) {}
-
- const std::string& result() const { return result_; }
-
- void ReadMore() override {
- // We may have drained the pipe while this task was waiting to run.
- if (reader_)
- ReadData();
- }
-
- void ReadData() {
- if (!client_) {
- client_.reset(new ClientImpl(this));
- reader_ = handle_->ObtainReader(
- client_.get(),
- blink::scheduler::GetSingleThreadTaskRunnerForTesting());
- }
-
- Result rv = kOk;
- size_t readSize = 0;
- while (true) {
- char buffer[16];
- rv = reader_->Read(&buffer, sizeof(buffer), kNone, &readSize);
- if (rv != kOk)
- break;
- result_.insert(result_.size(), &buffer[0], readSize);
- }
-
- if (rv == kShouldWait) {
- // Wait a while...
- return;
- }
-
- if (rv != kDone) {
- // Something is wrong.
- result_ = "error";
- }
-
- // The operation is done.
- reader_.reset();
- main_thread_task_runner_->PostTask(FROM_HERE, on_done_);
- }
-
- private:
- std::unique_ptr<WebDataConsumerHandleImpl> handle_;
- std::unique_ptr<WebDataConsumerHandle::Reader> reader_;
- std::unique_ptr<WebDataConsumerHandle::Client> client_;
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
- base::Closure on_done_;
- std::string result_;
-};
-
-class TwoPhaseReadDataOperation : public ReadDataOperationBase {
- public:
- typedef WebDataConsumerHandle::Result Result;
- TwoPhaseReadDataOperation(
- mojo::ScopedDataPipeConsumerHandle handle,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
- const base::Closure& on_done)
- : handle_(new WebDataConsumerHandleImpl(std::move(handle))),
- main_thread_task_runner_(std::move(main_thread_task_runner)),
- on_done_(on_done) {}
-
- const std::string& result() const { return result_; }
-
- void ReadMore() override {
- // We may have drained the pipe while this task was waiting to run.
- if (reader_)
- ReadData();
- }
-
- void ReadData() {
- if (!client_) {
- client_.reset(new ClientImpl(this));
- reader_ = handle_->ObtainReader(
- client_.get(),
- blink::scheduler::GetSingleThreadTaskRunnerForTesting());
- }
-
- Result rv;
- while (true) {
- const void* buffer = nullptr;
- size_t size;
- rv = reader_->BeginRead(&buffer, kNone, &size);
- if (rv != kOk)
- break;
- // In order to verify endRead, we read at most one byte for each time.
- size_t read_size = std::max(static_cast<size_t>(1), size);
- result_.insert(result_.size(), static_cast<const char*>(buffer),
- read_size);
- rv = reader_->EndRead(read_size);
- if (rv != kOk) {
- // Something is wrong.
- result_ = "error";
- main_thread_task_runner_->PostTask(FROM_HERE, on_done_);
- return;
- }
- }
-
- if (rv == kShouldWait) {
- // Wait a while...
- return;
- }
-
- if (rv != kDone) {
- // Something is wrong.
- result_ = "error";
- }
-
- // The operation is done.
- reader_.reset();
- main_thread_task_runner_->PostTask(FROM_HERE, on_done_);
- }
-
- private:
- std::unique_ptr<WebDataConsumerHandleImpl> handle_;
- std::unique_ptr<WebDataConsumerHandle::Reader> reader_;
- std::unique_ptr<WebDataConsumerHandle::Client> client_;
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
- base::Closure on_done_;
- std::string result_;
-};
-
-class WebDataConsumerHandleImplTest : public ::testing::Test {
- public:
- typedef WebDataConsumerHandle::Result Result;
-
- void SetUp() override {
- MojoCreateDataPipeOptions options;
- options.struct_size = sizeof(MojoCreateDataPipeOptions);
- options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
- options.element_num_bytes = 1;
- options.capacity_num_bytes = kDataPipeCapacity;
-
- MojoResult result = mojo::CreateDataPipe(&options, &producer_, &consumer_);
- ASSERT_EQ(MOJO_RESULT_OK, result);
- }
-
- protected:
- static constexpr int kDataPipeCapacity = 4;
-
- // This function can be blocked if the associated consumer doesn't consume
- // the data.
- std::string ProduceData(size_t total_size) {
- int index = 0;
- std::string expected;
- for (size_t i = 0; i < total_size; ++i) {
- expected += static_cast<char>(index + 'a');
- index = (37 * index + 11) % 26;
- }
-
- const char* p = expected.data();
- size_t remaining = total_size;
- const MojoWriteDataFlags kNone = MOJO_WRITE_DATA_FLAG_NONE;
- MojoResult rv;
- while (remaining > 0) {
- uint32_t size = remaining;
- rv = producer_->WriteData(p, &size, kNone);
- if (rv == MOJO_RESULT_OK) {
- remaining -= size;
- p += size;
- } else if (rv != MOJO_RESULT_SHOULD_WAIT) {
- // Something is wrong.
- EXPECT_TRUE(false) << "WriteData() returns an invalid value.";
- return "error on writing";
- }
- }
- return expected;
- }
-
- base::test::ScopedTaskEnvironment task_environment_;
-
- mojo::ScopedDataPipeProducerHandle producer_;
- mojo::ScopedDataPipeConsumerHandle consumer_;
-};
-
-TEST_F(WebDataConsumerHandleImplTest, ReadData) {
- base::RunLoop run_loop;
- auto operation = std::make_unique<ReadDataOperation>(
- std::move(consumer_),
- blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
- run_loop.QuitClosure());
-
- base::Thread t("DataConsumerHandle test thread");
- ASSERT_TRUE(t.Start());
-
- t.task_runner()->PostTask(FROM_HERE,
- base::BindOnce(&ReadDataOperation::ReadData,
- base::Unretained(operation.get())));
-
- std::string expected = ProduceData(24 * 1024);
- producer_.reset();
-
- run_loop.Run();
- t.Stop();
-
- EXPECT_EQ(expected, operation->result());
-}
-
-TEST_F(WebDataConsumerHandleImplTest, TwoPhaseReadData) {
- base::RunLoop run_loop;
- auto operation = std::make_unique<TwoPhaseReadDataOperation>(
- std::move(consumer_),
- blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
- run_loop.QuitClosure());
-
- base::Thread t("DataConsumerHandle test thread");
- ASSERT_TRUE(t.Start());
-
- t.task_runner()->PostTask(FROM_HERE,
- base::BindOnce(&TwoPhaseReadDataOperation::ReadData,
- base::Unretained(operation.get())));
-
- std::string expected = ProduceData(24 * 1024);
- producer_.reset();
-
- run_loop.Run();
- t.Stop();
-
- EXPECT_EQ(expected, operation->result());
-}
-
-TEST_F(WebDataConsumerHandleImplTest, ZeroSizeRead) {
- ASSERT_GT(kDataPipeCapacity - 1, 0);
- constexpr size_t data_size = kDataPipeCapacity - 1;
- std::unique_ptr<WebDataConsumerHandleImpl> handle(
- new WebDataConsumerHandleImpl(std::move(consumer_)));
- std::unique_ptr<WebDataConsumerHandle::Reader> reader(handle->ObtainReader(
- nullptr, blink::scheduler::GetSingleThreadTaskRunnerForTesting()));
-
- size_t read_size;
- WebDataConsumerHandle::Result rv =
- reader->Read(nullptr, 0, WebDataConsumerHandle::kFlagNone, &read_size);
- EXPECT_EQ(WebDataConsumerHandle::Result::kShouldWait, rv);
-
- std::string expected = ProduceData(data_size);
- producer_.reset();
-
- rv = reader->Read(nullptr, 0, WebDataConsumerHandle::kFlagNone, &read_size);
- EXPECT_EQ(WebDataConsumerHandle::Result::kOk, rv);
-
- char buffer[16];
- rv = reader->Read(&buffer, sizeof(buffer), WebDataConsumerHandle::kFlagNone,
- &read_size);
- EXPECT_EQ(WebDataConsumerHandle::Result::kOk, rv);
- EXPECT_EQ(data_size, read_size);
- EXPECT_EQ(expected, std::string(buffer, read_size));
-
- rv = reader->Read(nullptr, 0, WebDataConsumerHandle::kFlagNone, &read_size);
- EXPECT_EQ(WebDataConsumerHandle::Result::kDone, rv);
-}
-
-class CountDidGetReadableClient : public blink::WebDataConsumerHandle::Client {
- public:
- ~CountDidGetReadableClient() override {}
- void DidGetReadable() override { num_did_get_readable_called_++; }
- int num_did_get_readable_called() { return num_did_get_readable_called_; }
-
- private:
- int num_did_get_readable_called_ = 0;
-};
-
-TEST_F(WebDataConsumerHandleImplTest, DidGetReadable) {
- static constexpr size_t kBlockSize = kDataPipeCapacity / 3;
- static constexpr size_t kTotalSize = kBlockSize * 2;
-
- std::unique_ptr<CountDidGetReadableClient> client =
- std::make_unique<CountDidGetReadableClient>();
- std::unique_ptr<WebDataConsumerHandleImpl> handle(
- new WebDataConsumerHandleImpl(std::move(consumer_)));
- std::unique_ptr<WebDataConsumerHandle::Reader> reader(handle->ObtainReader(
- client.get(), blink::scheduler::GetSingleThreadTaskRunnerForTesting()));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0, client->num_did_get_readable_called());
-
- // Push two blocks.
- {
- std::string expected;
- int index = 0;
- for (size_t i = 0; i < kTotalSize; ++i) {
- expected += static_cast<char>(index + 'a');
- index = (37 * index + 11) % 26;
- }
- uint32_t size = expected.size();
- MojoResult rv =
- producer_->WriteData(expected.data(), &size, MOJO_WRITE_DATA_FLAG_NONE);
- EXPECT_EQ(MOJO_RESULT_OK, rv);
- EXPECT_EQ(kTotalSize, size);
- }
- base::RunLoop().RunUntilIdle();
- // |client| is notified the pipe gets ready.
- EXPECT_EQ(1, client->num_did_get_readable_called());
-
- // Read a block.
- {
- char buffer[kBlockSize];
- size_t size = 0;
- Result rv = reader->Read(&buffer, sizeof(buffer),
- WebDataConsumerHandle::kFlagNone, &size);
- EXPECT_EQ(Result::kOk, rv);
- EXPECT_EQ(sizeof(buffer), size);
- }
- base::RunLoop().RunUntilIdle();
- // |client| is NOT notified since the data is still available.
- EXPECT_EQ(1, client->num_did_get_readable_called());
-
- // Read the other block.
- {
- const void* buffer = nullptr;
- size_t size = sizeof(buffer);
- Result rv =
- reader->BeginRead(&buffer, WebDataConsumerHandle::kFlagNone, &size);
- EXPECT_EQ(Result::kOk, rv);
- EXPECT_TRUE(buffer);
- EXPECT_EQ(kTotalSize - kBlockSize, size);
- base::RunLoop().RunUntilIdle();
-
- rv = reader->EndRead(kBlockSize);
- EXPECT_EQ(Result::kOk, rv);
- }
- base::RunLoop().RunUntilIdle();
- // |client| is NOT notified the pipe is still waiting for more data.
- EXPECT_EQ(1, client->num_did_get_readable_called());
-
- // Read one more.
- {
- char buffer[kBlockSize];
- size_t size = 0;
- Result rv = reader->Read(&buffer, sizeof(buffer),
- WebDataConsumerHandle::kFlagNone, &size);
- EXPECT_EQ(Result::kShouldWait, rv);
- }
- base::RunLoop().RunUntilIdle();
- // |client| is NOT notified because the pipe is still waiting for more data.
- EXPECT_EQ(1, client->num_did_get_readable_called());
-
- // Push one more block.
- {
- std::string expected(kBlockSize, 'x');
- uint32_t size = expected.size();
- MojoResult rv =
- producer_->WriteData(expected.data(), &size, MOJO_WRITE_DATA_FLAG_NONE);
- EXPECT_EQ(MOJO_RESULT_OK, rv);
- EXPECT_EQ(expected.size(), size);
- }
- base::RunLoop().RunUntilIdle();
- // |client| is notified the pipe gets ready.
- EXPECT_EQ(2, client->num_did_get_readable_called());
-}
-
-} // namespace
-
-} // namespace content
diff --git a/chromium/content/renderer/loader/web_url_loader_impl.cc b/chromium/content/renderer/loader/web_url_loader_impl.cc
index d0751735e20..3bf1111118f 100644
--- a/chromium/content/renderer/loader/web_url_loader_impl.cc
+++ b/chromium/content/renderer/loader/web_url_loader_impl.cc
@@ -46,6 +46,7 @@
#include "net/base/ip_endpoint.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/ct_sct_to_string.h"
#include "net/cert/x509_certificate.h"
@@ -57,7 +58,6 @@
#include "net/url_request/url_request_data_job.h"
#include "services/network/loader_util.h"
#include "services/network/public/cpp/resource_request.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
@@ -317,6 +317,50 @@ void SetSecurityStyleAndDetails(const GURL& url,
response->SetSecurityDetails(webSecurityDetails);
}
+// Relationship of resource being authenticated with the top level page.
+enum HttpAuthRelationType {
+ HTTP_AUTH_RELATION_TOP, // Top-level page itself
+ HTTP_AUTH_RELATION_SAME_DOMAIN, // Sub-content from same domain
+ HTTP_AUTH_RELATION_BLOCKED_CROSS, // Blocked Sub-content from cross domain
+ HTTP_AUTH_RELATION_ALLOWED_CROSS, // Allowed Sub-content per command line
+ HTTP_AUTH_RELATION_LAST
+};
+
+HttpAuthRelationType HttpAuthRelationTypeOf(
+ network::ResourceRequest* resource_request,
+ const WebURLRequest& request) {
+ auto& request_url = resource_request->url;
+ auto& first_party = resource_request->site_for_cookies;
+
+ if (!first_party.is_valid())
+ return HTTP_AUTH_RELATION_TOP;
+
+ bool allow_cross_origin_auth_prompt = false;
+ if (request.GetExtraData()) {
+ RequestExtraData* extra_data =
+ static_cast<RequestExtraData*>(request.GetExtraData());
+ allow_cross_origin_auth_prompt =
+ extra_data->allow_cross_origin_auth_prompt();
+ }
+
+ if (net::registry_controlled_domains::SameDomainOrHost(
+ first_party, request_url,
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
+ // If the first party is secure but the subresource is not, this is
+ // mixed-content. Do not allow the image.
+ if (!allow_cross_origin_auth_prompt && IsOriginSecure(first_party) &&
+ !IsOriginSecure(request_url)) {
+ return HTTP_AUTH_RELATION_BLOCKED_CROSS;
+ }
+ return HTTP_AUTH_RELATION_SAME_DOMAIN;
+ }
+
+ if (allow_cross_origin_auth_prompt)
+ return HTTP_AUTH_RELATION_ALLOWED_CROSS;
+
+ return HTTP_AUTH_RELATION_BLOCKED_CROSS;
+}
+
} // namespace
WebURLLoaderFactoryImpl::WebURLLoaderFactoryImpl(
@@ -641,6 +685,8 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
resource_request->top_frame_origin = request.TopFrameOrigin();
resource_request->upgrade_if_insecure = request.UpgradeIfInsecure();
resource_request->is_revalidating = request.IsRevalidating();
+ resource_request->should_also_use_factory_bound_origin_for_cors =
+ request.ShouldAlsoUseFactoryBoundOriginForCors();
if (!request.RequestorOrigin().IsNull()) {
if (request.RequestorOrigin().ToString() == "null") {
// "file:" origin is treated like an opaque unique origin when
@@ -691,6 +737,8 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
WebString(request.GetPurposeHeader()).Utf8());
}
+ resource_request->load_flags = request.GetLoadFlagsForWebUrlRequest();
+
if (resource_request->resource_type ==
static_cast<int>(ResourceType::kPrefetch) ||
resource_request->resource_type ==
@@ -698,7 +746,28 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
resource_request->do_not_prompt_for_login = true;
}
- resource_request->load_flags = request.GetLoadFlagsForWebUrlRequest();
+ if (request.GetRequestContext() ==
+ blink::mojom::RequestContextType::XML_HTTP_REQUEST &&
+ (resource_request->url.has_username() ||
+ resource_request->url.has_password())) {
+ resource_request->do_not_prompt_for_login = true;
+ }
+
+ if (resource_request->resource_type ==
+ static_cast<int>(ResourceType::kImage) &&
+ HTTP_AUTH_RELATION_BLOCKED_CROSS ==
+ HttpAuthRelationTypeOf(resource_request.get(), request)) {
+ // Prevent third-party image content from prompting for login, as this
+ // is often a scam to extract credentials for another domain from the
+ // user. Only block image loads, as the attack applies largely to the
+ // "src" property of the <img> tag. It is common for web properties to
+ // allow untrusted values for <img src>; this is considered a fair thing
+ // for an HTML sanitizer to do. Conversely, any HTML sanitizer that didn't
+ // filter sources for <script>, <link>, <embed>, <object>, <iframe> tags
+ // would be considered vulnerable in and of itself.
+ resource_request->do_not_prompt_for_login = true;
+ resource_request->load_flags |= net::LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
+ }
// |plugin_child_id| only needs to be non-zero if the request originates
// outside the render process, so we can use requestorProcessID even
@@ -706,7 +775,10 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
resource_request->plugin_child_id = request.GetPluginChildID();
resource_request->priority =
ConvertWebKitPriorityToNetPriority(request.GetPriority());
- resource_request->appcache_host_id = request.AppCacheHostID();
+ resource_request->appcache_host_id =
+ request.AppCacheHostID().is_empty()
+ ? base::nullopt
+ : base::make_optional(request.AppCacheHostID());
resource_request->should_reset_appcache = request.ShouldResetAppCache();
resource_request->is_external_request = request.IsExternalRequest();
resource_request->cors_preflight_policy = request.GetCorsPreflightPolicy();
@@ -719,20 +791,12 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
resource_request->fetch_request_context_type =
static_cast<int>(GetRequestContextTypeForWebURLRequest(request));
- resource_request->fetch_frame_type =
- network::mojom::RequestContextFrameType::kNone;
resource_request->request_body =
GetRequestBodyForWebURLRequest(request).get();
resource_request->keepalive = request.GetKeepalive();
resource_request->has_user_gesture = request.HasUserGesture();
resource_request->enable_load_timing = true;
resource_request->enable_upload_progress = request.ReportUploadProgress();
- GURL gurl(url_);
- if (request.GetRequestContext() ==
- blink::mojom::RequestContextType::XML_HTTP_REQUEST &&
- (gurl.has_username() || gurl.has_password())) {
- resource_request->do_not_prompt_for_login = true;
- }
resource_request->report_raw_headers = request.ReportRawHeaders();
// TODO(ryansturm): Remove resource_request->previews_state once it is no
// longer used in a network delegate. https://crbug.com/842233
@@ -773,6 +837,16 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
std::make_unique<WebURLLoaderImpl::RequestPeerImpl>(this, discard_body);
}
+ if (resource_request->resource_type ==
+ static_cast<int>(ResourceType::kPrefetch)) {
+ resource_request->corb_detachable = true;
+ }
+
+ if (resource_request->resource_type ==
+ static_cast<int>(ResourceType::kPluginResource)) {
+ resource_request->corb_excluded = true;
+ }
+
auto throttles = extra_data->TakeURLLoaderThrottles();
// The frame request blocker is only for a frame's subresources.
if (extra_data->frame_request_blocker() &&
@@ -880,9 +954,9 @@ void WebURLLoaderImpl::Context::OnReceivedCachedMetadata(
const char* data, int len) {
if (!client_)
return;
- TRACE_EVENT_WITH_FLOW0(
- "loading", "WebURLLoaderImpl::Context::OnReceivedCachedMetadata",
- this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+ TRACE_EVENT_WITH_FLOW1(
+ "loading", "WebURLLoaderImpl::Context::OnReceivedCachedMetadata", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "length", len);
client_->DidReceiveCachedMetadata(data, len);
}
@@ -1051,6 +1125,7 @@ void WebURLLoaderImpl::PopulateURLResponse(
response->SetRequestId(request_id);
response->SetIsSignedExchangeInnerResponse(
info.is_signed_exchange_inner_response);
+ response->SetWasInPrefetchCache(info.was_in_prefetch_cache);
SetSecurityStyleAndDetails(url, info, response, report_security_info);
diff --git a/chromium/content/renderer/loader/web_url_loader_impl.h b/chromium/content/renderer/loader/web_url_loader_impl.h
index ad2cda7aca1..9ce1066841f 100644
--- a/chromium/content/renderer/loader/web_url_loader_impl.h
+++ b/chromium/content/renderer/loader/web_url_loader_impl.h
@@ -86,7 +86,6 @@ class CONTENT_EXPORT WebURLLoaderImpl : public blink::WebURLLoader {
blink::WebBlobInfo& downloaded_blob) override;
void LoadAsynchronously(const blink::WebURLRequest& request,
blink::WebURLLoaderClient* client) override;
- void Cancel() override;
void SetDefersLoading(bool value) override;
void DidChangePriority(blink::WebURLRequest::Priority new_priority,
int intra_priority_value) override;
@@ -96,6 +95,9 @@ class CONTENT_EXPORT WebURLLoaderImpl : public blink::WebURLLoader {
class Context;
class RequestPeerImpl;
class SinkPeer;
+
+ void Cancel();
+
scoped_refptr<Context> context_;
DISALLOW_COPY_AND_ASSIGN(WebURLLoaderImpl);
diff --git a/chromium/content/renderer/loader/web_url_loader_impl_unittest.cc b/chromium/content/renderer/loader/web_url_loader_impl_unittest.cc
index 2e395a8a6c9..cb6590b4a4b 100644
--- a/chromium/content/renderer/loader/web_url_loader_impl_unittest.cc
+++ b/chromium/content/renderer/loader/web_url_loader_impl_unittest.cc
@@ -37,7 +37,6 @@
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/resource_response_info.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_data.h"
diff --git a/chromium/content/renderer/loader/web_url_request_util.cc b/chromium/content/renderer/loader/web_url_request_util.cc
index 084a641fa0a..0f7d31df55d 100644
--- a/chromium/content/renderer/loader/web_url_request_util.cc
+++ b/chromium/content/renderer/loader/web_url_request_util.cc
@@ -21,7 +21,6 @@
#include "net/http/http_util.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/data_pipe_getter.mojom.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"
diff --git a/chromium/content/renderer/loader/web_url_request_util.h b/chromium/content/renderer/loader/web_url_request_util.h
index e00bd898e5e..57ede1af0dd 100644
--- a/chromium/content/renderer/loader/web_url_request_util.h
+++ b/chromium/content/renderer/loader/web_url_request_util.h
@@ -11,7 +11,6 @@
#include "content/public/common/resource_type.h"
#include "net/http/http_request_headers.h"
#include "services/network/public/cpp/resource_request_body.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
diff --git a/chromium/content/renderer/loader/web_worker_fetch_context_impl.cc b/chromium/content/renderer/loader/web_worker_fetch_context_impl.cc
index ed54d9dded7..5395cc49c44 100644
--- a/chromium/content/renderer/loader/web_worker_fetch_context_impl.cc
+++ b/chromium/content/renderer/loader/web_worker_fetch_context_impl.cc
@@ -497,7 +497,8 @@ void WebWorkerFetchContextImpl::SetResponseOverrideForMainScript(
response_override_ = std::move(response_override);
}
-void WebWorkerFetchContextImpl::SetApplicationCacheHostID(int id) {
+void WebWorkerFetchContextImpl::SetApplicationCacheHostID(
+ const base::UnguessableToken& id) {
appcache_host_id_ = id;
}
diff --git a/chromium/content/renderer/loader/web_worker_fetch_context_impl.h b/chromium/content/renderer/loader/web_worker_fetch_context_impl.h
index ee7efa1e7a7..3fe0c838d83 100644
--- a/chromium/content/renderer/loader/web_worker_fetch_context_impl.h
+++ b/chromium/content/renderer/loader/web_worker_fetch_context_impl.h
@@ -24,7 +24,6 @@
#include "third_party/blink/public/mojom/service_worker/service_worker_container.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.mojom.h"
-#include "third_party/blink/public/platform/web_application_cache_host.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "url/gurl.h"
@@ -98,7 +97,7 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl
void DidDisplayContentWithCertificateErrors() override;
void DidRunInsecureContent(const blink::WebSecurityOrigin&,
const blink::WebURL& insecure_url) override;
- void SetApplicationCacheHostID(int id) override;
+ void SetApplicationCacheHostID(const base::UnguessableToken& id) override;
void SetSubresourceFilterBuilder(
std::unique_ptr<blink::WebDocumentSubresourceFilter::Builder>) override;
std::unique_ptr<blink::WebDocumentSubresourceFilter> TakeSubresourceFilter()
@@ -246,7 +245,7 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl
base::Optional<url::Origin> top_frame_origin_;
bool is_secure_context_ = false;
GURL origin_url_;
- int appcache_host_id_ = blink::mojom::kAppCacheNoHostId;
+ base::UnguessableToken appcache_host_id_;
blink::mojom::RendererPreferences renderer_preferences_;
diff --git a/chromium/content/renderer/manifest/OWNERS b/chromium/content/renderer/manifest/OWNERS
deleted file mode 100644
index e60c0b9edd1..00000000000
--- a/chromium/content/renderer/manifest/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-file://third_party/blink/renderer/modules/manifest/OWNERS
-
-# COMPONENT: Manifest
diff --git a/chromium/content/renderer/manifest/manifest_change_notifier.cc b/chromium/content/renderer/manifest/manifest_change_notifier.cc
deleted file mode 100644
index 8e2a94bb4c7..00000000000
--- a/chromium/content/renderer/manifest/manifest_change_notifier.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/renderer/manifest/manifest_change_notifier.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "content/public/renderer/render_frame.h"
-#include "content/renderer/manifest/manifest_manager.h"
-#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
-#include "third_party/blink/public/web/web_document.h"
-#include "third_party/blink/public/web/web_local_frame.h"
-
-namespace content {
-
-ManifestChangeNotifier::ManifestChangeNotifier(RenderFrame* render_frame)
- : RenderFrameObserver(render_frame), weak_factory_(this) {}
-
-ManifestChangeNotifier::~ManifestChangeNotifier() = default;
-
-void ManifestChangeNotifier::DidChangeManifest() {
- // Manifests are not considered when the current page has a unique origin.
- if (!ManifestManager::CanFetchManifest(render_frame()))
- return;
-
- if (weak_factory_.HasWeakPtrs())
- return;
-
- // Changing the manifest URL can trigger multiple notifications; the manifest
- // URL update may involve removing the old manifest link before adding the new
- // one, triggering multiple calls to DidChangeManifest(). Coalesce changes
- // during a single event loop task to avoid sending spurious notifications to
- // the browser.
- //
- // During document load, coalescing is disabled to maintain relative ordering
- // of this notification and the favicon URL reporting.
- if (!render_frame()->GetWebFrame()->IsLoading()) {
- render_frame()
- ->GetTaskRunner(blink::TaskType::kInternalLoading)
- ->PostTask(FROM_HERE,
- base::BindOnce(&ManifestChangeNotifier::ReportManifestChange,
- weak_factory_.GetWeakPtr()));
- return;
- }
- ReportManifestChange();
-}
-
-void ManifestChangeNotifier::OnDestruct() {
- delete this;
-}
-
-void ManifestChangeNotifier::ReportManifestChange() {
- auto manifest_url =
- render_frame()->GetWebFrame()->GetDocument().ManifestURL();
- if (manifest_url.IsNull()) {
- GetManifestChangeObserver().ManifestUrlChanged(base::nullopt);
- } else {
- GetManifestChangeObserver().ManifestUrlChanged(GURL(manifest_url));
- }
-}
-
-mojom::ManifestUrlChangeObserver&
-ManifestChangeNotifier::GetManifestChangeObserver() {
- if (!manifest_change_observer_) {
- render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
- &manifest_change_observer_);
- }
- return *manifest_change_observer_;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/manifest/manifest_change_notifier.h b/chromium/content/renderer/manifest/manifest_change_notifier.h
deleted file mode 100644
index cfc623818e7..00000000000
--- a/chromium/content/renderer/manifest/manifest_change_notifier.h
+++ /dev/null
@@ -1,37 +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_RENDERER_MANIFEST_MANIFEST_CHANGE_NOTIFIER_H_
-#define CONTENT_RENDERER_MANIFEST_MANIFEST_CHANGE_NOTIFIER_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/manifest_observer.mojom.h"
-#include "content/public/renderer/render_frame_observer.h"
-
-namespace content {
-
-class ManifestChangeNotifier : public RenderFrameObserver {
- public:
- explicit ManifestChangeNotifier(RenderFrame* render_frame);
- ~ManifestChangeNotifier() override;
-
- private:
- // RenderFrameObserver implementation.
- void DidChangeManifest() override;
- void OnDestruct() override;
-
- void ReportManifestChange();
- mojom::ManifestUrlChangeObserver& GetManifestChangeObserver();
-
- mojom::ManifestUrlChangeObserverAssociatedPtr manifest_change_observer_;
-
- base::WeakPtrFactory<ManifestChangeNotifier> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ManifestChangeNotifier);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MANIFEST_MANIFEST_CHANGE_NOTIFIER_H_
diff --git a/chromium/content/renderer/manifest/manifest_manager.cc b/chromium/content/renderer/manifest/manifest_manager.cc
deleted file mode 100644
index 4cefec39e57..00000000000
--- a/chromium/content/renderer/manifest/manifest_manager.cc
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/manifest/manifest_manager.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/no_destructor.h"
-#include "base/strings/nullable_string16.h"
-#include "content/public/renderer/render_frame.h"
-#include "content/renderer/manifest/manifest_uma_util.h"
-#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
-#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
-#include "third_party/blink/public/platform/web_url_response.h"
-#include "third_party/blink/public/web/web_console_message.h"
-#include "third_party/blink/public/web/web_document.h"
-#include "third_party/blink/public/web/web_local_frame.h"
-#include "third_party/blink/public/web/web_manifest_fetcher.h"
-#include "third_party/blink/public/web/web_manifest_parser.h"
-
-namespace content {
-
-// static
-bool ManifestManager::CanFetchManifest(RenderFrame* render_frame) {
- // Do not fetch the manifest if we are on a unique origin.
- return !render_frame->GetWebFrame()
- ->GetDocument()
- .GetSecurityOrigin()
- .IsUnique();
-}
-
-ManifestManager::ManifestManager(RenderFrame* render_frame)
- : RenderFrameObserver(render_frame),
- may_have_manifest_(false),
- manifest_dirty_(true) {}
-
-ManifestManager::~ManifestManager() {
- if (fetcher_)
- fetcher_->Cancel();
-
- // Consumers in the browser process will not receive this message but they
- // will be aware of the RenderFrame dying and should act on that. Consumers
- // in the renderer process should be correctly notified.
- ResolveCallbacks(ResolveStateFailure);
-}
-
-void ManifestManager::RequestManifest(RequestManifestCallback callback) {
- RequestManifestImpl(base::BindOnce(
- [](RequestManifestCallback callback, const GURL& manifest_url,
- const blink::Manifest& manifest,
- const blink::mojom::ManifestDebugInfo* debug_info) {
- std::move(callback).Run(manifest_url, manifest);
- },
- std::move(callback)));
-}
-
-void ManifestManager::RequestManifestDebugInfo(
- RequestManifestDebugInfoCallback callback) {
- RequestManifestImpl(base::BindOnce(
- [](RequestManifestDebugInfoCallback callback, const GURL& manifest_url,
- const blink::Manifest& manifest,
- const blink::mojom::ManifestDebugInfo* debug_info) {
- std::move(callback).Run(manifest_url,
- debug_info ? debug_info->Clone() : nullptr);
- },
- std::move(callback)));
-}
-
-void ManifestManager::RequestManifestImpl(
- InternalRequestManifestCallback callback) {
- if (!may_have_manifest_) {
- std::move(callback).Run(GURL(), blink::Manifest(), nullptr);
- return;
- }
-
- if (!manifest_dirty_) {
- std::move(callback).Run(manifest_url_, manifest_,
- manifest_debug_info_.get());
- return;
- }
-
- pending_callbacks_.push_back(std::move(callback));
-
- // Just wait for the running call to be done if there are other callbacks.
- if (pending_callbacks_.size() > 1)
- return;
-
- FetchManifest();
-}
-
-void ManifestManager::DidChangeManifest() {
- may_have_manifest_ = true;
- manifest_dirty_ = true;
- manifest_url_ = GURL();
- manifest_debug_info_ = nullptr;
-}
-
-void ManifestManager::DidCommitProvisionalLoad(bool is_same_document_navigation,
- ui::PageTransition transition) {
- if (is_same_document_navigation)
- return;
-
- may_have_manifest_ = false;
- manifest_dirty_ = true;
- manifest_url_ = GURL();
-}
-
-void ManifestManager::FetchManifest() {
- if (!CanFetchManifest(render_frame())) {
- ManifestUmaUtil::FetchFailed(ManifestUmaUtil::FETCH_FROM_UNIQUE_ORIGIN);
- ResolveCallbacks(ResolveStateFailure);
- return;
- }
-
- blink::WebDocument document = render_frame()->GetWebFrame()->GetDocument();
- manifest_url_ = document.ManifestURL();
-
- if (manifest_url_.is_empty()) {
- ManifestUmaUtil::FetchFailed(ManifestUmaUtil::FETCH_EMPTY_URL);
- ResolveCallbacks(ResolveStateFailure);
- return;
- }
-
- fetcher_.reset(new blink::WebManifestFetcher(manifest_url_));
-
- fetcher_->Start(&document, document.ManifestUseCredentials(),
- base::BindOnce(&ManifestManager::OnManifestFetchComplete,
- base::Unretained(this), document.Url()));
-}
-
-static const std::string& GetMessagePrefix() {
- static base::NoDestructor<std::string> message_prefix("Manifest: ");
- return *message_prefix;
-}
-
-void ManifestManager::OnManifestFetchComplete(
- const GURL& document_url,
- const blink::WebURLResponse& response,
- const blink::WebString& data) {
- fetcher_.reset();
- if (response.IsNull() && data.IsEmpty()) {
- manifest_debug_info_ = nullptr;
- ManifestUmaUtil::FetchFailed(ManifestUmaUtil::FETCH_UNSPECIFIED_REASON);
- ResolveCallbacks(ResolveStateFailure);
- return;
- }
-
- ManifestUmaUtil::FetchSucceeded();
- GURL response_url = response.CurrentRequestUrl();
- std::string data_string = data.Utf8();
- base::StringPiece data_piece(data_string);
-
- blink::WebVector<blink::ManifestError> errors;
- bool result = blink::WebManifestParser::ParseManifest(
- data_piece, response_url, document_url, &manifest_, &errors);
-
- manifest_debug_info_ = blink::mojom::ManifestDebugInfo::New();
- manifest_debug_info_->raw_manifest = data_string;
-
- for (const auto& error : errors) {
- blink::WebConsoleMessage message;
- message.level = error.critical
- ? blink::mojom::ConsoleMessageLevel::kError
- : blink::mojom::ConsoleMessageLevel::kWarning;
- message.text =
- blink::WebString::FromUTF8(GetMessagePrefix() + error.message);
- message.url =
- render_frame()->GetWebFrame()->GetDocument().ManifestURL().GetString();
- message.line_number = error.line;
- message.column_number = error.column;
- render_frame()->GetWebFrame()->AddMessageToConsole(message);
-
- manifest_debug_info_->errors.push_back({base::in_place, error.message,
- error.critical, error.line,
- error.column});
- }
-
- // Having errors while parsing the manifest doesn't mean the manifest parsing
- // failed. Some properties might have been ignored but some others kept.
- if (!result) {
- ResolveCallbacks(ResolveStateFailure);
- return;
- }
-
- manifest_url_ = response.CurrentRequestUrl();
- ResolveCallbacks(ResolveStateSuccess);
-}
-
-void ManifestManager::ResolveCallbacks(ResolveState state) {
- // Do not reset |manifest_url_| on failure here. If manifest_url_ is
- // non-empty, that means the link 404s, we failed to fetch it, or it was
- // unparseable. However, the site still tried to specify a manifest, so
- // preserve that information in the URL for the callbacks.
- // |manifest_url| will be reset on navigation or if we receive a didchange
- // event.
- if (state == ResolveStateFailure)
- manifest_ = blink::Manifest();
-
- manifest_dirty_ = state != ResolveStateSuccess;
-
- std::vector<InternalRequestManifestCallback> callbacks;
- swap(callbacks, pending_callbacks_);
-
- for (auto& callback : callbacks) {
- std::move(callback).Run(manifest_url_, manifest_,
- manifest_debug_info_.get());
- }
-}
-
-void ManifestManager::BindToRequest(
- blink::mojom::ManifestManagerRequest request) {
- bindings_.AddBinding(this, std::move(request));
-}
-
-void ManifestManager::OnDestruct() {}
-
-} // namespace content
diff --git a/chromium/content/renderer/manifest/manifest_manager.h b/chromium/content/renderer/manifest/manifest_manager.h
deleted file mode 100644
index a1920c934b1..00000000000
--- a/chromium/content/renderer/manifest/manifest_manager.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MANIFEST_MANIFEST_MANAGER_H_
-#define CONTENT_RENDERER_MANIFEST_MANIFEST_MANAGER_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/public/renderer/render_frame_observer.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "third_party/blink/public/common/manifest/manifest.h"
-#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
-
-class GURL;
-
-namespace blink {
-class WebManifestFetcher;
-class WebURLResponse;
-}
-
-namespace content {
-
-class ManifestFetcher;
-
-// The ManifestManager is a helper class that takes care of fetching and parsing
-// the Manifest of the associated RenderFrame. It uses the ManifestFetcher and
-// the ManifestParser in order to do so.
-//
-// Consumers should use the mojo ManifestManager interface to use this class.
-class ManifestManager : public RenderFrameObserver,
- public blink::mojom::ManifestManager {
- public:
- static bool CanFetchManifest(RenderFrame* render_frame);
-
- explicit ManifestManager(RenderFrame* render_frame);
- ~ManifestManager() override;
-
- // RenderFrameObserver implementation.
- void DidChangeManifest() override;
- void DidCommitProvisionalLoad(bool is_same_document_navigation,
- ui::PageTransition transition) override;
-
- void BindToRequest(blink::mojom::ManifestManagerRequest request);
-
- private:
- enum ResolveState {
- ResolveStateSuccess,
- ResolveStateFailure
- };
-
- using InternalRequestManifestCallback =
- base::OnceCallback<void(const GURL&,
- const blink::Manifest&,
- const blink::mojom::ManifestDebugInfo*)>;
-
- // RenderFrameObserver implementation.
- void OnDestruct() override;
-
- // blink::mojom::ManifestManager implementation.
- void RequestManifest(RequestManifestCallback callback) override;
- void RequestManifestDebugInfo(
- RequestManifestDebugInfoCallback callback) override;
-
- void RequestManifestImpl(InternalRequestManifestCallback callback);
-
- void FetchManifest();
- void OnManifestFetchComplete(const GURL& document_url,
- const blink::WebURLResponse& response,
- const blink::WebString& data);
- void ResolveCallbacks(ResolveState state);
-
- std::unique_ptr<blink::WebManifestFetcher> fetcher_;
-
- // Whether the RenderFrame may have an associated Manifest. If true, the frame
- // may have a manifest, if false, it can't have one. This boolean is true when
- // DidChangeManifest() is called, if it is never called, it means that the
- // associated document has no <link rel='manifest'>.
- bool may_have_manifest_;
-
- // Whether the current Manifest is dirty.
- bool manifest_dirty_;
-
- // Current Manifest. Might be outdated if manifest_dirty_ is true.
- blink::Manifest manifest_;
-
- // The URL of the current manifest.
- GURL manifest_url_;
-
- // Current Manifest debug information.
- blink::mojom::ManifestDebugInfoPtr manifest_debug_info_;
-
- std::vector<InternalRequestManifestCallback> pending_callbacks_;
-
- mojo::BindingSet<blink::mojom::ManifestManager> bindings_;
-
- DISALLOW_COPY_AND_ASSIGN(ManifestManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MANIFEST_MANIFEST_MANAGER_H_
diff --git a/chromium/content/renderer/manifest/manifest_uma_util.cc b/chromium/content/renderer/manifest/manifest_uma_util.cc
deleted file mode 100644
index 7bb45b5c6da..00000000000
--- a/chromium/content/renderer/manifest/manifest_uma_util.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/manifest/manifest_uma_util.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "third_party/blink/public/common/manifest/manifest.h"
-
-namespace content {
-
-namespace {
-
-static const char kUMANameParseSuccess[] = "Manifest.ParseSuccess";
-static const char kUMANameFetchResult[] = "Manifest.FetchResult";
-
-// Enum for UMA purposes, make sure you update histograms.xml if you add new
-// result types. Never delete or reorder an entry; only add new entries
-// immediately before MANIFEST_FETCH_RESULT_TYPE_COUNT.
-enum ManifestFetchResultType {
- MANIFEST_FETCH_SUCCESS = 0,
- MANIFEST_FETCH_ERROR_EMPTY_URL = 1,
- MANIFEST_FETCH_ERROR_UNSPECIFIED = 2,
- MANIFEST_FETCH_ERROR_FROM_UNIQUE_ORIGIN = 3,
-
- // Must stay at the end.
- MANIFEST_FETCH_RESULT_TYPE_COUNT
-};
-
-} // anonymous namespace
-
-void ManifestUmaUtil::ParseSucceeded(const blink::Manifest& manifest) {
- UMA_HISTOGRAM_BOOLEAN(kUMANameParseSuccess, true);
- UMA_HISTOGRAM_BOOLEAN("Manifest.IsEmpty", manifest.IsEmpty());
- if (manifest.IsEmpty())
- return;
-
- UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.name", !manifest.name.is_null());
- UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.short_name",
- !manifest.short_name.is_null());
- UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.start_url",
- !manifest.start_url.is_empty());
- UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.display",
- manifest.display != blink::kWebDisplayModeUndefined);
- UMA_HISTOGRAM_BOOLEAN(
- "Manifest.HasProperty.orientation",
- manifest.orientation != blink::kWebScreenOrientationLockDefault);
- UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.icons", !manifest.icons.empty());
- UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.share_target",
- manifest.share_target.has_value());
- UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.gcm_sender_id",
- !manifest.gcm_sender_id.is_null());
-}
-
-void ManifestUmaUtil::ParseFailed() {
- UMA_HISTOGRAM_BOOLEAN(kUMANameParseSuccess, false);
-}
-
-void ManifestUmaUtil::FetchSucceeded() {
- UMA_HISTOGRAM_ENUMERATION(kUMANameFetchResult,
- MANIFEST_FETCH_SUCCESS,
- MANIFEST_FETCH_RESULT_TYPE_COUNT);
-}
-
-void ManifestUmaUtil::FetchFailed(FetchFailureReason reason) {
- ManifestFetchResultType fetch_result_type = MANIFEST_FETCH_RESULT_TYPE_COUNT;
- switch (reason) {
- case FETCH_EMPTY_URL:
- fetch_result_type = MANIFEST_FETCH_ERROR_EMPTY_URL;
- break;
- case FETCH_FROM_UNIQUE_ORIGIN:
- fetch_result_type = MANIFEST_FETCH_ERROR_FROM_UNIQUE_ORIGIN;
- break;
- case FETCH_UNSPECIFIED_REASON:
- fetch_result_type = MANIFEST_FETCH_ERROR_UNSPECIFIED;
- break;
- }
- DCHECK_NE(fetch_result_type, MANIFEST_FETCH_RESULT_TYPE_COUNT);
-
- UMA_HISTOGRAM_ENUMERATION(kUMANameFetchResult,
- fetch_result_type,
- MANIFEST_FETCH_RESULT_TYPE_COUNT);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/manifest/manifest_uma_util.h b/chromium/content/renderer/manifest/manifest_uma_util.h
deleted file mode 100644
index 1bf569b8ca6..00000000000
--- a/chromium/content/renderer/manifest/manifest_uma_util.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MANIFEST_MANIFEST_UMA_UTIL_H_
-#define CONTENT_RENDERER_MANIFEST_MANIFEST_UMA_UTIL_H_
-
-namespace blink {
-struct Manifest;
-}
-
-namespace content {
-
-class ManifestUmaUtil {
- public:
- enum FetchFailureReason {
- FETCH_EMPTY_URL = 0,
- FETCH_FROM_UNIQUE_ORIGIN,
- FETCH_UNSPECIFIED_REASON
- };
-
- // Record that the Manifest was successfully parsed. If it is an empty
- // Manifest, it will recorded as so and nothing will happen. Otherwise, the
- // presence of each properties will be recorded.
- static void ParseSucceeded(const blink::Manifest& manifest);
-
- // Record that the Manifest parsing failed.
- static void ParseFailed();
-
- // Record that the Manifest fetching succeeded.
- static void FetchSucceeded();
-
- // Record that the Manifest fetching failed and takes the |reason| why it
- // failed.
- static void FetchFailed(FetchFailureReason reason);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MANIFEST_MANIFEST_UMA_UTIL_H_
diff --git a/chromium/content/renderer/media/OWNERS b/chromium/content/renderer/media/OWNERS
index d0c029f0676..f6ac99b1ae8 100644
--- a/chromium/content/renderer/media/OWNERS
+++ b/chromium/content/renderer/media/OWNERS
@@ -2,7 +2,6 @@ file://media/OWNERS
miu@chromium.org
# WebRTC OWNERS.
-emircan@chromium.org
hbos@chromium.org
perkj@chromium.org
tommi@chromium.org
@@ -10,4 +9,7 @@ guidou@chromium.org
olka@chromium.org
maxmorin@chromium.org
+# Original (legacy) owner.
+emircan@chromium.org
+
# COMPONENT: Internals>Media
diff --git a/chromium/content/renderer/media/android/flinging_renderer_client.cc b/chromium/content/renderer/media/android/flinging_renderer_client.cc
new file mode 100644
index 00000000000..d2a017a0952
--- /dev/null
+++ b/chromium/content/renderer/media/android/flinging_renderer_client.cc
@@ -0,0 +1,46 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/android/flinging_renderer_client.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+
+namespace content {
+
+FlingingRendererClient::FlingingRendererClient(
+ ClientExtentionRequest client_extension_request,
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
+ std::unique_ptr<media::MojoRenderer> mojo_renderer)
+ : MojoRendererWrapper(std::move(mojo_renderer)),
+ media_task_runner_(std::move(media_task_runner)),
+ delayed_bind_client_extension_request_(
+ std::move(client_extension_request)),
+ client_extension_binding_(this) {}
+
+FlingingRendererClient::~FlingingRendererClient() = default;
+
+void FlingingRendererClient::Initialize(
+ media::MediaResource* media_resource,
+ media::RendererClient* client,
+ const media::PipelineStatusCB& init_cb) {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ client_ = client;
+
+ client_extension_binding_.Bind(
+ std::move(delayed_bind_client_extension_request_), media_task_runner_);
+
+ MojoRendererWrapper::Initialize(media_resource, client, init_cb);
+}
+
+void FlingingRendererClient::OnRemotePlayStateChange(
+ media::MediaStatus::State state) {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ client_->OnRemotePlayStateChange(state);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/android/flinging_renderer_client.h b/chromium/content/renderer/media/android/flinging_renderer_client.h
new file mode 100644
index 00000000000..fc63f2bcde9
--- /dev/null
+++ b/chromium/content/renderer/media/android/flinging_renderer_client.h
@@ -0,0 +1,66 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_ANDROID_FLINGING_RENDERER_CLIENT_H_
+#define CONTENT_RENDERER_MEDIA_ANDROID_FLINGING_RENDERER_CLIENT_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "content/common/content_export.h"
+#include "media/base/media_resource.h"
+#include "media/base/renderer.h"
+#include "media/base/renderer_client.h"
+#include "media/base/video_renderer_sink.h"
+#include "media/mojo/clients/mojo_renderer.h"
+#include "media/mojo/clients/mojo_renderer_wrapper.h"
+#include "media/mojo/interfaces/renderer_extensions.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+
+namespace content {
+
+// FlingingRendererClient lives in Renderer process and mirrors a
+// FlingingRenderer living in the Browser process.
+class CONTENT_EXPORT FlingingRendererClient
+ : public media::mojom::FlingingRendererClientExtension,
+ public media::MojoRendererWrapper {
+ public:
+ using ClientExtentionRequest =
+ media::mojom::FlingingRendererClientExtensionRequest;
+
+ FlingingRendererClient(
+ ClientExtentionRequest client_extension_request,
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
+ std::unique_ptr<media::MojoRenderer> mojo_renderer);
+
+ ~FlingingRendererClient() override;
+
+ // media::MojoRendererWrapper overrides.
+ void Initialize(media::MediaResource* media_resource,
+ media::RendererClient* client,
+ const media::PipelineStatusCB& init_cb) override;
+
+ // media::mojom::FlingingRendererClientExtension implementation
+ void OnRemotePlayStateChange(media::MediaStatus::State state) override;
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
+
+ media::RendererClient* client_;
+
+ // Used temporarily, to delay binding to |client_extension_binding_| until we
+ // are on the right sequence, when Initialize() is called.
+ ClientExtentionRequest delayed_bind_client_extension_request_;
+
+ mojo::Binding<FlingingRendererClientExtension> client_extension_binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlingingRendererClient);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_ANDROID_FLINGING_RENDERER_CLIENT_H_
diff --git a/chromium/content/renderer/media/android/flinging_renderer_client_factory.cc b/chromium/content/renderer/media/android/flinging_renderer_client_factory.cc
index bfe3a29bc1c..97b9a303fd2 100644
--- a/chromium/content/renderer/media/android/flinging_renderer_client_factory.cc
+++ b/chromium/content/renderer/media/android/flinging_renderer_client_factory.cc
@@ -9,8 +9,10 @@
#include <utility>
#include "base/logging.h"
+#include "content/renderer/media/android/flinging_renderer_client.h"
#include "media/mojo/clients/mojo_renderer.h"
#include "media/mojo/clients/mojo_renderer_factory.h"
+#include "media/mojo/interfaces/renderer_extensions.mojom.h"
namespace content {
@@ -31,8 +33,19 @@ std::unique_ptr<media::Renderer> FlingingRendererClientFactory::CreateRenderer(
const gfx::ColorSpace& /* target_color_space */) {
DCHECK(IsFlingingActive());
- return mojo_flinging_factory_->CreateFlingingRenderer(
- GetActivePresentationId(), media_task_runner, video_renderer_sink);
+ // Used to send messages from the FlingingRenderer (Browser process),
+ // to the FlingingRendererClient (Renderer process). The
+ // |client_extension_request| will be bound in FlingingRendererClient.
+ media::mojom::FlingingRendererClientExtensionPtr client_extension_ptr;
+ auto client_extension_request = mojo::MakeRequest(&client_extension_ptr);
+
+ auto mojo_renderer = mojo_flinging_factory_->CreateFlingingRenderer(
+ GetActivePresentationId(), std::move(client_extension_ptr),
+ media_task_runner, video_renderer_sink);
+
+ return std::make_unique<FlingingRendererClient>(
+ std::move(client_extension_request), media_task_runner,
+ std::move(mojo_renderer));
}
std::string FlingingRendererClientFactory::GetActivePresentationId() {
diff --git a/chromium/content/renderer/media/android/flinging_renderer_client_factory.h b/chromium/content/renderer/media/android/flinging_renderer_client_factory.h
index 7a8114e44ca..91263172a38 100644
--- a/chromium/content/renderer/media/android/flinging_renderer_client_factory.h
+++ b/chromium/content/renderer/media/android/flinging_renderer_client_factory.h
@@ -20,15 +20,10 @@ namespace content {
// Creates a renderer for media flinging.
// The FRCF uses a MojoRendererFactory to create a FlingingRenderer in the
-// browser process. The actual renderer returned by the FRCF is a MojoRenderer
-// directly (as opposed to a dedicated FlingingRendererClient), because all the
-// renderer needs to do is forward calls to the FlingingRenderer in the browser.
+// browser process.
class CONTENT_EXPORT FlingingRendererClientFactory
: public media::RendererFactory {
public:
- // |mojo_flinging_factory| should be created using
- // HostedRendererType::kFlinging, and GetActivePresentationId()
- // should be given to it through SetGetTypeSpecificIdCB().
FlingingRendererClientFactory(
std::unique_ptr<media::MojoRendererFactory> mojo_renderer_factory,
std::unique_ptr<media::RemotePlaybackClientWrapper>
diff --git a/chromium/content/renderer/media/android/media_player_renderer_client.cc b/chromium/content/renderer/media/android/media_player_renderer_client.cc
index 91ac22bb8eb..2a3bcb85fdc 100644
--- a/chromium/content/renderer/media/android/media_player_renderer_client.cc
+++ b/chromium/content/renderer/media/android/media_player_renderer_client.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/callback_helpers.h"
namespace content {
@@ -85,7 +84,7 @@ void MediaPlayerRendererClient::OnStreamTextureWrapperInitialized(
bool success) {
DCHECK(media_task_runner_->BelongsToCurrentThread());
if (!success) {
- base::ResetAndReturn(&init_cb_).Run(
+ std::move(init_cb_).Run(
media::PipelineStatus::PIPELINE_ERROR_INITIALIZATION_FAILED);
return;
}
@@ -118,7 +117,7 @@ void MediaPlayerRendererClient::OnRemoteRendererInitialized(
base::Bind(&MediaPlayerRendererClient::OnScopedSurfaceRequested,
weak_factory_.GetWeakPtr()));
}
- base::ResetAndReturn(&init_cb_).Run(status);
+ std::move(init_cb_).Run(status);
}
void MediaPlayerRendererClient::OnFrameAvailable() {
diff --git a/chromium/content/renderer/media/android/media_player_renderer_client_factory.h b/chromium/content/renderer/media/android/media_player_renderer_client_factory.h
index 94b4c9a5b99..7e7ce468077 100644
--- a/chromium/content/renderer/media/android/media_player_renderer_client_factory.h
+++ b/chromium/content/renderer/media/android/media_player_renderer_client_factory.h
@@ -28,7 +28,7 @@ class CONTENT_EXPORT MediaPlayerRendererClientFactory
: public media::RendererFactory {
public:
using GetStreamTextureWrapperCB =
- base::Callback<media::ScopedStreamTextureWrapper()>;
+ base::RepeatingCallback<media::ScopedStreamTextureWrapper()>;
MediaPlayerRendererClientFactory(
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
diff --git a/chromium/content/renderer/media/android/stream_texture_factory.cc b/chromium/content/renderer/media/android/stream_texture_factory.cc
index cfcb963256f..75af46ea41d 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory.cc
+++ b/chromium/content/renderer/media/android/stream_texture_factory.cc
@@ -39,7 +39,7 @@ void StreamTextureProxy::ClearReceivedFrameCB() {
}
void StreamTextureProxy::BindToTaskRunner(
- const base::Closure& received_frame_cb,
+ const base::RepeatingClosure& received_frame_cb,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
DCHECK(task_runner.get());
diff --git a/chromium/content/renderer/media/android/stream_texture_factory.h b/chromium/content/renderer/media/android/stream_texture_factory.h
index 1f2c63a9641..9e54672bfc8 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory.h
+++ b/chromium/content/renderer/media/android/stream_texture_factory.h
@@ -44,7 +44,7 @@ class StreamTextureProxy : public StreamTextureHost::Listener {
// provided callback will be run on. This can be called on any thread, but
// must be called with the same |task_runner| every time.
void BindToTaskRunner(
- const base::Closure& received_frame_cb,
+ const base::RepeatingClosure& received_frame_cb,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
// StreamTextureHost::Listener implementation:
@@ -76,7 +76,7 @@ class StreamTextureProxy : public StreamTextureHost::Listener {
// Protects access to |received_frame_cb_| and |task_runner_|.
base::Lock lock_;
- base::Closure received_frame_cb_;
+ base::RepeatingClosure received_frame_cb_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureProxy);
diff --git a/chromium/content/renderer/media/android/stream_texture_wrapper_impl.cc b/chromium/content/renderer/media/android/stream_texture_wrapper_impl.cc
index 33192148b5b..9d74c5af738 100644
--- a/chromium/content/renderer/media/android/stream_texture_wrapper_impl.cc
+++ b/chromium/content/renderer/media/android/stream_texture_wrapper_impl.cc
@@ -93,7 +93,7 @@ void StreamTextureWrapperImpl::ReallocateVideoFrame(
media::VideoFrame::WrapNativeTextures(
media::PIXEL_FORMAT_ARGB, holders,
media::BindToCurrentLoop(
- base::Bind(&OnReleaseTexture, factory_, texture_id_ref)),
+ base::BindOnce(&OnReleaseTexture, factory_, texture_id_ref)),
natural_size, gfx::Rect(natural_size), natural_size,
base::TimeDelta());
@@ -117,9 +117,9 @@ void StreamTextureWrapperImpl::ClearReceivedFrameCBOnAnyThread() {
}
void StreamTextureWrapperImpl::SetCurrentFrameInternal(
- const scoped_refptr<media::VideoFrame>& video_frame) {
+ scoped_refptr<media::VideoFrame> video_frame) {
base::AutoLock auto_lock(current_frame_lock_);
- current_frame_ = video_frame;
+ current_frame_ = std::move(video_frame);
}
void StreamTextureWrapperImpl::UpdateTextureSize(const gfx::Size& new_size) {
@@ -146,7 +146,7 @@ void StreamTextureWrapperImpl::UpdateTextureSize(const gfx::Size& new_size) {
}
void StreamTextureWrapperImpl::Initialize(
- const base::Closure& received_frame_cb,
+ const base::RepeatingClosure& received_frame_cb,
const gfx::Size& natural_size,
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
const StreamTextureWrapperInitCB& init_cb) {
@@ -163,7 +163,7 @@ void StreamTextureWrapperImpl::Initialize(
}
void StreamTextureWrapperImpl::InitializeOnMainThread(
- const base::Closure& received_frame_cb,
+ const base::RepeatingClosure& received_frame_cb,
const StreamTextureWrapperInitCB& init_cb) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
DVLOG(2) << __func__;
diff --git a/chromium/content/renderer/media/android/stream_texture_wrapper_impl.h b/chromium/content/renderer/media/android/stream_texture_wrapper_impl.h
index 80f96c7ad3f..bb14d614c1b 100644
--- a/chromium/content/renderer/media/android/stream_texture_wrapper_impl.h
+++ b/chromium/content/renderer/media/android/stream_texture_wrapper_impl.h
@@ -61,7 +61,7 @@ class CONTENT_EXPORT StreamTextureWrapperImpl
// - New frames will be signaled on |compositor_task_runner| via |client|'s
// DidReceiveFrame() method.
void Initialize(
- const base::Closure& received_frame_cb,
+ const base::RepeatingClosure& received_frame_cb,
const gfx::Size& natural_size,
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
const StreamTextureWrapperInitCB& init_cb) override;
@@ -97,13 +97,12 @@ class CONTENT_EXPORT StreamTextureWrapperImpl
// Destroys |this| safely on |main_task_runner_|.
void Destroy() override;
- void InitializeOnMainThread(const base::Closure& received_frame_cb,
+ void InitializeOnMainThread(const base::RepeatingClosure& received_frame_cb,
const StreamTextureWrapperInitCB& init_cb);
void ReallocateVideoFrame(const gfx::Size& natural_size);
- void SetCurrentFrameInternal(
- const scoped_refptr<media::VideoFrame>& video_frame);
+ void SetCurrentFrameInternal(scoped_refptr<media::VideoFrame> video_frame);
bool enable_texture_copy_;
diff --git a/chromium/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc
index b8390d3b7a1..8075706517e 100644
--- a/chromium/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc
+++ b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc
@@ -33,8 +33,9 @@ constexpr base::TimeDelta kDeleteTimeout =
class AudioRendererSinkCacheTest : public testing::Test {
public:
AudioRendererSinkCacheTest()
- : task_env_(base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
- base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED),
+ : task_env_(
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+ base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED),
cache_(std::make_unique<AudioRendererSinkCacheImpl>(
task_env_.GetMainThreadTaskRunner(),
base::BindRepeating(&AudioRendererSinkCacheTest::CreateSink,
diff --git a/chromium/content/renderer/media/audio/mojo_audio_output_ipc.cc b/chromium/content/renderer/media/audio/mojo_audio_output_ipc.cc
index 267f7ea1ae6..03666b904dc 100644
--- a/chromium/content/renderer/media/audio/mojo_audio_output_ipc.cc
+++ b/chromium/content/renderer/media/audio/mojo_audio_output_ipc.cc
@@ -50,9 +50,9 @@ void MojoAudioOutputIPC::RequestDeviceAuthorization(
DCHECK(!StreamCreationRequested());
delegate_ = delegate;
- // We wrap the callback in a ScopedCallbackRunner to detect the case when the
- // mojo connection is terminated prior to receiving the response. In this
- // case, the callback runner will be destructed and call
+ // We wrap the callback in a WrapCallbackWithDefaultInvokeIfNotRun to detect
+ // the case when the mojo connection is terminated prior to receiving the
+ // response. In this case, the callback runner will be destructed and call
// ReceivedDeviceAuthorization with an error.
DoRequestDeviceAuthorization(
session_id, device_id,
@@ -108,6 +108,12 @@ void MojoAudioOutputIPC::PauseStream() {
stream_->Pause();
}
+void MojoAudioOutputIPC::FlushStream() {
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ if (stream_.is_bound())
+ stream_->Flush();
+}
+
void MojoAudioOutputIPC::CloseStream() {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
stream_provider_.reset();
@@ -162,8 +168,8 @@ MojoAudioOutputIPC::MakeProviderRequest() {
// Don't set a connection error handler.
// There are three possible reasons for a connection error.
// 1. The connection is broken before authorization was completed. In this
- // case, the ScopedCallbackRunner wrapping the callback will call the
- // callback with failure.
+ // case, the WrapCallbackWithDefaultInvokeIfNotRun wrapping the callback
+ // will call the callback with failure.
// 2. The connection is broken due to authorization being denied. In this
// case, the callback was called with failure first, so the state of the
// stream provider is irrelevant.
diff --git a/chromium/content/renderer/media/audio/mojo_audio_output_ipc.h b/chromium/content/renderer/media/audio/mojo_audio_output_ipc.h
index 05a7ce91186..eaabab40e1b 100644
--- a/chromium/content/renderer/media/audio/mojo_audio_output_ipc.h
+++ b/chromium/content/renderer/media/audio/mojo_audio_output_ipc.h
@@ -50,6 +50,7 @@ class CONTENT_EXPORT MojoAudioOutputIPC
const base::Optional<base::UnguessableToken>& processing_id) override;
void PlayStream() override;
void PauseStream() override;
+ void FlushStream() override;
void CloseStream() override;
void SetVolume(double volume) override;
diff --git a/chromium/content/renderer/media/audio/mojo_audio_output_ipc_unittest.cc b/chromium/content/renderer/media/audio/mojo_audio_output_ipc_unittest.cc
index ff912da8635..ced4c5375da 100644
--- a/chromium/content/renderer/media/audio/mojo_audio_output_ipc_unittest.cc
+++ b/chromium/content/renderer/media/audio/mojo_audio_output_ipc_unittest.cc
@@ -174,6 +174,7 @@ class MockStream : public media::mojom::AudioOutputStream {
public:
MOCK_METHOD0(Play, void());
MOCK_METHOD0(Pause, void());
+ MOCK_METHOD0(Flush, void());
MOCK_METHOD1(SetVolume, void(double));
};
diff --git a/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc b/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
index 95eeccda317..469fd103f3f 100644
--- a/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
+++ b/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
@@ -8,7 +8,6 @@
#include <GLES2/gl2ext.h>
#include "base/bind.h"
-#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/unguessable_token.h"
@@ -24,7 +23,6 @@
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
-#include "media/base/media_switches.h"
#include "media/filters/gpu_video_decoder.h"
#include "media/gpu/gpu_video_accelerator_util.h"
#include "media/gpu/ipc/client/gpu_video_decode_accelerator_host.h"
@@ -121,22 +119,22 @@ void GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner(
if (context_provider_->BindToCurrentThread() !=
gpu::ContextResult::kSuccess) {
- SetContextProviderLost();
+ OnContextLost();
return;
}
+ context_provider_->AddObserver(this);
+
#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
- if (base::FeatureList::IsEnabled(media::kMojoVideoDecoder)) {
- // Note: This is a bit of a hack, since we don't specify the implementation
- // before asking for the map of supported configs. We do this because it
- // (a) saves an ipc call, and (b) makes the return of those configs atomic.
- // Otherwise, we might have received configs for kDefault but not yet
- // kAlternate, for example.
- interface_factory_->CreateVideoDecoder(mojo::MakeRequest(&video_decoder_));
- video_decoder_->GetSupportedConfigs(base::BindOnce(
- &GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs,
- base::Unretained(this)));
- }
+ // Note: This is a bit of a hack, since we don't specify the implementation
+ // before asking for the map of supported configs. We do this because it
+ // (a) saves an ipc call, and (b) makes the return of those configs atomic.
+ // Otherwise, we might have received configs for kDefault but not yet
+ // kAlternate, for example.
+ interface_factory_->CreateVideoDecoder(mojo::MakeRequest(&video_decoder_));
+ video_decoder_->GetSupportedConfigs(base::BindOnce(
+ &GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs,
+ base::Unretained(this)));
#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
}
@@ -153,7 +151,7 @@ bool GpuVideoAcceleratorFactoriesImpl::CheckContextLost() {
return true;
if (context_provider_->ContextGL()->GetGraphicsResetStatusKHR() !=
GL_NO_ERROR) {
- SetContextProviderLost();
+ OnContextLost();
return true;
}
return false;
@@ -165,6 +163,8 @@ void GpuVideoAcceleratorFactoriesImpl::DestroyContext() {
if (!context_provider_)
return;
+
+ context_provider_->RemoveObserver(this);
context_provider_ = nullptr;
RecordContextProviderPhaseUmaEnum(
ContextProviderPhase::CONTEXT_PROVIDER_RELEASED);
@@ -231,21 +231,14 @@ GpuVideoAcceleratorFactoriesImpl::CreateVideoDecoder(
return nullptr;
#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
- if (base::FeatureList::IsEnabled(media::kMojoVideoDecoder)) {
- media::mojom::VideoDecoderPtr video_decoder;
- interface_factory_->CreateVideoDecoder(mojo::MakeRequest(&video_decoder));
- return std::make_unique<media::MojoVideoDecoder>(
- task_runner_, this, media_log, std::move(video_decoder), implementation,
- request_overlay_info_cb, rendering_color_space_);
- }
+ media::mojom::VideoDecoderPtr video_decoder;
+ interface_factory_->CreateVideoDecoder(mojo::MakeRequest(&video_decoder));
+ return std::make_unique<media::MojoVideoDecoder>(
+ task_runner_, this, media_log, std::move(video_decoder), implementation,
+ request_overlay_info_cb, rendering_color_space_);
+#else
+ return nullptr;
#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
-
- // GpuVideoDecoder is our default implementation without MVD.
- if (implementation != media::VideoDecoderImplementation::kDefault)
- return nullptr;
-
- return std::make_unique<media::GpuVideoDecoder>(
- this, request_overlay_info_cb, rendering_color_space_, media_log);
}
std::unique_ptr<media::VideoDecodeAccelerator>
@@ -518,8 +511,9 @@ bool GpuVideoAcceleratorFactoriesImpl::CheckContextProviderLostOnMainThread() {
return context_provider_lost_;
}
-void GpuVideoAcceleratorFactoriesImpl::SetContextProviderLost() {
+void GpuVideoAcceleratorFactoriesImpl::OnContextLost() {
DCHECK(task_runner_->BelongsToCurrentThread());
+ TRACE_EVENT0("media", "GpuVideoAcceleratorFactoriesImpl::OnContextLost");
// Don't delete the |context_provider_| here, we could be in the middle of
// it notifying about the loss, and we'd be destroying it while it's on
diff --git a/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h b/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h
index 96e1141f2f9..b4117a6f753 100644
--- a/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h
+++ b/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h
@@ -19,6 +19,7 @@
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/unguessable_token.h"
+#include "components/viz/common/gpu/context_lost_observer.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/content_export.h"
#include "media/mojo/interfaces/interface_factory.mojom.h"
@@ -50,7 +51,8 @@ namespace content {
// |context_provider| should not support locking and will be bound to
// |task_runner_| where all the operations on the context should also happen.
class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
- : public media::GpuVideoAcceleratorFactories {
+ : public media::GpuVideoAcceleratorFactories,
+ public viz::ContextLostObserver {
public:
// Takes a ref on |gpu_channel_host| and tests |context| for loss before each
// use. Safe to call from any thread.
@@ -160,7 +162,8 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
media::mojom::InterfaceFactoryPtrInfo interface_factory_info,
media::mojom::VideoEncodeAcceleratorProviderPtrInfo vea_provider_info);
- void SetContextProviderLost();
+ // viz::ContextLostObserver implementation.
+ void OnContextLost() override;
void SetContextProviderLostOnMainThread();
void OnSupportedDecoderConfigs(
diff --git a/chromium/content/renderer/media/media_factory.cc b/chromium/content/renderer/media/media_factory.cc
index ca4338f1f76..dfad0ae368e 100644
--- a/chromium/content/renderer/media/media_factory.cc
+++ b/chromium/content/renderer/media/media_factory.cc
@@ -36,7 +36,6 @@
#include "media/blink/resource_fetch_context.h"
#include "media/blink/webencryptedmediaclient_impl.h"
#include "media/blink/webmediaplayer_impl.h"
-#include "media/filters/context_3d.h"
#include "media/media_buildflags.h"
#include "media/renderers/decrypting_renderer_factory.h"
#include "media/renderers/default_decoder_factory.h"
@@ -50,7 +49,6 @@
#include "third_party/blink/public/platform/web_video_frame_submitter.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_local_frame.h"
-#include "ui/base/ui_base_features.h"
#include "url/origin.h"
#if defined(OS_ANDROID)
@@ -142,9 +140,6 @@ namespace content {
// static
blink::WebMediaPlayer::SurfaceLayerMode
MediaFactory::GetVideoSurfaceLayerMode() {
- if (features::IsMultiProcessMash())
- return blink::WebMediaPlayer::SurfaceLayerMode::kNever;
-
#if defined(OS_ANDROID)
if (base::FeatureList::IsEnabled(media::kDisableSurfaceLayerForVideo))
return blink::WebMediaPlayer::SurfaceLayerMode::kNever;
@@ -439,10 +434,10 @@ MediaFactory::CreateRendererFactorySelector(
std::make_unique<MediaPlayerRendererClientFactory>(
render_thread->compositor_task_runner(),
std::move(mojo_media_player_renderer_factory),
- base::Bind(&StreamTextureWrapperImpl::Create,
- render_thread->EnableStreamTextureCopy(),
- render_thread->GetStreamTexureFactory(),
- base::ThreadTaskRunnerHandle::Get())));
+ base::BindRepeating(&StreamTextureWrapperImpl::Create,
+ render_thread->EnableStreamTextureCopy(),
+ render_thread->GetStreamTexureFactory(),
+ base::ThreadTaskRunnerHandle::Get())));
factory_selector->SetUseMediaPlayer(use_media_player);
diff --git a/chromium/content/renderer/media/media_interface_factory.cc b/chromium/content/renderer/media/media_interface_factory.cc
index d3ea6407825..50b4c9691c5 100644
--- a/chromium/content/renderer/media/media_interface_factory.cc
+++ b/chromium/content/renderer/media/media_interface_factory.cc
@@ -110,18 +110,20 @@ void MediaInterfaceFactory::CreateMediaPlayerRenderer(
void MediaInterfaceFactory::CreateFlingingRenderer(
const std::string& presentation_id,
+ media::mojom::FlingingRendererClientExtensionPtr client_extension,
media::mojom::RendererRequest request) {
if (!task_runner_->BelongsToCurrentThread()) {
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&MediaInterfaceFactory::CreateFlingingRenderer,
- weak_this_, presentation_id, std::move(request)));
+ weak_this_, presentation_id, std::move(client_extension),
+ std::move(request)));
return;
}
DVLOG(1) << __func__;
- GetMediaInterfaceFactory()->CreateFlingingRenderer(presentation_id,
- std::move(request));
+ GetMediaInterfaceFactory()->CreateFlingingRenderer(
+ presentation_id, std::move(client_extension), std::move(request));
}
#endif // defined(OS_ANDROID)
diff --git a/chromium/content/renderer/media/media_interface_factory.h b/chromium/content/renderer/media/media_interface_factory.h
index 59cb288e038..b22aad68e3c 100644
--- a/chromium/content/renderer/media/media_interface_factory.h
+++ b/chromium/content/renderer/media/media_interface_factory.h
@@ -42,8 +42,10 @@ class CONTENT_EXPORT MediaInterfaceFactory
media::mojom::RendererRequest request) final;
#endif
#if defined(OS_ANDROID)
- void CreateFlingingRenderer(const std::string& presentation_id,
- media::mojom::RendererRequest request) final;
+ void CreateFlingingRenderer(
+ const std::string& presentation_id,
+ media::mojom::FlingingRendererClientExtensionPtr client_extension,
+ media::mojom::RendererRequest request) final;
void CreateMediaPlayerRenderer(
media::mojom::MediaPlayerRendererClientExtensionPtr client_extension_ptr,
media::mojom::RendererRequest request,
diff --git a/chromium/content/renderer/media/media_permission_dispatcher.cc b/chromium/content/renderer/media/media_permission_dispatcher.cc
index 96f057c5f6a..d971db6ac70 100644
--- a/chromium/content/renderer/media/media_permission_dispatcher.cc
+++ b/chromium/content/renderer/media/media_permission_dispatcher.cc
@@ -67,18 +67,19 @@ void MediaPermissionDispatcher::OnNavigation() {
void MediaPermissionDispatcher::HasPermission(
Type type,
- const PermissionStatusCB& permission_status_cb) {
+ PermissionStatusCB permission_status_cb) {
if (!task_runner_->RunsTasksInCurrentSequence()) {
task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(&MediaPermissionDispatcher::HasPermission, weak_ptr_,
- type, media::BindToCurrentLoop(permission_status_cb)));
+ base::BindOnce(
+ &MediaPermissionDispatcher::HasPermission, weak_ptr_, type,
+ media::BindToCurrentLoop(std::move(permission_status_cb))));
return;
}
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- int request_id = RegisterCallback(permission_status_cb);
+ int request_id = RegisterCallback(std::move(permission_status_cb));
DVLOG(2) << __func__ << ": request ID " << request_id;
GetPermissionService()->HasPermission(
@@ -89,18 +90,19 @@ void MediaPermissionDispatcher::HasPermission(
void MediaPermissionDispatcher::RequestPermission(
Type type,
- const PermissionStatusCB& permission_status_cb) {
+ PermissionStatusCB permission_status_cb) {
if (!task_runner_->RunsTasksInCurrentSequence()) {
task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(&MediaPermissionDispatcher::RequestPermission, weak_ptr_,
- type, media::BindToCurrentLoop(permission_status_cb)));
+ base::BindOnce(
+ &MediaPermissionDispatcher::RequestPermission, weak_ptr_, type,
+ media::BindToCurrentLoop(std::move(permission_status_cb))));
return;
}
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- int request_id = RegisterCallback(permission_status_cb);
+ int request_id = RegisterCallback(std::move(permission_status_cb));
DVLOG(2) << __func__ << ": request ID " << request_id;
GetPermissionService()->RequestPermission(
@@ -116,12 +118,12 @@ bool MediaPermissionDispatcher::IsEncryptedMediaEnabled() {
}
uint32_t MediaPermissionDispatcher::RegisterCallback(
- const PermissionStatusCB& permission_status_cb) {
+ PermissionStatusCB permission_status_cb) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
uint32_t request_id = next_request_id_++;
DCHECK(!requests_.count(request_id));
- requests_[request_id] = permission_status_cb;
+ requests_[request_id] = std::move(permission_status_cb);
return request_id;
}
@@ -147,7 +149,7 @@ void MediaPermissionDispatcher::OnPermissionStatus(
auto iter = requests_.find(request_id);
DCHECK(iter != requests_.end()) << "Request not found.";
- PermissionStatusCB permission_status_cb = iter->second;
+ PermissionStatusCB permission_status_cb = std::move(iter->second);
requests_.erase(iter);
std::move(permission_status_cb)
@@ -161,7 +163,7 @@ void MediaPermissionDispatcher::OnConnectionError() {
RequestMap requests;
requests.swap(requests_);
for (auto& request : requests)
- request.second.Run(false);
+ std::move(request.second).Run(false);
}
} // namespace content
diff --git a/chromium/content/renderer/media/media_permission_dispatcher.h b/chromium/content/renderer/media/media_permission_dispatcher.h
index b5ece99f3b6..a06b6c5bc29 100644
--- a/chromium/content/renderer/media/media_permission_dispatcher.h
+++ b/chromium/content/renderer/media/media_permission_dispatcher.h
@@ -37,10 +37,9 @@ class CONTENT_EXPORT MediaPermissionDispatcher : public media::MediaPermission {
// Note: Can be called on any thread. The |permission_status_cb| will always
// be fired on the thread where these methods are called.
void HasPermission(Type type,
- const PermissionStatusCB& permission_status_cb) override;
- void RequestPermission(
- Type type,
- const PermissionStatusCB& permission_status_cb) override;
+ PermissionStatusCB permission_status_cb) override;
+ void RequestPermission(Type type,
+ PermissionStatusCB permission_status_cb) override;
bool IsEncryptedMediaEnabled() override;
private:
@@ -49,7 +48,7 @@ class CONTENT_EXPORT MediaPermissionDispatcher : public media::MediaPermission {
// Register PermissionStatusCBs. Returns |request_id| that can be used to make
// PermissionService calls.
- uint32_t RegisterCallback(const PermissionStatusCB& permission_status_cb);
+ uint32_t RegisterCallback(PermissionStatusCB permission_status_cb);
// Ensure there is a connection to the permission service and return it.
blink::mojom::PermissionService* GetPermissionService();
diff --git a/chromium/content/renderer/media/render_media_client.cc b/chromium/content/renderer/media/render_media_client.cc
index 10061f183c5..e1878231f4e 100644
--- a/chromium/content/renderer/media/render_media_client.cc
+++ b/chromium/content/renderer/media/render_media_client.cc
@@ -9,6 +9,7 @@
#include "base/time/default_tick_clock.h"
#include "content/public/common/content_client.h"
#include "content/public/renderer/content_renderer_client.h"
+#include "media/base/audio_parameters.h"
#include "media/base/media_switches.h"
#include "media/base/video_color_space.h"
#include "ui/display/display_switches.h"
@@ -47,4 +48,11 @@ bool RenderMediaClient::IsSupportedBitstreamAudioCodec(
return GetContentClient()->renderer()->IsSupportedBitstreamAudioCodec(codec);
}
+base::Optional<::media::AudioRendererAlgorithmParameters>
+RenderMediaClient::GetAudioRendererAlgorithmParameters(
+ media::AudioParameters audio_parameters) {
+ return GetContentClient()->renderer()->GetAudioRendererAlgorithmParameters(
+ audio_parameters);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/render_media_client.h b/chromium/content/renderer/media/render_media_client.h
index eeb99cc318a..5cd93d2616a 100644
--- a/chromium/content/renderer/media/render_media_client.h
+++ b/chromium/content/renderer/media/render_media_client.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_MEDIA_RENDER_MEDIA_CLIENT_H_
#include "content/common/content_export.h"
+#include "media/base/audio_parameters.h"
#include "media/base/media_client.h"
namespace content {
@@ -26,6 +27,9 @@ class CONTENT_EXPORT RenderMediaClient : public media::MediaClient {
bool IsSupportedAudioType(const media::AudioType& type) final;
bool IsSupportedVideoType(const media::VideoType& type) final;
bool IsSupportedBitstreamAudioCodec(media::AudioCodec codec) final;
+ base::Optional<::media::AudioRendererAlgorithmParameters>
+ GetAudioRendererAlgorithmParameters(
+ media::AudioParameters audio_parameters) final;
private:
RenderMediaClient();
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
index 5c6b526f0ee..8d5a31c821e 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -114,10 +114,10 @@ std::unique_ptr<RendererWebAudioDeviceImpl> RendererWebAudioDeviceImpl::Create(
WebAudioDevice::RenderCallback* callback,
int session_id) {
return std::unique_ptr<RendererWebAudioDeviceImpl>(
- new RendererWebAudioDeviceImpl(layout, channels, latency_hint, callback,
- session_id,
- base::Bind(&GetOutputDeviceParameters),
- base::Bind(&FrameIdFromCurrentContext)));
+ new RendererWebAudioDeviceImpl(
+ layout, channels, latency_hint, callback, session_id,
+ base::BindOnce(&GetOutputDeviceParameters),
+ base::BindOnce(&FrameIdFromCurrentContext)));
}
RendererWebAudioDeviceImpl::RendererWebAudioDeviceImpl(
@@ -126,17 +126,17 @@ RendererWebAudioDeviceImpl::RendererWebAudioDeviceImpl(
const blink::WebAudioLatencyHint& latency_hint,
WebAudioDevice::RenderCallback* callback,
int session_id,
- const OutputDeviceParamsCallback& device_params_cb,
- const RenderFrameIdCallback& render_frame_id_cb)
+ OutputDeviceParamsCallback device_params_cb,
+ RenderFrameIdCallback render_frame_id_cb)
: latency_hint_(latency_hint),
client_callback_(callback),
session_id_(session_id),
- frame_id_(render_frame_id_cb.Run()) {
+ frame_id_(std::move(render_frame_id_cb).Run()) {
DCHECK(client_callback_);
- DCHECK_NE(frame_id_, MSG_ROUTING_NONE);
+ DCHECK(session_id_ == 0 || frame_id_ != MSG_ROUTING_NONE);
media::AudioParameters hardware_params(
- device_params_cb.Run(frame_id_, session_id_, std::string()));
+ std::move(device_params_cb).Run(frame_id_, session_id_, std::string()));
// On systems without audio hardware the returned parameters may be invalid.
// In which case just choose whatever we want for the fake device.
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.h b/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
index 3e39f74d257..9a83c67affe 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
@@ -67,20 +67,20 @@ class CONTENT_EXPORT RendererWebAudioDeviceImpl
protected:
// Callback to get output device params (for tests).
using OutputDeviceParamsCallback =
- base::Callback<media::AudioParameters(int frame_id,
- int session_id,
- const std::string& device_id)>;
+ base::OnceCallback<media::AudioParameters(int frame_id,
+ int session_id,
+ const std::string& device_id)>;
// Callback get render frame ID for current context (for tests).
- using RenderFrameIdCallback = base::Callback<int()>;
+ using RenderFrameIdCallback = base::OnceCallback<int()>;
RendererWebAudioDeviceImpl(media::ChannelLayout layout,
int channels,
const blink::WebAudioLatencyHint& latency_hint,
blink::WebAudioDevice::RenderCallback* callback,
int session_id,
- const OutputDeviceParamsCallback& device_params_cb,
- const RenderFrameIdCallback& render_frame_id_cb);
+ OutputDeviceParamsCallback device_params_cb,
+ RenderFrameIdCallback render_frame_id_cb);
private:
const scoped_refptr<base::SingleThreadTaskRunner>& GetMediaTaskRunner();
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
index 4b8faa45fc3..d8cbaf1f315 100644
--- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
@@ -238,8 +238,6 @@ bool RendererWebMediaPlayerDelegate::OnMessageReceived(
OnMediaDelegateVolumeMultiplierUpdate)
IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_BecamePersistentVideo,
OnMediaDelegateBecamePersistentVideo)
- IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_EndPictureInPictureMode,
- OnPictureInPictureModeEnded)
IPC_MESSAGE_UNHANDLED(return false)
IPC_END_MESSAGE_MAP()
return true;
@@ -355,13 +353,6 @@ void RendererWebMediaPlayerDelegate::OnMediaDelegateBecamePersistentVideo(
observer->OnBecamePersistentVideo(value);
}
-void RendererWebMediaPlayerDelegate::OnPictureInPictureModeEnded(
- int player_id) {
- Observer* observer = id_map_.Lookup(player_id);
- if (observer)
- observer->OnPictureInPictureModeEnded();
-}
-
void RendererWebMediaPlayerDelegate::ScheduleUpdateTask() {
if (!pending_update_task_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
index 3e3921e7b50..fc39ff3e5ac 100644
--- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
@@ -95,7 +95,6 @@ class CONTENT_EXPORT RendererWebMediaPlayerDelegate
void OnMediaDelegateSuspendAllMediaPlayers();
void OnMediaDelegateVolumeMultiplierUpdate(int player_id, double multiplier);
void OnMediaDelegateBecamePersistentVideo(int player_id, bool value);
- void OnPictureInPictureModeEnded(int player_id);
// Schedules UpdateTask() to run soon.
void ScheduleUpdateTask();
diff --git a/chromium/content/renderer/media/stream/apply_constraints_processor.cc b/chromium/content/renderer/media/stream/apply_constraints_processor.cc
index ca1101920c8..d3b2e6707f6 100644
--- a/chromium/content/renderer/media/stream/apply_constraints_processor.cc
+++ b/chromium/content/renderer/media/stream/apply_constraints_processor.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/sequenced_task_runner.h"
#include "base/task_runner.h"
@@ -346,7 +345,7 @@ void ApplyConstraintsProcessor::CleanupRequest(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!current_request_.IsNull());
DCHECK(request_completed_cb_);
- base::ResetAndReturn(&request_completed_cb_).Run();
+ std::move(request_completed_cb_).Run();
std::move(web_request_callback).Run();
current_request_.Reset();
video_source_ = nullptr;
diff --git a/chromium/content/renderer/media/stream/local_media_stream_audio_source.cc b/chromium/content/renderer/media/stream/local_media_stream_audio_source.cc
index bb54fd2574e..9f7325a0c74 100644
--- a/chromium/content/renderer/media/stream/local_media_stream_audio_source.cc
+++ b/chromium/content/renderer/media/stream/local_media_stream_audio_source.cc
@@ -17,13 +17,13 @@ LocalMediaStreamAudioSource::LocalMediaStreamAudioSource(
const blink::MediaStreamDevice& device,
const int* requested_buffer_size,
bool disable_local_echo,
- const ConstraintsCallback& started_callback,
+ ConstraintsRepeatingCallback started_callback,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: blink::MediaStreamAudioSource(std::move(task_runner),
true /* is_local_source */,
disable_local_echo),
consumer_render_frame_id_(consumer_render_frame_id),
- started_callback_(started_callback) {
+ started_callback_(std::move(started_callback)) {
DVLOG(1) << "LocalMediaStreamAudioSource::LocalMediaStreamAudioSource()";
SetDevice(device);
@@ -37,10 +37,17 @@ LocalMediaStreamAudioSource::LocalMediaStreamAudioSource(
(device.input.sample_rate() * blink::kFallbackAudioLatencyMs) / 1000;
}
- SetFormat(media::AudioParameters(
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- device.input.channel_layout(), device.input.sample_rate(),
- frames_per_buffer));
+ // Set audio format and take into account the special case where a discrete
+ // channel layout is reported since it will result in an invalid channel
+ // count (=0) if only default constructions is used.
+ media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ device.input.channel_layout(),
+ device.input.sample_rate(), frames_per_buffer);
+ if (device.input.channel_layout() == media::CHANNEL_LAYOUT_DISCRETE) {
+ DCHECK_LE(device.input.channels(), 2);
+ params.set_channels_for_discrete(device.input.channels());
+ }
+ SetFormat(params);
}
LocalMediaStreamAudioSource::~LocalMediaStreamAudioSource() {
diff --git a/chromium/content/renderer/media/stream/local_media_stream_audio_source.h b/chromium/content/renderer/media/stream/local_media_stream_audio_source.h
index 14915b8a1a4..c115e5b8fba 100644
--- a/chromium/content/renderer/media/stream/local_media_stream_audio_source.h
+++ b/chromium/content/renderer/media/stream/local_media_stream_audio_source.h
@@ -31,7 +31,7 @@ class CONTENT_EXPORT LocalMediaStreamAudioSource
const blink::MediaStreamDevice& device,
const int* requested_buffer_size,
bool disable_local_echo,
- const ConstraintsCallback& started_callback,
+ ConstraintsRepeatingCallback started_callback,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~LocalMediaStreamAudioSource() final;
@@ -61,7 +61,7 @@ class CONTENT_EXPORT LocalMediaStreamAudioSource
scoped_refptr<media::AudioCapturerSource> source_;
// Callback that's called when the audio source has been initialized.
- ConstraintsCallback started_callback_;
+ ConstraintsRepeatingCallback started_callback_;
// In debug builds, check that all methods that could cause object graph
// or data flow changes are being called on the main thread.
diff --git a/chromium/content/renderer/media/stream/media_stream_audio_processor.cc b/chromium/content/renderer/media/stream/media_stream_audio_processor.cc
index 5ec143e1e96..7e76f7aa126 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_processor.cc
+++ b/chromium/content/renderer/media/stream/media_stream_audio_processor.cc
@@ -48,7 +48,7 @@ using EchoCancellationType =
namespace {
using webrtc::AudioProcessing;
-using webrtc::NoiseSuppression;
+using NoiseSuppression = webrtc::AudioProcessing::Config::NoiseSuppression;
constexpr int kAudioProcessingNumberOfChannels = 1;
constexpr int kBuffersPerSecond = 100; // 10 ms per buffer.
@@ -378,7 +378,6 @@ void MediaStreamAudioProcessor::Stop() {
if (!audio_processing_.get())
return;
- audio_processing_.get()->UpdateHistogramsOnCallEnd();
blink::StopEchoCancellationDump(audio_processing_.get());
worker_queue_.reset(nullptr);
@@ -610,22 +609,6 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
playout_data_source_->AddPlayoutSink(this);
}
- if (properties.EchoCancellationIsWebRtcProvided()) {
- blink::EnableEchoCancellation(audio_processing_.get());
- }
-
- if (properties.goog_noise_suppression)
- blink::EnableNoiseSuppression(audio_processing_.get(),
- NoiseSuppression::kHigh);
-
- if (goog_typing_detection) {
- // TODO(xians): Remove this |typing_detector_| after the typing suppression
- // is enabled by default.
- typing_detector_.reset(new webrtc::TypingDetection());
- blink::EnableTypingDetection(audio_processing_.get(),
- typing_detector_.get());
- }
-
// TODO(saza): When Chrome uses AGC2, handle all JSON config via the
// webrtc::AudioProcessing::Config, crbug.com/895814.
base::Optional<double> pre_amplifier_fixed_gain_factor,
@@ -634,36 +617,44 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
&pre_amplifier_fixed_gain_factor,
&gain_control_compression_gain_db);
- if (properties.goog_auto_gain_control) {
- blink::EnableAutomaticGainControl(audio_processing_.get(),
- gain_control_compression_gain_db);
- }
-
webrtc::AudioProcessing::Config apm_config = audio_processing_->GetConfig();
apm_config.high_pass_filter.enabled = properties.goog_highpass_filter;
- if (properties.goog_experimental_auto_gain_control) {
- apm_config.gain_controller2.enabled =
- base::FeatureList::IsEnabled(features::kWebRtcHybridAgc);
- apm_config.gain_controller2.fixed_digital.gain_db = 0.f;
-
- apm_config.gain_controller2.adaptive_digital.enabled = true;
-
- const bool use_peaks_not_rms = base::GetFieldTrialParamByFeatureAsBool(
- features::kWebRtcHybridAgc, "use_peaks_not_rms", false);
- using Shortcut =
- webrtc::AudioProcessing::Config::GainController2::LevelEstimator;
- apm_config.gain_controller2.adaptive_digital.level_estimator =
- use_peaks_not_rms ? Shortcut::kPeak : Shortcut::kRms;
-
- const int saturation_margin = base::GetFieldTrialParamByFeatureAsInt(
- features::kWebRtcHybridAgc, "saturation_margin", -1);
- if (saturation_margin != -1) {
- apm_config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
- saturation_margin;
+ if (properties.goog_auto_gain_control ||
+ properties.goog_experimental_auto_gain_control) {
+ bool use_hybrid_agc = false;
+ base::Optional<bool> use_peaks_not_rms;
+ base::Optional<int> saturation_margin;
+ if (properties.goog_experimental_auto_gain_control) {
+ use_hybrid_agc = base::FeatureList::IsEnabled(features::kWebRtcHybridAgc);
+ if (use_hybrid_agc) {
+ DCHECK(properties.goog_auto_gain_control)
+ << "Cannot enable hybrid AGC when AGC is disabled.";
+ }
+ use_peaks_not_rms = base::GetFieldTrialParamByFeatureAsBool(
+ features::kWebRtcHybridAgc, "use_peaks_not_rms", false);
+ saturation_margin = base::GetFieldTrialParamByFeatureAsInt(
+ features::kWebRtcHybridAgc, "saturation_margin", -1);
}
+ blink::ConfigAutomaticGainControl(
+ &apm_config, properties.goog_auto_gain_control,
+ properties.goog_experimental_auto_gain_control, use_hybrid_agc,
+ use_peaks_not_rms, saturation_margin, gain_control_compression_gain_db);
}
+
blink::ConfigPreAmplifier(&apm_config, pre_amplifier_fixed_gain_factor);
+ if (goog_typing_detection) {
+ // TODO(xians): Remove this |typing_detector_| after the typing suppression
+ // is enabled by default.
+ typing_detector_.reset(new webrtc::TypingDetection());
+ blink::EnableTypingDetection(&apm_config, typing_detector_.get());
+ }
+ if (properties.goog_noise_suppression) {
+ blink::EnableNoiseSuppression(&apm_config, NoiseSuppression::kHigh);
+ }
+ if (properties.EchoCancellationIsWebRtcProvided()) {
+ blink::EnableEchoCancellation(&apm_config);
+ }
audio_processing_->ApplyConfig(apm_config);
RecordProcessingState(AUDIO_PROCESSING_ENABLED);
@@ -681,7 +672,13 @@ void MediaStreamAudioProcessor::InitializeCaptureFifo(
// convert at output) or ideally, have a backchannel from the sink to know
// what format it would prefer.
const int output_sample_rate = audio_processing_
- ? blink::kAudioProcessingSampleRate
+ ?
+#if defined(IS_CHROMECAST)
+ std::min(blink::kAudioProcessingSampleRate,
+ input_format.sample_rate())
+#else
+ blink::kAudioProcessingSampleRate
+#endif // defined(IS_CHROMECAST)
: input_format.sample_rate();
media::ChannelLayout output_channel_layout = audio_processing_ ?
media::GuessChannelLayout(kAudioProcessingNumberOfChannels) :
@@ -770,19 +767,13 @@ int MediaStreamAudioProcessor::ProcessData(const float* const* process_ptrs,
ap->set_stream_delay_ms(total_delay_ms);
DCHECK_LE(volume, WebRtcAudioDeviceImpl::kMaxVolumeLevel);
- webrtc::GainControl* agc = ap->gain_control();
- int err = agc->set_stream_analog_level(volume);
- DCHECK_EQ(err, 0) << "set_stream_analog_level() error: " << err;
-
+ ap->set_stream_analog_level(volume);
ap->set_stream_key_pressed(key_pressed);
- err = ap->ProcessStream(process_ptrs,
- process_frames,
- input_format_.sample_rate(),
- MapLayout(input_format_.channel_layout()),
- output_format_.sample_rate(),
- MapLayout(output_format_.channel_layout()),
- output_ptrs);
+ int err = ap->ProcessStream(
+ process_ptrs, process_frames, input_format_.sample_rate(),
+ MapLayout(input_format_.channel_layout()), output_format_.sample_rate(),
+ MapLayout(output_format_.channel_layout()), output_ptrs);
DCHECK_EQ(err, 0) << "ProcessStream() error: " << err;
if (typing_detector_) {
@@ -801,8 +792,8 @@ int MediaStreamAudioProcessor::ProcessData(const float* const* process_ptrs,
rtc::scoped_refptr<MediaStreamAudioProcessor>(this)));
// Return 0 if the volume hasn't been changed, and otherwise the new volume.
- return (agc->stream_analog_level() == volume) ?
- 0 : agc->stream_analog_level();
+ const int recommended_volume = ap->recommended_stream_analog_level();
+ return (recommended_volume == volume) ? 0 : recommended_volume;
}
void MediaStreamAudioProcessor::UpdateAecStats() {
diff --git a/chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc b/chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc
index d4bd6299249..7765a57a1c5 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc
@@ -157,25 +157,19 @@ class MediaStreamAudioProcessorTest : public ::testing::Test {
const webrtc::AudioProcessing::Config config =
audio_processing->GetConfig();
EXPECT_TRUE(config.echo_canceller.enabled);
+ EXPECT_TRUE(config.gain_controller1.enabled);
+ EXPECT_TRUE(config.high_pass_filter.enabled);
+ EXPECT_TRUE(config.noise_suppression.enabled);
+ EXPECT_EQ(config.noise_suppression.level, config.noise_suppression.kHigh);
+ EXPECT_FALSE(config.voice_detection.enabled);
#if defined(OS_ANDROID)
EXPECT_TRUE(config.echo_canceller.mobile_mode);
- EXPECT_FALSE(config.voice_detection.enabled);
+ EXPECT_EQ(config.gain_controller1.mode,
+ config.gain_controller1.kFixedDigital);
#else
EXPECT_FALSE(config.echo_canceller.mobile_mode);
- EXPECT_TRUE(config.voice_detection.enabled);
-#endif
- EXPECT_TRUE(config.high_pass_filter.enabled);
-
- EXPECT_TRUE(audio_processing->noise_suppression()->is_enabled());
- EXPECT_TRUE(audio_processing->noise_suppression()->level() ==
- webrtc::NoiseSuppression::kHigh);
- EXPECT_TRUE(audio_processing->gain_control()->is_enabled());
-#if defined(OS_ANDROID)
- EXPECT_TRUE(audio_processing->gain_control()->mode() ==
- webrtc::GainControl::kFixedDigital);
-#else
- EXPECT_TRUE(audio_processing->gain_control()->mode() ==
- webrtc::GainControl::kAdaptiveAnalog);
+ EXPECT_EQ(config.gain_controller1.mode,
+ config.gain_controller1.kAdaptiveAnalog);
#endif
}
@@ -246,8 +240,18 @@ TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestAllSampleRates) {
properties, webrtc_audio_device.get()));
EXPECT_TRUE(audio_processor->has_audio_processing());
- static const int kSupportedSampleRates[] =
- { 8000, 16000, 22050, 32000, 44100, 48000 };
+ static const int kSupportedSampleRates[] = {
+ 8000,
+ 16000,
+ 22050,
+ 32000,
+ 44100,
+ 48000
+#if defined(IS_CHROMECAST)
+ ,
+ 96000
+#endif // defined(IS_CHROMECAST)
+ };
for (size_t i = 0; i < base::size(kSupportedSampleRates); ++i) {
int buffer_size = kSupportedSampleRates[i] / 100;
media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
@@ -256,10 +260,15 @@ TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestAllSampleRates) {
audio_processor->OnCaptureFormatChanged(params);
VerifyDefaultComponents(audio_processor.get());
- ProcessDataAndVerifyFormat(audio_processor.get(),
- blink::kAudioProcessingSampleRate,
+ int expected_sample_rate =
+#if defined(IS_CHROMECAST)
+ std::min(kSupportedSampleRates[i], blink::kAudioProcessingSampleRate);
+#else
+ blink::kAudioProcessingSampleRate;
+#endif // defined(IS_CHROMECAST)
+ ProcessDataAndVerifyFormat(audio_processor.get(), expected_sample_rate,
kAudioProcessingNumberOfChannel,
- blink::kAudioProcessingSampleRate / 100);
+ expected_sample_rate / 100);
}
// Stop |audio_processor| so that it removes itself from
diff --git a/chromium/content/renderer/media/stream/media_stream_center.cc b/chromium/content/renderer/media/stream/media_stream_center.cc
index 8622723bfdd..47b1d416144 100644
--- a/chromium/content/renderer/media/stream/media_stream_center.cc
+++ b/chromium/content/renderer/media/stream/media_stream_center.cc
@@ -218,19 +218,14 @@ void MediaStreamCenter::GetSourceSettings(
return;
media::AudioParameters audio_parameters = source->GetAudioParameters();
- settings.sample_rate = audio_parameters.sample_rate();
+ if (audio_parameters.IsValid()) {
+ settings.sample_rate = audio_parameters.sample_rate();
+ settings.channel_count = audio_parameters.channels();
+ settings.latency = audio_parameters.GetBufferDuration().InSecondsF();
+ }
// kSampleFormatS16 is the format used for all audio input streams.
settings.sample_size =
media::SampleFormatToBitsPerChannel(media::kSampleFormatS16);
- settings.channel_count = audio_parameters.channels();
- settings.latency = audio_parameters.GetBufferDuration().InSecondsF();
-
- ProcessedLocalAudioSource* const processed_source =
- ProcessedLocalAudioSource::From(source);
- settings.volume = processed_source
- ? static_cast<double>(processed_source->Volume()) /
- processed_source->MaxVolume()
- : 1.0;
}
} // namespace content
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.cc
index 8e0db1e6d3d..7906f9c3cea 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.cc
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.cc
@@ -384,7 +384,6 @@ class EchoCancellationContainer {
properties->goog_auto_gain_control &= default_audio_processing_value;
properties->goog_experimental_echo_cancellation &=
default_audio_processing_value;
- properties->goog_typing_noise_detection &= default_audio_processing_value;
properties->goog_noise_suppression &= default_audio_processing_value;
properties->goog_experimental_noise_suppression &=
default_audio_processing_value;
@@ -618,7 +617,6 @@ class ProcessingBasedContainer {
BoolSet(), /* goog_audio_mirroring_set */
BoolSet(), /* goog_auto_gain_control_set */
BoolSet(), /* goog_experimental_echo_cancellation_set */
- BoolSet(), /* goog_typing_noise_detection_set */
BoolSet(), /* goog_noise_suppression_set */
BoolSet(), /* goog_experimental_noise_suppression_set */
BoolSet(), /* goog_highpass_filter_set */
@@ -647,7 +645,6 @@ class ProcessingBasedContainer {
BoolSet(), /* goog_audio_mirroring_set */
BoolSet(), /* goog_auto_gain_control_set */
BoolSet(), /* goog_experimental_echo_cancellation_set */
- BoolSet(), /* goog_typing_noise_detection_set */
BoolSet(), /* goog_noise_suppression_set */
BoolSet(), /* goog_experimental_noise_suppression_set */
BoolSet(), /* goog_highpass_filter_set */
@@ -674,7 +671,6 @@ class ProcessingBasedContainer {
BoolSet(), /* goog_audio_mirroring_set */
BoolSet({false}), /* goog_auto_gain_control_set */
BoolSet({false}), /* goog_experimental_echo_cancellation_set */
- BoolSet({false}), /* goog_typing_noise_detection_set */
BoolSet({false}), /* goog_noise_suppression_set */
BoolSet({false}), /* goog_experimental_noise_suppression_set */
BoolSet({false}), /* goog_highpass_filter_set */
@@ -701,7 +697,6 @@ class ProcessingBasedContainer {
BoolSet({false}), /* goog_audio_mirroring_set */
BoolSet({false}), /* goog_auto_gain_control_set */
BoolSet({false}), /* goog_experimental_echo_cancellation_set */
- BoolSet({false}), /* goog_typing_noise_detection_set */
BoolSet({false}), /* goog_noise_suppression_set */
BoolSet({false}), /* goog_experimental_noise_suppression_set */
BoolSet({false}), /* goog_highpass_filter_set */
@@ -843,7 +838,6 @@ class ProcessingBasedContainer {
kGoogAudioMirroring,
kGoogAutoGainControl,
kGoogExperimentalEchoCancellation,
- kGoogTypingNoiseDetection,
kGoogNoiseSuppression,
kGoogExperimentalNoiseSuppression,
kGoogHighpassFilter,
@@ -870,9 +864,6 @@ class ProcessingBasedContainer {
{kGoogExperimentalEchoCancellation,
&ConstraintSet::goog_experimental_echo_cancellation,
&AudioProcessingProperties::goog_experimental_echo_cancellation},
- {kGoogTypingNoiseDetection,
- &ConstraintSet::goog_typing_noise_detection,
- &AudioProcessingProperties::goog_typing_noise_detection},
{kGoogNoiseSuppression, &ConstraintSet::goog_noise_suppression,
&AudioProcessingProperties::goog_noise_suppression},
{kGoogExperimentalNoiseSuppression,
@@ -896,7 +887,6 @@ class ProcessingBasedContainer {
BoolSet goog_audio_mirroring_set,
BoolSet goog_auto_gain_control_set,
BoolSet goog_experimental_echo_cancellation_set,
- BoolSet goog_typing_noise_detection_set,
BoolSet goog_noise_suppression_set,
BoolSet goog_experimental_noise_suppression_set,
BoolSet goog_highpass_filter_set,
@@ -931,8 +921,6 @@ class ProcessingBasedContainer {
BooleanContainer(goog_auto_gain_control_set);
boolean_containers_[kGoogExperimentalEchoCancellation] =
BooleanContainer(goog_experimental_echo_cancellation_set);
- boolean_containers_[kGoogTypingNoiseDetection] =
- BooleanContainer(goog_typing_noise_detection_set);
boolean_containers_[kGoogNoiseSuppression] =
BooleanContainer(goog_noise_suppression_set);
boolean_containers_[kGoogExperimentalNoiseSuppression] =
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h
index 62de3d73063..40e99547f74 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h
@@ -144,8 +144,6 @@ using AudioDeviceCaptureCapabilities =
// Moreover, the echo_cancellation constraint influences most other
// audio-processing properties for which no explicit value is provided in
// their corresponding constraints.
-// TODO(guidou): Add support for other standard constraints such as sampleRate,
-// channelCount and groupId. https://crbug.com/731170
CONTENT_EXPORT blink::AudioCaptureSettings SelectSettingsAudioCapture(
const AudioDeviceCaptureCapabilities& capabilities,
const blink::WebMediaConstraints& constraints,
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc
index c7dd87f25ce..d2ac608ac99 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc
@@ -116,8 +116,7 @@ class MediaStreamConstraintsUtilAudioTestBase {
device.input.set_effects(effects);
return std::make_unique<ProcessedLocalAudioSource>(
- -1, device, disable_local_echo, properties,
- blink::WebPlatformMediaStreamSource::ConstraintsCallback(),
+ -1, device, disable_local_echo, properties, base::NullCallback(),
&pc_factory_, blink::scheduler::GetSingleThreadTaskRunnerForTesting());
}
@@ -202,10 +201,6 @@ class MediaStreamConstraintsUtilAudioTestBase {
CheckGoogExperimentalEchoCancellationDefault(properties, true);
}
if (!Contains(exclude_audio_properties,
- &AudioProcessingProperties::goog_typing_noise_detection)) {
- EXPECT_TRUE(properties.goog_typing_noise_detection);
- }
- if (!Contains(exclude_audio_properties,
&AudioProcessingProperties::goog_noise_suppression)) {
EXPECT_TRUE(properties.goog_noise_suppression);
}
@@ -254,10 +249,6 @@ class MediaStreamConstraintsUtilAudioTestBase {
EXPECT_FALSE(properties.goog_experimental_echo_cancellation);
}
if (!Contains(exclude_audio_properties,
- &AudioProcessingProperties::goog_typing_noise_detection)) {
- EXPECT_FALSE(properties.goog_typing_noise_detection);
- }
- if (!Contains(exclude_audio_properties,
&AudioProcessingProperties::goog_noise_suppression)) {
EXPECT_FALSE(properties.goog_noise_suppression);
}
@@ -349,8 +340,6 @@ class MediaStreamConstraintsUtilAudioTestBase {
CheckGoogExperimentalEchoCancellationDefault(
properties, enable_webrtc_audio_processing);
EXPECT_EQ(enable_webrtc_audio_processing,
- properties.goog_typing_noise_detection);
- EXPECT_EQ(enable_webrtc_audio_processing,
properties.goog_noise_suppression);
EXPECT_EQ(enable_webrtc_audio_processing,
properties.goog_experimental_noise_suppression);
@@ -383,7 +372,6 @@ class MediaStreamConstraintsUtilAudioTestBase {
properties.echo_cancellation_type);
EXPECT_TRUE(properties.goog_auto_gain_control);
CheckGoogExperimentalEchoCancellationDefault(properties, true);
- EXPECT_TRUE(properties.goog_typing_noise_detection);
EXPECT_TRUE(properties.goog_noise_suppression);
EXPECT_TRUE(properties.goog_experimental_noise_suppression);
EXPECT_TRUE(properties.goog_highpass_filter);
@@ -631,7 +619,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SingleBoolConstraint) {
&AudioProcessingProperties::goog_audio_mirroring,
&AudioProcessingProperties::goog_auto_gain_control,
&AudioProcessingProperties::goog_experimental_echo_cancellation,
- &AudioProcessingProperties::goog_typing_noise_detection,
&AudioProcessingProperties::goog_noise_suppression,
&AudioProcessingProperties::goog_experimental_noise_suppression,
&AudioProcessingProperties::goog_highpass_filter,
@@ -644,7 +631,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SingleBoolConstraint) {
&blink::WebMediaTrackConstraintSet::goog_auto_gain_control,
&blink::WebMediaTrackConstraintSet::
goog_experimental_echo_cancellation,
- &blink::WebMediaTrackConstraintSet::goog_typing_noise_detection,
&blink::WebMediaTrackConstraintSet::goog_noise_suppression,
&blink::WebMediaTrackConstraintSet::
goog_experimental_noise_suppression,
@@ -1306,8 +1292,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithWebRtc) {
CheckGoogExperimentalEchoCancellationDefault(
properties, enable_webrtc_audio_processing);
EXPECT_EQ(enable_webrtc_audio_processing,
- properties.goog_typing_noise_detection);
- EXPECT_EQ(enable_webrtc_audio_processing,
properties.goog_noise_suppression);
EXPECT_EQ(enable_webrtc_audio_processing,
properties.goog_experimental_noise_suppression);
@@ -1370,7 +1354,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithSystem) {
properties.echo_cancellation_type);
EXPECT_EQ(value, properties.goog_auto_gain_control);
CheckGoogExperimentalEchoCancellationDefault(properties, value);
- EXPECT_EQ(value, properties.goog_typing_noise_detection);
EXPECT_EQ(value, properties.goog_noise_suppression);
EXPECT_EQ(value, properties.goog_experimental_noise_suppression);
EXPECT_EQ(value, properties.goog_highpass_filter);
@@ -1622,7 +1605,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest,
}
EXPECT_EQ(ec_value, properties.goog_auto_gain_control);
CheckGoogExperimentalEchoCancellationDefault(properties, ec_value);
- EXPECT_EQ(ec_value, properties.goog_typing_noise_detection);
EXPECT_EQ(ec_value, properties.goog_noise_suppression);
EXPECT_EQ(ec_value, properties.goog_experimental_noise_suppression);
EXPECT_EQ(ec_value, properties.goog_highpass_filter);
@@ -1680,7 +1662,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest,
&AudioProcessingProperties::goog_audio_mirroring,
&AudioProcessingProperties::goog_auto_gain_control,
&AudioProcessingProperties::goog_experimental_echo_cancellation,
- &AudioProcessingProperties::goog_typing_noise_detection,
&AudioProcessingProperties::goog_noise_suppression,
&AudioProcessingProperties::goog_experimental_noise_suppression,
&AudioProcessingProperties::goog_highpass_filter,
@@ -1693,7 +1674,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest,
&blink::WebMediaTrackConstraintSet::goog_auto_gain_control,
&blink::WebMediaTrackConstraintSet::
goog_experimental_echo_cancellation,
- &blink::WebMediaTrackConstraintSet::goog_typing_noise_detection,
&blink::WebMediaTrackConstraintSet::goog_noise_suppression,
&blink::WebMediaTrackConstraintSet::
goog_experimental_noise_suppression,
@@ -1907,8 +1887,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) {
properties.goog_auto_gain_control = !properties.goog_auto_gain_control;
properties.goog_experimental_echo_cancellation =
!properties.goog_experimental_echo_cancellation;
- properties.goog_typing_noise_detection =
- !properties.goog_typing_noise_detection;
properties.goog_noise_suppression = !properties.goog_noise_suppression;
properties.goog_experimental_noise_suppression =
!properties.goog_experimental_noise_suppression;
@@ -1928,7 +1906,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) {
&blink::WebMediaTrackConstraintSet::goog_auto_gain_control,
&blink::WebMediaTrackConstraintSet::
goog_experimental_echo_cancellation,
- &blink::WebMediaTrackConstraintSet::goog_typing_noise_detection,
&blink::WebMediaTrackConstraintSet::goog_noise_suppression,
&blink::WebMediaTrackConstraintSet::
goog_experimental_noise_suppression,
@@ -1940,7 +1917,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) {
&AudioProcessingProperties::goog_audio_mirroring,
&AudioProcessingProperties::goog_auto_gain_control,
&AudioProcessingProperties::goog_experimental_echo_cancellation,
- &AudioProcessingProperties::goog_typing_noise_detection,
&AudioProcessingProperties::goog_noise_suppression,
&AudioProcessingProperties::goog_experimental_noise_suppression,
&AudioProcessingProperties::goog_highpass_filter,
diff --git a/chromium/content/renderer/media/stream/media_stream_device_observer.cc b/chromium/content/renderer/media/stream/media_stream_device_observer.cc
index a251a388c4f..8509de6231a 100644
--- a/chromium/content/renderer/media/stream/media_stream_device_observer.cc
+++ b/chromium/content/renderer/media/stream/media_stream_device_observer.cc
@@ -45,7 +45,7 @@ struct MediaStreamDeviceObserver::Stream {
MediaStreamDeviceObserver::MediaStreamDeviceObserver(RenderFrame* render_frame)
: RenderFrameObserver(render_frame), binding_(this) {
- registry_.AddInterface(base::Bind(
+ registry_.AddInterface(base::BindRepeating(
&MediaStreamDeviceObserver::BindMediaStreamDeviceObserverRequest,
base::Unretained(this)));
}
diff --git a/chromium/content/renderer/media/stream/media_stream_device_observer_unittest.cc b/chromium/content/renderer/media/stream/media_stream_device_observer_unittest.cc
index 99caed59012..29788ba86f0 100644
--- a/chromium/content/renderer/media/stream/media_stream_device_observer_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_device_observer_unittest.cc
@@ -24,7 +24,7 @@ class MediaStreamDeviceObserverTest : public ::testing::Test {
MediaStreamDeviceObserverTest()
: observer_(std::make_unique<MediaStreamDeviceObserver>(nullptr)) {}
- void OnDeviceOpened(base::Closure quit_closure,
+ void OnDeviceOpened(base::OnceClosure quit_closure,
bool success,
const std::string& label,
const blink::MediaStreamDevice& device) {
diff --git a/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc b/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc
index a6f570881ac..befbb2fe025 100644
--- a/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc
+++ b/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc
@@ -53,7 +53,6 @@ MediaStreamRendererFactoryImpl::~MediaStreamRendererFactoryImpl() {
scoped_refptr<blink::WebMediaStreamVideoRenderer>
MediaStreamRendererFactoryImpl::GetVideoRenderer(
const blink::WebMediaStream& web_stream,
- const base::Closure& error_cb,
const blink::WebMediaStreamVideoRenderer::RepaintCB& repaint_cb,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner) {
@@ -69,7 +68,7 @@ MediaStreamRendererFactoryImpl::GetVideoRenderer(
return nullptr;
}
- return new MediaStreamVideoRendererSink(video_tracks[0], error_cb, repaint_cb,
+ return new MediaStreamVideoRendererSink(video_tracks[0], repaint_cb,
std::move(io_task_runner),
std::move(main_render_task_runner));
}
diff --git a/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.h b/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.h
index f4da468d05e..b859759f10a 100644
--- a/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.h
+++ b/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.h
@@ -20,7 +20,6 @@ class MediaStreamRendererFactoryImpl
scoped_refptr<blink::WebMediaStreamVideoRenderer> GetVideoRenderer(
const blink::WebMediaStream& web_stream,
- const base::Closure& error_cb,
const blink::WebMediaStreamVideoRenderer::RepaintCB& repaint_cb,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner)
diff --git a/chromium/content/renderer/media/stream/media_stream_video_renderer_sink.cc b/chromium/content/renderer/media/stream/media_stream_video_renderer_sink.cc
index 548793b930f..f474f66f443 100644
--- a/chromium/content/renderer/media/stream/media_stream_video_renderer_sink.cc
+++ b/chromium/content/renderer/media/stream/media_stream_video_renderer_sink.cc
@@ -50,7 +50,7 @@ class MediaStreamVideoRendererSink::FrameDeliverer {
DCHECK(state_ == STARTED || state_ == PAUSED) << state_;
}
- void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame,
+ void OnVideoFrame(scoped_refptr<media::VideoFrame> frame,
base::TimeTicks /*current_time*/) {
DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
DCHECK(frame);
@@ -73,7 +73,7 @@ class MediaStreamVideoRendererSink::FrameDeliverer {
}
frame_size_ = frame->natural_size();
- repaint_cb_.Run(frame);
+ repaint_cb_.Run(std::move(frame));
}
void RenderEndOfStream() {
@@ -136,12 +136,10 @@ class MediaStreamVideoRendererSink::FrameDeliverer {
MediaStreamVideoRendererSink::MediaStreamVideoRendererSink(
const blink::WebMediaStreamTrack& video_track,
- const base::Closure& error_cb,
const RepaintCB& repaint_cb,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner)
- : error_cb_(error_cb),
- repaint_cb_(repaint_cb),
+ : repaint_cb_(repaint_cb),
video_track_(video_track),
io_task_runner_(std::move(io_task_runner)),
main_render_task_runner_(std::move(main_render_task_runner)),
diff --git a/chromium/content/renderer/media/stream/media_stream_video_renderer_sink.h b/chromium/content/renderer/media/stream/media_stream_video_renderer_sink.h
index 5d5c752e2c8..f417cff9b73 100644
--- a/chromium/content/renderer/media/stream/media_stream_video_renderer_sink.h
+++ b/chromium/content/renderer/media/stream/media_stream_video_renderer_sink.h
@@ -40,7 +40,6 @@ class CONTENT_EXPORT MediaStreamVideoRendererSink
public:
MediaStreamVideoRendererSink(
const blink::WebMediaStreamTrack& video_track,
- const base::Closure& error_cb,
const blink::WebMediaStreamVideoRenderer::RepaintCB& repaint_cb,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner);
@@ -70,7 +69,6 @@ class CONTENT_EXPORT MediaStreamVideoRendererSink
// Helper method used for testing.
State GetStateForTesting();
- const base::Closure error_cb_;
const RepaintCB repaint_cb_;
const blink::WebMediaStreamTrack video_track_;
diff --git a/chromium/content/renderer/media/stream/media_stream_video_renderer_sink_unittest.cc b/chromium/content/renderer/media/stream/media_stream_video_renderer_sink_unittest.cc
index c5805d6026c..e99f51f6d3e 100644
--- a/chromium/content/renderer/media/stream/media_stream_video_renderer_sink_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_video_renderer_sink_unittest.cc
@@ -53,8 +53,6 @@ class MediaStreamVideoRendererSinkTest : public testing::Test {
media_stream_video_renderer_sink_ = new MediaStreamVideoRendererSink(
blink_track_,
- base::Bind(&MediaStreamVideoRendererSinkTest::ErrorCallback,
- base::Unretained(this)),
base::Bind(&MediaStreamVideoRendererSinkTest::RepaintCallback,
base::Unretained(this)),
child_process_->io_task_runner(),
@@ -75,7 +73,6 @@ class MediaStreamVideoRendererSinkTest : public testing::Test {
}
MOCK_METHOD1(RepaintCallback, void(scoped_refptr<media::VideoFrame>));
- MOCK_METHOD0(ErrorCallback, void(void));
bool IsInStartedState() const {
RunIOUntilIdle();
@@ -165,8 +162,6 @@ class MediaStreamVideoRendererSinkTransparencyTest
MediaStreamVideoRendererSinkTransparencyTest() {
media_stream_video_renderer_sink_ = new MediaStreamVideoRendererSink(
blink_track_,
- base::Bind(&MediaStreamVideoRendererSinkTest::ErrorCallback,
- base::Unretained(this)),
base::Bind(&MediaStreamVideoRendererSinkTransparencyTest::
VerifyTransparentFrame,
base::Unretained(this)),
diff --git a/chromium/content/renderer/media/stream/media_stream_video_source_unittest.cc b/chromium/content/renderer/media/stream/media_stream_video_source_unittest.cc
index 700a34b53d4..d981d7ccf98 100644
--- a/chromium/content/renderer/media/stream/media_stream_video_source_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_video_source_unittest.cc
@@ -30,10 +30,6 @@ using ::testing::SaveArg;
namespace content {
-ACTION_P(RunClosure, closure) {
- closure.Run();
-}
-
class MediaStreamVideoSourceTest : public ::testing::Test {
public:
MediaStreamVideoSourceTest()
@@ -159,9 +155,10 @@ class MediaStreamVideoSourceTest : public ::testing::Test {
int height,
MockMediaStreamVideoSink* sink) {
base::RunLoop run_loop;
- base::Closure quit_closure = run_loop.QuitClosure();
- EXPECT_CALL(*sink, OnVideoFrame())
- .WillOnce(RunClosure(std::move(quit_closure)));
+ base::OnceClosure quit_closure = run_loop.QuitClosure();
+ EXPECT_CALL(*sink, OnVideoFrame()).WillOnce([&]() {
+ std::move(quit_closure).Run();
+ });
scoped_refptr<media::VideoFrame> frame =
media::VideoFrame::CreateBlackFrame(gfx::Size(width, height));
mock_source()->DeliverVideoFrame(frame);
@@ -181,10 +178,11 @@ class MediaStreamVideoSourceTest : public ::testing::Test {
MockMediaStreamVideoSink* sink1,
MockMediaStreamVideoSink* sink2) {
base::RunLoop run_loop;
- base::Closure quit_closure = run_loop.QuitClosure();
+ base::OnceClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*sink1, OnVideoFrame());
- EXPECT_CALL(*sink2, OnVideoFrame())
- .WillOnce(RunClosure(std::move(quit_closure)));
+ EXPECT_CALL(*sink2, OnVideoFrame()).WillOnce([&]() {
+ std::move(quit_closure).Run();
+ });
scoped_refptr<media::VideoFrame> frame =
media::VideoFrame::CreateBlackFrame(gfx::Size(width, height));
mock_source()->DeliverVideoFrame(frame);
@@ -420,11 +418,11 @@ TEST_F(MediaStreamVideoSourceTest, MutedSource) {
blink::WebMediaStreamSource::kReadyStateLive);
base::RunLoop run_loop;
- base::Closure quit_closure = run_loop.QuitClosure();
+ base::OnceClosure quit_closure = run_loop.QuitClosure();
bool muted_state = false;
EXPECT_CALL(*mock_source(), DoSetMutedState(_))
- .WillOnce(
- DoAll(SaveArg<0>(&muted_state), RunClosure(std::move(quit_closure))));
+ .WillOnce(DoAll(SaveArg<0>(&muted_state),
+ [&](auto) { std::move(quit_closure).Run(); }));
run_loop.Run();
EXPECT_EQ(muted_state, true);
@@ -432,10 +430,10 @@ TEST_F(MediaStreamVideoSourceTest, MutedSource) {
blink::WebMediaStreamSource::kReadyStateMuted);
base::RunLoop run_loop2;
- base::Closure quit_closure2 = run_loop2.QuitClosure();
+ base::OnceClosure quit_closure2 = run_loop2.QuitClosure();
EXPECT_CALL(*mock_source(), DoSetMutedState(_))
.WillOnce(DoAll(SaveArg<0>(&muted_state),
- RunClosure(std::move(quit_closure2))));
+ [&](auto) { std::move(quit_closure2).Run(); }));
DeliverVideoFrameAndWaitForRenderer(640, 480, &sink);
run_loop2.Run();
diff --git a/chromium/content/renderer/media/stream/media_stream_video_track_unittest.cc b/chromium/content/renderer/media/stream/media_stream_video_track_unittest.cc
index f84970ae37d..e2a58cba055 100644
--- a/chromium/content/renderer/media/stream/media_stream_video_track_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_video_track_unittest.cc
@@ -49,13 +49,13 @@ class MediaStreamVideoTrackTest : public ::testing::Test {
}
void DeliverVideoFrameAndWaitForRenderer(
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
MockMediaStreamVideoSink* sink) {
base::RunLoop run_loop;
base::Closure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*sink, OnVideoFrame())
.WillOnce(RunClosure(std::move(quit_closure)));
- mock_source()->DeliverVideoFrame(frame);
+ mock_source()->DeliverVideoFrame(std::move(frame));
run_loop.Run();
}
@@ -170,26 +170,23 @@ TEST_F(MediaStreamVideoTrackTest, AddAndRemoveSink) {
class CheckThreadHelper {
public:
- CheckThreadHelper(base::Closure callback, bool* correct)
- : callback_(callback),
- correct_(correct) {
- }
+ CheckThreadHelper(base::OnceClosure callback, bool* correct)
+ : callback_(std::move(callback)), correct_(correct) {}
~CheckThreadHelper() {
*correct_ = thread_checker_.CalledOnValidThread();
- callback_.Run();
+ std::move(callback_).Run();
}
private:
- base::Closure callback_;
+ base::OnceClosure callback_;
bool* correct_;
base::ThreadCheckerImpl thread_checker_;
};
-void CheckThreadVideoFrameReceiver(
- CheckThreadHelper* helper,
- const scoped_refptr<media::VideoFrame>& frame,
- base::TimeTicks estimated_capture_time) {
+void CheckThreadVideoFrameReceiver(CheckThreadHelper* helper,
+ scoped_refptr<media::VideoFrame> frame,
+ base::TimeTicks estimated_capture_time) {
// Do nothing.
}
@@ -361,16 +358,14 @@ TEST_F(MediaStreamVideoTrackTest, DeliverFramesAndGetSettings) {
blink::MediaStreamVideoTrack::GetVideoTrack(track);
blink::WebMediaStreamTrack::Settings settings;
- const scoped_refptr<media::VideoFrame>& frame1 =
- media::VideoFrame::CreateBlackFrame(gfx::Size(600, 400));
- DeliverVideoFrameAndWaitForRenderer(frame1, &sink);
+ auto frame1 = media::VideoFrame::CreateBlackFrame(gfx::Size(600, 400));
+ DeliverVideoFrameAndWaitForRenderer(std::move(frame1), &sink);
native_track->GetSettings(settings);
EXPECT_EQ(600, settings.width);
EXPECT_EQ(400, settings.height);
- const scoped_refptr<media::VideoFrame>& frame2 =
- media::VideoFrame::CreateBlackFrame(gfx::Size(200, 300));
- DeliverVideoFrameAndWaitForRenderer(frame2, &sink);
+ auto frame2 = media::VideoFrame::CreateBlackFrame(gfx::Size(200, 300));
+ DeliverVideoFrameAndWaitForRenderer(std::move(frame2), &sink);
native_track->GetSettings(settings);
EXPECT_EQ(200, settings.width);
EXPECT_EQ(300, settings.height);
diff --git a/chromium/content/renderer/media/stream/mock_constraint_factory.cc b/chromium/content/renderer/media/stream/mock_constraint_factory.cc
index 98d6c5ac32c..8260245243a 100644
--- a/chromium/content/renderer/media/stream/mock_constraint_factory.cc
+++ b/chromium/content/renderer/media/stream/mock_constraint_factory.cc
@@ -36,7 +36,6 @@ void MockConstraintFactory::DisableDefaultAudioConstraints() {
basic_.goog_noise_suppression.SetExact(false);
basic_.goog_noise_suppression.SetExact(false);
basic_.goog_highpass_filter.SetExact(false);
- basic_.goog_typing_noise_detection.SetExact(false);
basic_.goog_experimental_noise_suppression.SetExact(false);
}
diff --git a/chromium/content/renderer/media/stream/mock_media_stream_video_sink.cc b/chromium/content/renderer/media/stream/mock_media_stream_video_sink.cc
index 0646cbf618a..70d4f72a05e 100644
--- a/chromium/content/renderer/media/stream/mock_media_stream_video_sink.cc
+++ b/chromium/content/renderer/media/stream/mock_media_stream_video_sink.cc
@@ -28,12 +28,12 @@ MockMediaStreamVideoSink::GetDeliverFrameCB() {
}
void MockMediaStreamVideoSink::DeliverVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
base::TimeTicks estimated_capture_time) {
- last_frame_ = frame;
++number_of_frames_;
format_ = frame->format();
frame_size_ = frame->natural_size();
+ last_frame_ = std::move(frame);
OnVideoFrame();
}
diff --git a/chromium/content/renderer/media/stream/mock_media_stream_video_sink.h b/chromium/content/renderer/media/stream/mock_media_stream_video_sink.h
index 5f1b8a1b338..5d336b2b123 100644
--- a/chromium/content/renderer/media/stream/mock_media_stream_video_sink.h
+++ b/chromium/content/renderer/media/stream/mock_media_stream_video_sink.h
@@ -38,7 +38,7 @@ class MockMediaStreamVideoSink : public blink::MediaStreamVideoSink {
blink::WebMediaStreamSource::ReadyState state) override;
void OnEnabledChanged(bool enabled) override;
- // Triggered when OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame)
+ // Triggered when OnVideoFrame(scoped_refptr<media::VideoFrame> frame)
// is called.
MOCK_METHOD0(OnVideoFrame, void());
@@ -53,7 +53,7 @@ class MockMediaStreamVideoSink : public blink::MediaStreamVideoSink {
blink::WebMediaStreamSource::ReadyState state() const { return state_; }
private:
- void DeliverVideoFrame(const scoped_refptr<media::VideoFrame>& frame,
+ void DeliverVideoFrame(scoped_refptr<media::VideoFrame> frame,
base::TimeTicks estimated_capture_time);
int number_of_frames_;
diff --git a/chromium/content/renderer/media/stream/mock_media_stream_video_source.cc b/chromium/content/renderer/media/stream/mock_media_stream_video_source.cc
index 9e567688bb8..09ab6a25cbb 100644
--- a/chromium/content/renderer/media/stream/mock_media_stream_video_source.cc
+++ b/chromium/content/renderer/media/stream/mock_media_stream_video_source.cc
@@ -90,11 +90,12 @@ MockMediaStreamVideoSource::GetCurrentCaptureParams() const {
}
void MockMediaStreamVideoSource::DeliverVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
+ scoped_refptr<media::VideoFrame> frame) {
DCHECK(!is_stopped_for_restart_);
DCHECK(!frame_callback_.is_null());
io_task_runner()->PostTask(
- FROM_HERE, base::BindOnce(frame_callback_, frame, base::TimeTicks()));
+ FROM_HERE,
+ base::BindOnce(frame_callback_, std::move(frame), base::TimeTicks()));
}
void MockMediaStreamVideoSource::StopSourceForRestartImpl() {
diff --git a/chromium/content/renderer/media/stream/mock_media_stream_video_source.h b/chromium/content/renderer/media/stream/mock_media_stream_video_source.h
index 47868e79e2a..99bb3f6298f 100644
--- a/chromium/content/renderer/media/stream/mock_media_stream_video_source.h
+++ b/chromium/content/renderer/media/stream/mock_media_stream_video_source.h
@@ -35,7 +35,7 @@ class MockMediaStreamVideoSource : public blink::MediaStreamVideoSource {
// Delivers |frame| to all registered tracks on the IO thread. Its up to the
// call to make sure MockMediaStreamVideoSource is not destroyed before the
// frame has been delivered.
- void DeliverVideoFrame(const scoped_refptr<media::VideoFrame>& frame);
+ void DeliverVideoFrame(scoped_refptr<media::VideoFrame> frame);
const media::VideoCaptureFormat& start_format() const { return format_; }
int max_requested_height() const { return max_requested_height_; }
diff --git a/chromium/content/renderer/media/stream/processed_local_audio_source.cc b/chromium/content/renderer/media/stream/processed_local_audio_source.cc
index 8aa5d9c1151..d87321d74db 100644
--- a/chromium/content/renderer/media/stream/processed_local_audio_source.cc
+++ b/chromium/content/renderer/media/stream/processed_local_audio_source.cc
@@ -92,7 +92,7 @@ ProcessedLocalAudioSource::ProcessedLocalAudioSource(
const blink::MediaStreamDevice& device,
bool disable_local_echo,
const blink::AudioProcessingProperties& audio_processing_properties,
- const ConstraintsCallback& started_callback,
+ ConstraintsOnceCallback started_callback,
PeerConnectionDependencyFactory* factory,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: blink::MediaStreamAudioSource(std::move(task_runner),
@@ -101,7 +101,7 @@ ProcessedLocalAudioSource::ProcessedLocalAudioSource(
consumer_render_frame_id_(consumer_render_frame_id),
pc_factory_(factory),
audio_processing_properties_(audio_processing_properties),
- started_callback_(started_callback),
+ started_callback_(std::move(started_callback)),
volume_(0),
allow_invalid_render_frame_id_for_testing_(false),
weak_factory_(this) {
@@ -357,7 +357,7 @@ int ProcessedLocalAudioSource::MaxVolume() const {
}
void ProcessedLocalAudioSource::OnCaptureStarted() {
- started_callback_.Run(this, blink::MEDIA_DEVICE_OK, "");
+ std::move(started_callback_).Run(this, blink::MEDIA_DEVICE_OK, "");
}
void ProcessedLocalAudioSource::Capture(const media::AudioBus* audio_bus,
diff --git a/chromium/content/renderer/media/stream/processed_local_audio_source.h b/chromium/content/renderer/media/stream/processed_local_audio_source.h
index e7c05c53ed9..7f0e908bce7 100644
--- a/chromium/content/renderer/media/stream/processed_local_audio_source.h
+++ b/chromium/content/renderer/media/stream/processed_local_audio_source.h
@@ -46,7 +46,7 @@ class CONTENT_EXPORT ProcessedLocalAudioSource final
const blink::MediaStreamDevice& device,
bool disable_local_echo,
const blink::AudioProcessingProperties& audio_processing_properties,
- const ConstraintsCallback& started_callback,
+ ConstraintsOnceCallback started_callback,
PeerConnectionDependencyFactory* factory,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
@@ -133,7 +133,7 @@ class CONTENT_EXPORT ProcessedLocalAudioSource final
blink::AudioProcessingProperties audio_processing_properties_;
// Callback that's called when the audio source has been initialized.
- ConstraintsCallback started_callback_;
+ ConstraintsOnceCallback started_callback_;
// At most one of |audio_processor_| and |audio_processor_proxy_| can be set.
diff --git a/chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc b/chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc
index 5158a922adf..ae54fb42212 100644
--- a/chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc
+++ b/chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc
@@ -106,9 +106,7 @@ class ProcessedLocalAudioSourceTest : public testing::Test {
"mock_audio_device_id",
"Mock audio device", kSampleRate,
kChannelLayout, kRequestedBufferSize),
- false /* disable_local_echo */, properties,
- base::Bind(&ProcessedLocalAudioSourceTest::OnAudioSourceStarted,
- base::Unretained(this)),
+ false /* disable_local_echo */, properties, base::DoNothing(),
&mock_dependency_factory_,
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
source->SetAllowInvalidRenderFrameIdForTesting(true);
@@ -145,10 +143,6 @@ class ProcessedLocalAudioSourceTest : public testing::Test {
return blink_audio_track_;
}
- void OnAudioSourceStarted(blink::WebPlatformMediaStreamSource* source,
- blink::MediaStreamRequestResult result,
- const blink::WebString& result_name) {}
-
private:
base::test::ScopedTaskEnvironment
task_environment_; // Needed for MSAudioProcessor.
diff --git a/chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc b/chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc
index 4a027c0b92a..a76827d498b 100644
--- a/chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc
+++ b/chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc
@@ -358,7 +358,7 @@ class UserMediaProcessorUnderTest : public UserMediaProcessor {
std::unique_ptr<blink::MediaStreamAudioSource> CreateAudioSource(
const blink::MediaStreamDevice& device,
- const blink::WebPlatformMediaStreamSource::ConstraintsCallback&
+ blink::WebPlatformMediaStreamSource::ConstraintsRepeatingCallback
source_ready) override {
std::unique_ptr<blink::MediaStreamAudioSource> source;
if (create_source_that_fails_) {
@@ -389,7 +389,7 @@ class UserMediaProcessorUnderTest : public UserMediaProcessor {
blink::scheduler::GetSingleThreadTaskRunnerForTesting()->PostTask(
FROM_HERE,
base::BindOnce(&UserMediaProcessorUnderTest::SignalSourceReady,
- source_ready, source.get()));
+ std::move(source_ready), source.get()));
}
return source;
@@ -413,10 +413,9 @@ class UserMediaProcessorUnderTest : public UserMediaProcessor {
private:
static void SignalSourceReady(
- const blink::WebPlatformMediaStreamSource::ConstraintsCallback&
- source_ready,
+ blink::WebPlatformMediaStreamSource::ConstraintsOnceCallback source_ready,
blink::WebPlatformMediaStreamSource* source) {
- source_ready.Run(source, blink::MEDIA_DEVICE_OK, "");
+ std::move(source_ready).Run(source, blink::MEDIA_DEVICE_OK, "");
}
PeerConnectionDependencyFactory* factory_;
@@ -917,7 +916,6 @@ TEST_F(UserMediaClientImplTest, DefaultConstraintsPropagate) {
EXPECT_EQ(
blink::AudioProcessingProperties().goog_experimental_echo_cancellation,
properties.goog_experimental_echo_cancellation);
- EXPECT_TRUE(properties.goog_typing_noise_detection);
EXPECT_TRUE(properties.goog_noise_suppression);
EXPECT_TRUE(properties.goog_experimental_noise_suppression);
EXPECT_TRUE(properties.goog_highpass_filter);
@@ -977,7 +975,6 @@ TEST_F(UserMediaClientImplTest, DefaultTabCapturePropagate) {
EXPECT_FALSE(properties.goog_audio_mirroring);
EXPECT_FALSE(properties.goog_auto_gain_control);
EXPECT_FALSE(properties.goog_experimental_echo_cancellation);
- EXPECT_FALSE(properties.goog_typing_noise_detection);
EXPECT_FALSE(properties.goog_noise_suppression);
EXPECT_FALSE(properties.goog_experimental_noise_suppression);
EXPECT_FALSE(properties.goog_highpass_filter);
@@ -1035,7 +1032,6 @@ TEST_F(UserMediaClientImplTest, DefaultDesktopCapturePropagate) {
EXPECT_FALSE(properties.goog_audio_mirroring);
EXPECT_FALSE(properties.goog_auto_gain_control);
EXPECT_FALSE(properties.goog_experimental_echo_cancellation);
- EXPECT_FALSE(properties.goog_typing_noise_detection);
EXPECT_FALSE(properties.goog_noise_suppression);
EXPECT_FALSE(properties.goog_experimental_noise_suppression);
EXPECT_FALSE(properties.goog_highpass_filter);
@@ -1071,7 +1067,6 @@ TEST_F(UserMediaClientImplTest, NonDefaultAudioConstraintsPropagate) {
factory.basic().render_to_associated_sink.SetExact(true);
factory.basic().echo_cancellation.SetExact(false);
factory.basic().goog_audio_mirroring.SetExact(true);
- factory.basic().goog_typing_noise_detection.SetExact(true);
blink::WebMediaConstraints audio_constraints =
factory.CreateWebMediaConstraints();
// Request contains only audio
@@ -1099,7 +1094,6 @@ TEST_F(UserMediaClientImplTest, NonDefaultAudioConstraintsPropagate) {
EXPECT_TRUE(properties.goog_audio_mirroring);
EXPECT_FALSE(properties.goog_auto_gain_control);
EXPECT_FALSE(properties.goog_experimental_echo_cancellation);
- EXPECT_TRUE(properties.goog_typing_noise_detection);
EXPECT_FALSE(properties.goog_noise_suppression);
EXPECT_FALSE(properties.goog_experimental_noise_suppression);
EXPECT_FALSE(properties.goog_highpass_filter);
diff --git a/chromium/content/renderer/media/stream/user_media_processor.cc b/chromium/content/renderer/media/stream/user_media_processor.cc
index accd1f9e8c7..fd70cdb2f3f 100644
--- a/chromium/content/renderer/media/stream/user_media_processor.cc
+++ b/chromium/content/renderer/media/stream/user_media_processor.cc
@@ -223,9 +223,9 @@ class UserMediaProcessor::RequestInfo
: public base::SupportsWeakPtr<RequestInfo> {
public:
using ResourcesReady =
- base::Callback<void(RequestInfo* request_info,
- MediaStreamRequestResult result,
- const blink::WebString& result_name)>;
+ base::OnceCallback<void(RequestInfo* request_info,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name)>;
enum class State {
NOT_SENT_FOR_GENERATION,
SENT_FOR_GENERATION,
@@ -241,7 +241,7 @@ class UserMediaProcessor::RequestInfo
// Triggers |callback| when all sources used in this request have either
// successfully started, or a source has failed to start.
- void CallbackOnTracksStarted(const ResourcesReady& callback);
+ void CallbackOnTracksStarted(ResourcesReady callback);
// Called when a local audio source has finished (or failed) initializing.
void OnAudioSourceStarted(blink::WebPlatformMediaStreamSource* source,
@@ -324,7 +324,7 @@ class UserMediaProcessor::RequestInfo
MediaStreamRequestResult result,
const blink::WebString& result_name);
- // Cheks if the sources for all tracks have been started and if so,
+ // Checks if the sources for all tracks have been started and if so,
// invoke the |ready_callback_|. Note that the caller should expect
// that |this| might be deleted when the function returns.
void CheckAllTracksStarted();
@@ -401,9 +401,9 @@ UserMediaProcessor::RequestInfo::CreateAndStartVideoTrack(
}
void UserMediaProcessor::RequestInfo::CallbackOnTracksStarted(
- const ResourcesReady& callback) {
+ ResourcesReady callback) {
DCHECK(ready_callback_.is_null());
- ready_callback_ = callback;
+ ready_callback_ = std::move(callback);
CheckAllTracksStarted();
}
@@ -427,8 +427,8 @@ void UserMediaProcessor::RequestInfo::OnTrackStarted(
}
void UserMediaProcessor::RequestInfo::CheckAllTracksStarted() {
- if (!ready_callback_.is_null() && sources_waiting_for_callback_.empty()) {
- ready_callback_.Run(this, request_result_, request_result_name_);
+ if (ready_callback_ && sources_waiting_for_callback_.empty()) {
+ std::move(ready_callback_).Run(this, request_result_, request_result_name_);
// NOTE: |this| might now be deleted.
}
}
@@ -828,8 +828,9 @@ void UserMediaProcessor::OnAudioSourceStartedOnAudioThread(
MediaStreamRequestResult result,
const blink::WebString& result_name) {
task_runner->PostTask(
- FROM_HERE, base::BindOnce(&UserMediaProcessor::OnAudioSourceStarted,
- weak_ptr, source, result, result_name));
+ FROM_HERE,
+ base::BindOnce(&UserMediaProcessor::OnAudioSourceStarted,
+ std::move(weak_ptr), source, result, result_name));
}
void UserMediaProcessor::OnAudioSourceStarted(
@@ -975,8 +976,8 @@ blink::WebMediaStreamSource UserMediaProcessor::InitializeAudioSourceObject(
// See OnAudioSourceStarted for more details.
pending_local_sources_.push_back(source);
- blink::WebPlatformMediaStreamSource::ConstraintsCallback source_ready =
- base::BindRepeating(
+ blink::WebPlatformMediaStreamSource::ConstraintsRepeatingCallback
+ source_ready = base::BindRepeating(
&UserMediaProcessor::OnAudioSourceStartedOnAudioThread, task_runner_,
weak_factory_.GetWeakPtr());
@@ -1032,7 +1033,7 @@ blink::WebMediaStreamSource UserMediaProcessor::InitializeAudioSourceObject(
std::unique_ptr<blink::MediaStreamAudioSource>
UserMediaProcessor::CreateAudioSource(
const MediaStreamDevice& device,
- const blink::WebPlatformMediaStreamSource::ConstraintsCallback&
+ blink::WebPlatformMediaStreamSource::ConstraintsRepeatingCallback
source_ready) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(current_request_info_);
@@ -1051,7 +1052,8 @@ UserMediaProcessor::CreateAudioSource(
render_frame_->GetRoutingID(), device,
base::OptionalOrNullptr(current_request_info_->audio_capture_settings()
.requested_buffer_size()),
- stream_controls->disable_local_echo, source_ready, task_runner_);
+ stream_controls->disable_local_echo, std::move(source_ready),
+ task_runner_);
}
// The audio device is not associated with screen capture and also requires
@@ -1059,7 +1061,7 @@ UserMediaProcessor::CreateAudioSource(
return std::make_unique<ProcessedLocalAudioSource>(
render_frame_->GetRoutingID(), device,
stream_controls->disable_local_echo, audio_processing_properties,
- source_ready, dependency_factory_, task_runner_);
+ std::move(source_ready), dependency_factory_, task_runner_);
}
std::unique_ptr<blink::MediaStreamVideoSource>
@@ -1099,8 +1101,8 @@ void UserMediaProcessor::StartTracks(const std::string& label) {
// Wait for the tracks to be started successfully or to fail.
current_request_info_->CallbackOnTracksStarted(
- base::BindRepeating(&UserMediaProcessor::OnCreateNativeTracksCompleted,
- weak_factory_.GetWeakPtr(), label));
+ base::BindOnce(&UserMediaProcessor::OnCreateNativeTracksCompleted,
+ weak_factory_.GetWeakPtr(), label));
}
void UserMediaProcessor::CreateVideoTracks(
@@ -1406,7 +1408,7 @@ bool UserMediaProcessor::DeleteWebRequest(
if (current_request_info_ &&
current_request_info_->web_request() == web_request) {
current_request_info_.reset();
- base::ResetAndReturn(&request_completed_cb_).Run();
+ std::move(request_completed_cb_).Run();
return true;
}
return false;
diff --git a/chromium/content/renderer/media/stream/user_media_processor.h b/chromium/content/renderer/media/stream/user_media_processor.h
index ef3aa510d51..9ad4df2d064 100644
--- a/chromium/content/renderer/media/stream/user_media_processor.h
+++ b/chromium/content/renderer/media/stream/user_media_processor.h
@@ -133,7 +133,7 @@ class CONTENT_EXPORT UserMediaProcessor
// These are virtual for test purposes.
virtual std::unique_ptr<blink::MediaStreamAudioSource> CreateAudioSource(
const blink::MediaStreamDevice& device,
- const blink::WebPlatformMediaStreamSource::ConstraintsCallback&
+ blink::WebPlatformMediaStreamSource::ConstraintsRepeatingCallback
source_ready);
virtual std::unique_ptr<blink::MediaStreamVideoSource> CreateVideoSource(
const blink::MediaStreamDevice& device,
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms.cc b/chromium/content/renderer/media/stream/webmediaplayer_ms.cc
index 9e4d209ca97..b7a85e978ae 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms.cc
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms.cc
@@ -24,7 +24,7 @@
#include "media/base/media_content_type.h"
#include "media/base/media_log.h"
#include "media/base/video_frame.h"
-#include "media/base/video_rotation.h"
+#include "media/base/video_transformation.h"
#include "media/base/video_types.h"
#include "media/blink/webmediaplayer_util.h"
#include "media/video/gpu_memory_buffer_video_frame_pool.h"
@@ -150,7 +150,7 @@ class WebMediaPlayerMS::FrameDeliverer {
FROM_HERE,
base::BindOnce(
&media::GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame,
- base::Unretained(gpu_memory_buffer_pool_.get()), frame,
+ base::Unretained(gpu_memory_buffer_pool_.get()), std::move(frame),
media::BindToCurrentLoop(
base::BindOnce(&FrameDeliverer::EnqueueFrame,
weak_factory_for_pool_.GetWeakPtr()))));
@@ -169,7 +169,7 @@ class WebMediaPlayerMS::FrameDeliverer {
private:
friend class WebMediaPlayerMS;
- void EnqueueFrame(const scoped_refptr<media::VideoFrame>& frame) {
+ void EnqueueFrame(scoped_refptr<media::VideoFrame> frame) {
DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
{
@@ -187,7 +187,7 @@ class WebMediaPlayerMS::FrameDeliverer {
}
}
- enqueue_frame_cb_.Run(frame);
+ enqueue_frame_cb_.Run(std::move(frame));
}
void DropCurrentPoolTasks() {
@@ -250,7 +250,7 @@ WebMediaPlayerMS::WebMediaPlayerMS(
delegate_(delegate),
delegate_id_(0),
paused_(true),
- video_rotation_(media::VIDEO_ROTATION_0),
+ video_transformation_(media::kNoTransformation),
media_log_(std::move(media_log)),
renderer_factory_(std::move(factory)),
main_render_task_runner_(std::move(main_render_task_runner)),
@@ -265,10 +265,12 @@ WebMediaPlayerMS::WebMediaPlayerMS(
should_play_upon_shown_(false),
create_bridge_callback_(std::move(create_bridge_callback)),
submitter_(std::move(submitter)),
- surface_layer_mode_(surface_layer_mode) {
+ surface_layer_mode_(surface_layer_mode),
+ weak_factory_(this) {
DVLOG(1) << __func__;
DCHECK(client);
DCHECK(delegate_);
+ weak_this_ = weak_factory_.GetWeakPtr();
delegate_id_ = delegate_->AddObserver(this);
media_log_->AddEvent(
@@ -325,7 +327,7 @@ blink::WebMediaPlayer::LoadTiming WebMediaPlayerMS::Load(
compositor_ = new WebMediaPlayerMSCompositor(
compositor_task_runner_, io_task_runner_, web_stream_,
- std::move(submitter_), surface_layer_mode_, AsWeakPtr());
+ std::move(submitter_), surface_layer_mode_, weak_this_);
SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
SetReadyState(WebMediaPlayer::kReadyStateHaveNothing);
@@ -334,14 +336,12 @@ blink::WebMediaPlayer::LoadTiming WebMediaPlayerMS::Load(
media_log_->AddEvent(media_log_->CreateLoadEvent(stream_id));
frame_deliverer_.reset(new WebMediaPlayerMS::FrameDeliverer(
- AsWeakPtr(),
+ weak_this_,
base::BindRepeating(&WebMediaPlayerMSCompositor::EnqueueFrame,
compositor_),
media_task_runner_, worker_task_runner_, gpu_factories_));
video_frame_provider_ = renderer_factory_->GetVideoRenderer(
web_stream_,
- media::BindToCurrentLoop(
- base::Bind(&WebMediaPlayerMS::OnSourceError, AsWeakPtr())),
frame_deliverer_->GetRepaintCallback(), io_task_runner_,
main_render_task_runner_);
@@ -468,6 +468,10 @@ base::Optional<viz::SurfaceId> WebMediaPlayerMS::GetSurfaceId() {
return base::nullopt;
}
+base::WeakPtr<blink::WebMediaPlayer> WebMediaPlayerMS::AsWeakPtr() {
+ return weak_this_;
+}
+
void WebMediaPlayerMS::Reload() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (web_stream_.IsNull())
@@ -502,8 +506,6 @@ void WebMediaPlayerMS::ReloadVideo() {
SetNetworkState(kNetworkStateLoading);
video_frame_provider_ = renderer_factory_->GetVideoRenderer(
web_stream_,
- media::BindToCurrentLoop(
- base::Bind(&WebMediaPlayerMS::OnSourceError, AsWeakPtr())),
frame_deliverer_->GetRepaintCallback(), io_task_runner_,
main_render_task_runner_);
DCHECK(video_frame_provider_);
@@ -689,8 +691,8 @@ blink::WebSize WebMediaPlayerMS::NaturalSize() const {
if (!video_frame_provider_)
return blink::WebSize();
- if (video_rotation_ == media::VIDEO_ROTATION_90 ||
- video_rotation_ == media::VideoRotation::VIDEO_ROTATION_270) {
+ if (video_transformation_.rotation == media::VIDEO_ROTATION_90 ||
+ video_transformation_.rotation == media::VIDEO_ROTATION_270) {
const gfx::Size& current_size = compositor_->GetCurrentSize();
return blink::WebSize(current_size.height(), current_size.width());
}
@@ -699,14 +701,13 @@ blink::WebSize WebMediaPlayerMS::NaturalSize() const {
blink::WebSize WebMediaPlayerMS::VisibleRect() const {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- scoped_refptr<media::VideoFrame> video_frame =
- compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ scoped_refptr<media::VideoFrame> video_frame = compositor_->GetCurrentFrame();
if (!video_frame)
return blink::WebSize();
const gfx::Rect& visible_rect = video_frame->visible_rect();
- if (video_rotation_ == media::VIDEO_ROTATION_90 ||
- video_rotation_ == media::VideoRotation::VIDEO_ROTATION_270) {
+ if (video_transformation_.rotation == media::VIDEO_ROTATION_90 ||
+ video_transformation_.rotation == media::VIDEO_ROTATION_270) {
return blink::WebSize(visible_rect.height(), visible_rect.width());
}
return blink::WebSize(visible_rect.width(), visible_rect.height());
@@ -781,23 +782,19 @@ void WebMediaPlayerMS::Paint(cc::PaintCanvas* canvas,
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- const scoped_refptr<media::VideoFrame> frame =
- compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ const scoped_refptr<media::VideoFrame> frame = compositor_->GetCurrentFrame();
- media::Context3D context_3d;
- gpu::ContextSupport* context_support = nullptr;
+ viz::ContextProvider* provider = nullptr;
if (frame && frame->HasTextures()) {
- auto* provider =
+ provider =
RenderThreadImpl::current()->SharedMainThreadContextProvider().get();
// GPU Process crashed.
if (!provider)
return;
- context_3d = media::Context3D(provider->ContextGL(), provider->GrContext());
- context_support = provider->ContextSupport();
}
const gfx::RectF dest_rect(rect.x, rect.y, rect.width, rect.height);
- video_renderer_.Paint(frame, canvas, dest_rect, flags, video_rotation_,
- context_3d, context_support);
+ video_renderer_.Paint(frame, canvas, dest_rect, flags, video_transformation_,
+ provider);
}
bool WebMediaPlayerMS::WouldTaintOrigin() const {
@@ -930,15 +927,6 @@ void WebMediaPlayerMS::OnBecamePersistentVideo(bool value) {
get_client()->OnBecamePersistentVideo(value);
}
-void WebMediaPlayerMS::OnPictureInPictureModeEnded() {
- // It is possible for this method to be called when the player is no longer in
- // Picture-in-Picture mode.
- if (!client_ || !IsInPictureInPicture())
- return;
-
- client_->PictureInPictureStopped();
-}
-
bool WebMediaPlayerMS::CopyVideoTextureToPlatformTexture(
gpu::gles2::GLES2Interface* gl,
unsigned target,
@@ -954,24 +942,20 @@ bool WebMediaPlayerMS::CopyVideoTextureToPlatformTexture(
TRACE_EVENT0("media", "copyVideoTextureToPlatformTexture");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- scoped_refptr<media::VideoFrame> video_frame =
- compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ scoped_refptr<media::VideoFrame> video_frame = compositor_->GetCurrentFrame();
if (!video_frame.get() || !video_frame->HasTextures())
return false;
- media::Context3D context_3d;
auto* provider =
RenderThreadImpl::current()->SharedMainThreadContextProvider().get();
// GPU Process crashed.
if (!provider)
return false;
- context_3d = media::Context3D(provider->ContextGL(), provider->GrContext());
- DCHECK(context_3d.gl);
return video_renderer_.CopyVideoFrameTexturesToGLTexture(
- context_3d, provider->ContextSupport(), gl, video_frame.get(), target,
- texture, internal_format, format, type, level, premultiply_alpha, flip_y);
+ provider, gl, video_frame.get(), target, texture, internal_format, format,
+ type, level, premultiply_alpha, flip_y);
}
bool WebMediaPlayerMS::CopyVideoYUVDataToPlatformTexture(
@@ -989,26 +973,22 @@ bool WebMediaPlayerMS::CopyVideoYUVDataToPlatformTexture(
TRACE_EVENT0("media", "copyVideoYUVDataToPlatformTexture");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- scoped_refptr<media::VideoFrame> video_frame =
- compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ scoped_refptr<media::VideoFrame> video_frame = compositor_->GetCurrentFrame();
if (!video_frame)
return false;
if (video_frame->HasTextures())
return false;
- media::Context3D context_3d;
auto* provider =
RenderThreadImpl::current()->SharedMainThreadContextProvider().get();
// GPU Process crashed.
if (!provider)
return false;
- context_3d = media::Context3D(provider->ContextGL(), provider->GrContext());
- DCHECK(context_3d.gl);
return video_renderer_.CopyVideoFrameYUVDataToGLTexture(
- context_3d, gl, video_frame.get(), target, texture, internal_format,
- format, type, level, premultiply_alpha, flip_y);
+ provider, gl, *video_frame, target, texture, internal_format, format,
+ type, level, premultiply_alpha, flip_y);
}
bool WebMediaPlayerMS::TexImageImpl(TexImageFunctionID functionID,
@@ -1028,7 +1008,7 @@ bool WebMediaPlayerMS::TexImageImpl(TexImageFunctionID functionID,
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
const scoped_refptr<media::VideoFrame> video_frame =
- compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ compositor_->GetCurrentFrame();
if (!video_frame || !video_frame->IsMappable() ||
video_frame->HasTextures() ||
video_frame->format() != media::PIXEL_FORMAT_Y16) {
@@ -1071,7 +1051,7 @@ void WebMediaPlayerMS::ActivateSurfaceLayerForVideo() {
FROM_HERE, base::BindOnce(&WebMediaPlayerMSCompositor::EnableSubmission,
compositor_, bridge_->GetSurfaceId(),
bridge_->GetLocalSurfaceIdAllocationTime(),
- video_rotation_, IsInPictureInPicture()));
+ video_transformation_, IsInPictureInPicture()));
// If the element is already in Picture-in-Picture mode, it means that it
// was set in this mode prior to this load, with a different
@@ -1127,7 +1107,7 @@ void WebMediaPlayerMS::OnOpacityChanged(bool is_opaque) {
void WebMediaPlayerMS::OnRotationChanged(media::VideoRotation video_rotation) {
DVLOG(1) << __func__;
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- video_rotation_ = video_rotation;
+ video_transformation_ = {video_rotation, 0};
if (!bridge_) {
// Keep the old |video_layer_| alive until SetCcLayer() is called with a new
@@ -1152,12 +1132,6 @@ void WebMediaPlayerMS::RepaintInternal() {
get_client()->Repaint();
}
-void WebMediaPlayerMS::OnSourceError() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- SetNetworkState(WebMediaPlayer::kNetworkStateFormatError);
- RepaintInternal();
-}
-
void WebMediaPlayerMS::SetNetworkState(WebMediaPlayer::NetworkState state) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
network_state_ = state;
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms.h b/chromium/content/renderer/media/stream/webmediaplayer_ms.h
index 3bdda3570ea..dc148fdf6b3 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms.h
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms.h
@@ -74,8 +74,7 @@ class CONTENT_EXPORT WebMediaPlayerMS
: public blink::WebMediaStreamObserver,
public blink::WebMediaPlayer,
public media::WebMediaPlayerDelegate::Observer,
- public blink::WebSurfaceLayerBridgeObserver,
- public base::SupportsWeakPtr<WebMediaPlayerMS> {
+ public blink::WebSurfaceLayerBridgeObserver {
public:
// Construct a WebMediaPlayerMS with reference to the client, and
// a MediaStreamClient which provides blink::WebMediaStreamVideoRenderer.
@@ -182,7 +181,6 @@ class CONTENT_EXPORT WebMediaPlayerMS
void OnSeekBackward(double seconds) override;
void OnVolumeMultiplierUpdate(double multiplier) override;
void OnBecamePersistentVideo(bool value) override;
- void OnPictureInPictureModeEnded() override;
void OnFirstFrameReceived(media::VideoRotation video_rotation,
bool is_opaque);
@@ -236,6 +234,8 @@ class CONTENT_EXPORT WebMediaPlayerMS
int GetDelegateId() override;
base::Optional<viz::SurfaceId> GetSurfaceId() override;
+ base::WeakPtr<blink::WebMediaPlayer> AsWeakPtr() override;
+
void OnDisplayTypeChanged(WebMediaPlayer::DisplayType) override;
private:
@@ -253,9 +253,6 @@ class CONTENT_EXPORT WebMediaPlayerMS
// Need repaint due to state change.
void RepaintInternal();
- // The callback for source to report error.
- void OnSourceError();
-
// Helpers that set the network/ready state and notifies the client if
// they've changed.
void SetNetworkState(blink::WebMediaPlayer::NetworkState state);
@@ -309,7 +306,7 @@ class CONTENT_EXPORT WebMediaPlayerMS
media::PaintCanvasVideoRenderer video_renderer_;
bool paused_;
- media::VideoRotation video_rotation_;
+ media::VideoTransformation video_transformation_;
std::unique_ptr<media::MediaLog> media_log_;
@@ -360,6 +357,9 @@ class CONTENT_EXPORT WebMediaPlayerMS
// Whether the video is known to be opaque or not.
bool opaque_ = true;
+ base::WeakPtr<WebMediaPlayerMS> weak_this_;
+ base::WeakPtrFactory<WebMediaPlayerMS> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerMS);
};
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
index 9373f9a70a3..023faa7bb8b 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
@@ -41,7 +41,7 @@ namespace {
// This function copies |frame| to a new I420 or YV12A media::VideoFrame.
scoped_refptr<media::VideoFrame> CopyFrame(
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
media::PaintCanvasVideoRenderer* video_renderer) {
scoped_refptr<media::VideoFrame> new_frame;
if (frame->HasTextures()) {
@@ -68,10 +68,7 @@ scoped_refptr<media::VideoFrame> CopyFrame(
cc::SkiaPaintCanvas paint_canvas(bitmap);
DCHECK(provider->ContextGL());
- video_renderer->Copy(
- frame.get(), &paint_canvas,
- media::Context3D(provider->ContextGL(), provider->GrContext()),
- provider->ContextSupport());
+ video_renderer->Copy(frame.get(), &paint_canvas, provider);
SkPixmap pixmap;
const bool result = bitmap.peekPixels(&pixmap);
@@ -214,7 +211,7 @@ void WebMediaPlayerMSCompositor::SetIsSurfaceVisible(bool state) {
void WebMediaPlayerMSCompositor::EnableSubmission(
const viz::SurfaceId& id,
base::TimeTicks local_surface_id_allocation_time,
- media::VideoRotation rotation,
+ media::VideoTransformation transformation,
bool force_submit) {
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
@@ -224,7 +221,7 @@ void WebMediaPlayerMSCompositor::EnableSubmission(
video_frame_provider_client_->StopUsingProvider();
}
- submitter_->SetRotation(rotation);
+ submitter_->SetRotation(transformation.rotation);
submitter_->SetForceSubmit(force_submit);
submitter_->EnableSubmission(id, local_surface_id_allocation_time);
video_frame_provider_client_ = submitter_.get();
@@ -334,11 +331,11 @@ void WebMediaPlayerMSCompositor::EnqueueFrame(
dropped_frame_count_ += rendering_frame_buffer_->frames_queued() - 1;
rendering_frame_buffer_->Reset();
timestamps_to_clock_times_.clear();
- RenderWithoutAlgorithm(std::move(frame));
+ RenderWithoutAlgorithm(frame);
}
timestamps_to_clock_times_[frame->timestamp()] = render_time;
- rendering_frame_buffer_->EnqueueFrame(frame);
+ rendering_frame_buffer_->EnqueueFrame(std::move(frame));
}
bool WebMediaPlayerMSCompositor::UpdateCurrentFrame(
@@ -386,7 +383,6 @@ bool WebMediaPlayerMSCompositor::HasCurrentFrame() {
scoped_refptr<media::VideoFrame> WebMediaPlayerMSCompositor::GetCurrentFrame() {
DVLOG(3) << __func__;
- DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
base::AutoLock auto_lock(current_frame_lock_);
TRACE_EVENT_INSTANT1("media", "WebMediaPlayerMSCompositor::GetCurrentFrame",
TRACE_EVENT_SCOPE_THREAD, "Timestamp",
@@ -403,14 +399,9 @@ void WebMediaPlayerMSCompositor::PutCurrentFrame() {
current_frame_rendered_ = true;
}
-scoped_refptr<media::VideoFrame>
-WebMediaPlayerMSCompositor::GetCurrentFrameWithoutUpdatingStatistics() {
- DVLOG(3) << __func__;
- base::AutoLock auto_lock(current_frame_lock_);
- if (!render_started_)
- return nullptr;
-
- return current_frame_;
+base::TimeDelta WebMediaPlayerMSCompositor::GetPreferredRenderInterval() {
+ DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
+ return viz::BeginFrameArgs::MinInterval();
}
void WebMediaPlayerMSCompositor::StartRendering() {
@@ -486,39 +477,40 @@ void WebMediaPlayerMSCompositor::RenderUsingAlgorithm(
if (!frame || frame == current_frame_)
return;
+ const base::TimeDelta timestamp = frame->timestamp();
SetCurrentFrame(std::move(frame));
const auto& end = timestamps_to_clock_times_.end();
const auto& begin = timestamps_to_clock_times_.begin();
auto iterator = begin;
- while (iterator != end && iterator->first < frame->timestamp())
+ while (iterator != end && iterator->first < timestamp)
++iterator;
timestamps_to_clock_times_.erase(begin, iterator);
}
void WebMediaPlayerMSCompositor::RenderWithoutAlgorithm(
- const scoped_refptr<media::VideoFrame>& frame) {
+ scoped_refptr<media::VideoFrame> frame) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
video_frame_compositor_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&WebMediaPlayerMSCompositor::RenderWithoutAlgorithmOnCompositor, this,
- frame));
+ std::move(frame)));
}
void WebMediaPlayerMSCompositor::RenderWithoutAlgorithmOnCompositor(
- const scoped_refptr<media::VideoFrame>& frame) {
+ scoped_refptr<media::VideoFrame> frame) {
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
{
base::AutoLock auto_lock(current_frame_lock_);
- SetCurrentFrame(frame);
+ SetCurrentFrame(std::move(frame));
}
if (video_frame_provider_client_)
video_frame_provider_client_->DidReceiveFrame();
}
void WebMediaPlayerMSCompositor::SetCurrentFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
+ scoped_refptr<media::VideoFrame> frame) {
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
current_frame_lock_.AssertAcquired();
TRACE_EVENT_INSTANT1("media", "WebMediaPlayerMSCompositor::SetCurrentFrame",
@@ -529,49 +521,75 @@ void WebMediaPlayerMSCompositor::SetCurrentFrame(
++dropped_frame_count_;
current_frame_rendered_ = false;
- scoped_refptr<media::VideoFrame> old_frame = std::move(current_frame_);
- current_frame_ = frame;
+ // Compare current frame with |frame|. Initialize values as if there is no
+ // current frame.
+ bool is_first_frame = true;
+ bool has_frame_size_changed = false;
+ base::Optional<media::VideoRotation> new_rotation = media::VIDEO_ROTATION_0;
+ base::Optional<bool> new_opacity;
+
+ new_opacity = media::IsOpaque(frame->format());
+ media::VideoRotation current_video_rotation;
+ if (frame->metadata()->GetRotation(media::VideoFrameMetadata::ROTATION,
+ &current_video_rotation)) {
+ new_rotation = current_video_rotation;
+ }
+
+ if (current_frame_) {
+ // We have a current frame, so determine what has changed.
+ is_first_frame = false;
+
+ if (!current_frame_->metadata()->GetRotation(
+ media::VideoFrameMetadata::ROTATION, &current_video_rotation) ||
+ current_video_rotation == *new_rotation) {
+ new_rotation.reset();
+ }
+
+ if (*new_opacity == media::IsOpaque(current_frame_->format()))
+ new_opacity.reset();
+
+ has_frame_size_changed =
+ frame->natural_size() != current_frame_->natural_size();
+ }
+
+ current_frame_ = std::move(frame);
// Complete the checks after |current_frame_| is accessible to avoid
// deadlocks, see https://crbug.com/901744.
video_frame_compositor_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&WebMediaPlayerMSCompositor::CheckForFrameChanges, this,
- old_frame, frame));
+ is_first_frame, has_frame_size_changed,
+ std::move(new_rotation), std::move(new_opacity)));
}
void WebMediaPlayerMSCompositor::CheckForFrameChanges(
- const scoped_refptr<media::VideoFrame>& old_frame,
- const scoped_refptr<media::VideoFrame>& new_frame) {
+ bool is_first_frame,
+ bool has_frame_size_changed,
+ base::Optional<media::VideoRotation> new_frame_rotation,
+ base::Optional<bool> new_frame_opacity) {
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
- const bool new_frame_is_opaque = media::IsOpaque(new_frame->format());
- media::VideoRotation new_frame_video_rotation = media::VIDEO_ROTATION_0;
- ignore_result(new_frame->metadata()->GetRotation(
- media::VideoFrameMetadata::ROTATION, &new_frame_video_rotation));
- if (!old_frame) {
+ if (is_first_frame) {
main_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&WebMediaPlayerMS::OnFirstFrameReceived, player_,
- new_frame_video_rotation, new_frame_is_opaque));
+ *new_frame_rotation, *new_frame_opacity));
return;
}
- media::VideoRotation old_frame_video_rotation = media::VIDEO_ROTATION_0;
- ignore_result(old_frame->metadata()->GetRotation(
- media::VideoFrameMetadata::ROTATION, &old_frame_video_rotation));
- if (new_frame_video_rotation != old_frame_video_rotation) {
+ if (new_frame_rotation.has_value()) {
main_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&WebMediaPlayerMS::OnRotationChanged, player_,
- new_frame_video_rotation));
+ *new_frame_rotation));
if (submitter_)
- submitter_->SetRotation(new_frame_video_rotation);
+ submitter_->SetRotation(*new_frame_rotation);
}
- if (new_frame_is_opaque != media::IsOpaque(old_frame->format())) {
+ if (new_frame_opacity.has_value()) {
main_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&WebMediaPlayerMS::OnOpacityChanged, player_,
- new_frame_is_opaque));
+ *new_frame_opacity));
}
- if (old_frame->natural_size() != new_frame->natural_size()) {
+ if (has_frame_size_changed) {
main_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&WebMediaPlayerMS::TriggerResize, player_));
}
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h
index 6f2d882dbf6..bb1b8dc9520 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h
@@ -13,6 +13,7 @@
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "cc/layers/surface_layer.h"
@@ -58,10 +59,6 @@ class CONTENT_EXPORT WebMediaPlayerMSCompositor
: public cc::VideoFrameProvider,
public base::RefCountedDeleteOnSequence<WebMediaPlayerMSCompositor> {
public:
- // This |url| represents the media stream we are rendering. |url| is used to
- // find out what web stream this WebMediaPlayerMSCompositor is playing, and
- // together with flag "--disable-rtc-smoothness-algorithm" determine whether
- // we enable algorithm or not.
WebMediaPlayerMSCompositor(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
@@ -88,7 +85,7 @@ class CONTENT_EXPORT WebMediaPlayerMSCompositor
virtual void EnableSubmission(
const viz::SurfaceId& id,
base::TimeTicks local_surface_id_allocation_time,
- media::VideoRotation rotation,
+ media::VideoTransformation transformation,
bool force_submit);
// Notifies the |submitter_| that the frames must be submitted.
@@ -105,13 +102,7 @@ class CONTENT_EXPORT WebMediaPlayerMSCompositor
bool HasCurrentFrame() override;
scoped_refptr<media::VideoFrame> GetCurrentFrame() override;
void PutCurrentFrame() override;
-
- // Return the current frame being rendered.
- // Difference between GetCurrentFrame(): GetCurrentFrame() is designed for
- // chrome compositor to pull frame from WebMediaPlayerMSCompositor, and thus
- // calling GetCurrentFrame() will affect statistics like |dropped_frames_|
- // etc. Calling this function has no side effect.
- scoped_refptr<media::VideoFrame> GetCurrentFrameWithoutUpdatingStatistics();
+ base::TimeDelta GetPreferredRenderInterval() override;
void StartRendering();
void StopRendering();
@@ -149,16 +140,19 @@ class CONTENT_EXPORT WebMediaPlayerMSCompositor
// For algorithm disabled case only: call SetCurrentFrame() with the current
// frame immediately. |video_frame_provider_client_| gets notified about the
// new frame with a DidReceiveFrame() call.
- void RenderWithoutAlgorithm(const scoped_refptr<media::VideoFrame>& frame);
+ void RenderWithoutAlgorithm(scoped_refptr<media::VideoFrame> frame);
void RenderWithoutAlgorithmOnCompositor(
- const scoped_refptr<media::VideoFrame>& frame);
+ scoped_refptr<media::VideoFrame> frame);
// Update |current_frame_| and |dropped_frame_count_|
- void SetCurrentFrame(const scoped_refptr<media::VideoFrame>& frame);
+ void SetCurrentFrame(scoped_refptr<media::VideoFrame> frame);
// Following the update to |current_frame_|, this will check for changes that
// require updating video layer.
- void CheckForFrameChanges(const scoped_refptr<media::VideoFrame>& old_frame,
- const scoped_refptr<media::VideoFrame>& new_frame);
+ void CheckForFrameChanges(
+ bool is_first_frame,
+ bool has_frame_size_changed,
+ base::Optional<media::VideoRotation> new_frame_rotation,
+ base::Optional<bool> new_frame_opacity);
void StartRenderingInternal();
void StopRenderingInternal();
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc b/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
index 285c2ba3ae3..3deac07024d 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
@@ -202,13 +202,11 @@ class MockMediaStreamVideoRenderer : public blink::WebMediaStreamVideoRenderer {
MockMediaStreamVideoRenderer(
const scoped_refptr<base::SingleThreadTaskRunner> task_runner,
ReusableMessageLoopEvent* message_loop_controller,
- const base::Closure& error_cb,
const blink::WebMediaStreamVideoRenderer::RepaintCB& repaint_cb)
: started_(false),
standard_size_(kStandardWidth, kStandardHeight),
task_runner_(task_runner),
message_loop_controller_(message_loop_controller),
- error_cb_(error_cb),
repaint_cb_(repaint_cb),
delay_till_next_generated_frame_(
base::TimeDelta::FromSecondsD(1.0 / 30.0)) {}
@@ -238,8 +236,7 @@ class MockMediaStreamVideoRenderer : public blink::WebMediaStreamVideoRenderer {
void InjectFrame();
// Methods for test use
- void AddFrame(FrameType category,
- const scoped_refptr<media::VideoFrame>& frame);
+ void AddFrame(FrameType category, scoped_refptr<media::VideoFrame> frame);
bool started_;
bool paused_;
@@ -247,7 +244,6 @@ class MockMediaStreamVideoRenderer : public blink::WebMediaStreamVideoRenderer {
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
ReusableMessageLoopEvent* const message_loop_controller_;
- const base::Closure error_cb_;
const blink::WebMediaStreamVideoRenderer::RepaintCB repaint_cb_;
base::circular_deque<TestFrame> frames_;
@@ -299,8 +295,8 @@ void MockMediaStreamVideoRenderer::Pause() {
void MockMediaStreamVideoRenderer::AddFrame(
FrameType category,
- const scoped_refptr<media::VideoFrame>& frame) {
- frames_.push_back(std::make_pair(category, frame));
+ scoped_refptr<media::VideoFrame> frame) {
+ frames_.push_back(std::make_pair(category, std::move(frame)));
}
void MockMediaStreamVideoRenderer::QueueFrames(
@@ -365,10 +361,8 @@ void MockMediaStreamVideoRenderer::InjectFrame() {
auto frame = frames_.front();
frames_.pop_front();
- if (frame.first == FrameType::BROKEN_FRAME) {
- error_cb_.Run();
+ if (frame.first == FrameType::BROKEN_FRAME)
return;
- }
// For pause case, the provider will still let the stream continue, but
// not send the frames to the player. As is the same case in reality.
@@ -435,7 +429,6 @@ class MockRenderFactory : public blink::WebMediaStreamRendererFactory {
scoped_refptr<blink::WebMediaStreamVideoRenderer> GetVideoRenderer(
const blink::WebMediaStream& web_stream,
- const base::Closure& error_cb,
const blink::WebMediaStreamVideoRenderer::RepaintCB& repaint_cb,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner)
@@ -475,15 +468,14 @@ class MockRenderFactory : public blink::WebMediaStreamRendererFactory {
scoped_refptr<blink::WebMediaStreamVideoRenderer>
MockRenderFactory::GetVideoRenderer(
const blink::WebMediaStream& web_stream,
- const base::Closure& error_cb,
const blink::WebMediaStreamVideoRenderer::RepaintCB& repaint_cb,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner) {
if (!support_video_renderer_)
return nullptr;
- provider_ = new MockMediaStreamVideoRenderer(task_runner_,
- message_loop_controller_, error_cb, repaint_cb);
+ provider_ = new MockMediaStreamVideoRenderer(
+ task_runner_, message_loop_controller_, repaint_cb);
return provider_;
}
@@ -585,7 +577,6 @@ class WebMediaPlayerMSTest
const blink::WebString& remote_device_friendly_name) override {}
void MediaRemotingStopped(
blink::WebLocalizedString::Name error_msg) override {}
- void PictureInPictureStopped() override {}
void RequestPlay() override {}
void RequestPause() override {}
void RequestMuted(bool muted) override {}
@@ -899,45 +890,6 @@ TEST_P(WebMediaPlayerMSTest, Playing_Normal) {
EXPECT_CALL(*this, DoStopRendering());
}
-TEST_P(WebMediaPlayerMSTest, Playing_ErrorFrame) {
- // This tests sends a broken frame to WebMediaPlayerMS, and verifies
- // OnSourceError function works as expected.
-
- InitializeWebMediaPlayerMS();
-
- MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(false);
-
- const int kBrokenFrame = static_cast<int>(FrameType::BROKEN_FRAME);
- int tokens[] = {0, 33, 66, 100, 133, 166, 200, 233, 266, 300,
- 333, 366, 400, 433, 466, 500, 533, 566, 600, kBrokenFrame};
- std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
- provider->QueueFrames(timestamps);
-
- if (enable_surface_layer_for_video_) {
- EXPECT_CALL(*submitter_ptr_, StartRendering());
- } else {
- EXPECT_CALL(*this, DoSetCcLayer(true));
- EXPECT_CALL(*this, DoStartRendering());
- }
- EXPECT_CALL(*this, DoReadyStateChanged(
- blink::WebMediaPlayer::kReadyStateHaveMetadata));
- EXPECT_CALL(*this, DoReadyStateChanged(
- blink::WebMediaPlayer::kReadyStateHaveEnoughData));
- EXPECT_CALL(*this, DoNetworkStateChanged(
- blink::WebMediaPlayer::kNetworkStateFormatError));
- EXPECT_CALL(*this,
- CheckSizeChanged(gfx::Size(kStandardWidth, kStandardHeight)));
- message_loop_controller_.RunAndWaitForStatus(
- media::PipelineStatus::PIPELINE_ERROR_NETWORK);
- testing::Mock::VerifyAndClearExpectations(this);
-
- EXPECT_CALL(*this, DoSetCcLayer(false));
- if (enable_surface_layer_for_video_)
- EXPECT_CALL(*submitter_ptr_, StopUsingProvider());
- else
- EXPECT_CALL(*this, DoStopRendering());
-}
-
TEST_P(WebMediaPlayerMSTest, PlayThenPause) {
InitializeWebMediaPlayerMS();
const bool opaque_frame = testing::get<1>(GetParam());
@@ -979,10 +931,10 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPause) {
EXPECT_CALL(*this, DoStopRendering());
player_->Pause();
- auto prev_frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ auto prev_frame = compositor_->GetCurrentFrame();
message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK);
- auto after_frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ auto after_frame = compositor_->GetCurrentFrame();
EXPECT_EQ(prev_frame->timestamp(), after_frame->timestamp());
testing::Mock::VerifyAndClearExpectations(this);
@@ -1030,10 +982,10 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
EXPECT_CALL(*this, DoStopRendering());
player_->Pause();
- auto prev_frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ auto prev_frame = compositor_->GetCurrentFrame();
message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK);
- auto after_frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ auto after_frame = compositor_->GetCurrentFrame();
EXPECT_EQ(prev_frame->timestamp(), after_frame->timestamp());
testing::Mock::VerifyAndClearExpectations(this);
@@ -1044,10 +996,10 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
EXPECT_CALL(*this, DoStartRendering());
player_->Play();
- prev_frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ prev_frame = compositor_->GetCurrentFrame();
message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK);
- after_frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ after_frame = compositor_->GetCurrentFrame();
EXPECT_NE(prev_frame->timestamp(), after_frame->timestamp());
testing::Mock::VerifyAndClearExpectations(this);
@@ -1232,18 +1184,18 @@ TEST_P(WebMediaPlayerMSTest, BackgroundRendering) {
EXPECT_CALL(*this, DoDidReceiveFrame()).Times(testing::AtLeast(1));
SetBackgroundRendering(true);
- auto prev_frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ auto prev_frame = compositor_->GetCurrentFrame();
message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK);
- auto after_frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ auto after_frame = compositor_->GetCurrentFrame();
EXPECT_NE(prev_frame->timestamp(), after_frame->timestamp());
// Switch to foreground rendering.
SetBackgroundRendering(false);
- prev_frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ prev_frame = compositor_->GetCurrentFrame();
message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK);
- after_frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ after_frame = compositor_->GetCurrentFrame();
EXPECT_NE(prev_frame->timestamp(), after_frame->timestamp());
testing::Mock::VerifyAndClearExpectations(this);
@@ -1324,7 +1276,7 @@ TEST_P(WebMediaPlayerMSTest, CreateHardwareFrames) {
std::move(frame_ready_cbs_[0]).Run();
base::RunLoop().RunUntilIdle();
- auto frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+ auto frame = compositor_->GetCurrentFrame();
ASSERT_TRUE(frame != nullptr);
testing::Mock::VerifyAndClearExpectations(this);
diff --git a/chromium/content/renderer/media/video_capture/OWNERS b/chromium/content/renderer/media/video_capture/OWNERS
index 8bc343a986b..0a6f62e7be4 100644
--- a/chromium/content/renderer/media/video_capture/OWNERS
+++ b/chromium/content/renderer/media/video_capture/OWNERS
@@ -1,5 +1,4 @@
chfremer@chromium.org
-emircan@chromium.org
guidou@chromium.org
# COMPONENT: Blink>GetUserMedia>Webcam
diff --git a/chromium/content/renderer/media/video_capture/local_video_capturer_source.cc b/chromium/content/renderer/media/video_capture/local_video_capturer_source.cc
index 52d3e94764e..103a4202f89 100644
--- a/chromium/content/renderer/media/video_capture/local_video_capturer_source.cc
+++ b/chromium/content/renderer/media/video_capture/local_video_capturer_source.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/callback_helpers.h"
#include "content/renderer/media/video_capture/video_capture_impl_manager.h"
#include "content/renderer/render_thread_impl.h"
#include "media/base/bind_to_current_loop.h"
@@ -27,7 +26,7 @@ LocalVideoCapturerSource::LocalVideoCapturerSource(
LocalVideoCapturerSource::~LocalVideoCapturerSource() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- release_device_cb_.Run();
+ std::move(release_device_cb_).Run();
}
media::VideoCaptureFormats LocalVideoCapturerSource::GetPreferredFormats() {
@@ -54,7 +53,7 @@ void LocalVideoCapturerSource::StartCapture(
void LocalVideoCapturerSource::RequestRefreshFrame() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (stop_capture_cb_.is_null())
+ if (!stop_capture_cb_)
return; // Do not request frames if the source is stopped.
manager_->RequestRefreshFrame(session_id_);
}
@@ -72,8 +71,8 @@ void LocalVideoCapturerSource::Resume() {
void LocalVideoCapturerSource::StopCapture() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Immediately make sure we don't provide more frames.
- if (!stop_capture_cb_.is_null())
- base::ResetAndReturn(&stop_capture_cb_).Run();
+ if (stop_capture_cb_)
+ std::move(stop_capture_cb_).Run();
}
void LocalVideoCapturerSource::OnFrameDropped(
@@ -105,7 +104,7 @@ void LocalVideoCapturerSource::OnStateUpdate(blink::VideoCaptureState state) {
case blink::VIDEO_CAPTURE_STATE_STOPPED:
case blink::VIDEO_CAPTURE_STATE_ERROR:
case blink::VIDEO_CAPTURE_STATE_ENDED:
- release_device_cb_.Run();
+ std::move(release_device_cb_).Run();
release_device_cb_ = manager_->UseDevice(session_id_);
OnLog(
"LocalVideoCapturerSource::OnStateUpdate signaling to "
diff --git a/chromium/content/renderer/media/video_capture/local_video_capturer_source.h b/chromium/content/renderer/media/video_capture/local_video_capturer_source.h
index 8579fc054f5..9076ce3269a 100644
--- a/chromium/content/renderer/media/video_capture/local_video_capturer_source.h
+++ b/chromium/content/renderer/media/video_capture/local_video_capturer_source.h
@@ -58,13 +58,13 @@ class LocalVideoCapturerSource : public media::VideoCapturerSource {
VideoCaptureImplManager* const manager_;
- base::Closure release_device_cb_;
+ base::OnceClosure release_device_cb_;
// These two are valid between StartCapture() and StopCapture().
// |running_call_back_| is run when capture is successfully started, and when
// it is stopped or error happens.
RunningCallback running_callback_;
- base::Closure stop_capture_cb_;
+ base::OnceClosure stop_capture_cb_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/chromium/content/renderer/media/video_capture/video_capture_impl.cc b/chromium/content/renderer/media/video_capture/video_capture_impl.cc
index e162e3196b6..24cb7b213c9 100644
--- a/chromium/content/renderer/media/video_capture/video_capture_impl.cc
+++ b/chromium/content/renderer/media/video_capture/video_capture_impl.cc
@@ -248,21 +248,21 @@ void VideoCaptureImpl::RequestRefreshFrame() {
}
void VideoCaptureImpl::GetDeviceSupportedFormats(
- const blink::VideoCaptureDeviceFormatsCB& callback) {
+ blink::VideoCaptureDeviceFormatsCB callback) {
DCHECK(io_thread_checker_.CalledOnValidThread());
GetVideoCaptureHost()->GetDeviceSupportedFormats(
device_id_, session_id_,
base::BindOnce(&VideoCaptureImpl::OnDeviceSupportedFormats,
- weak_factory_.GetWeakPtr(), callback));
+ weak_factory_.GetWeakPtr(), std::move(callback)));
}
void VideoCaptureImpl::GetDeviceFormatsInUse(
- const blink::VideoCaptureDeviceFormatsCB& callback) {
+ blink::VideoCaptureDeviceFormatsCB callback) {
DCHECK(io_thread_checker_.CalledOnValidThread());
GetVideoCaptureHost()->GetDeviceFormatsInUse(
device_id_, session_id_,
base::BindOnce(&VideoCaptureImpl::OnDeviceFormatsInUse,
- weak_factory_.GetWeakPtr(), callback));
+ weak_factory_.GetWeakPtr(), std::move(callback)));
}
void VideoCaptureImpl::OnFrameDropped(
@@ -549,17 +549,17 @@ void VideoCaptureImpl::StartCaptureInternal() {
}
void VideoCaptureImpl::OnDeviceSupportedFormats(
- const blink::VideoCaptureDeviceFormatsCB& callback,
+ blink::VideoCaptureDeviceFormatsCB callback,
const media::VideoCaptureFormats& supported_formats) {
DCHECK(io_thread_checker_.CalledOnValidThread());
- callback.Run(supported_formats);
+ std::move(callback).Run(supported_formats);
}
void VideoCaptureImpl::OnDeviceFormatsInUse(
- const blink::VideoCaptureDeviceFormatsCB& callback,
+ blink::VideoCaptureDeviceFormatsCB callback,
const media::VideoCaptureFormats& formats_in_use) {
DCHECK(io_thread_checker_.CalledOnValidThread());
- callback.Run(formats_in_use);
+ std::move(callback).Run(formats_in_use);
}
bool VideoCaptureImpl::RemoveClient(int client_id, ClientInfoMap* clients) {
diff --git a/chromium/content/renderer/media/video_capture/video_capture_impl.h b/chromium/content/renderer/media/video_capture/video_capture_impl.h
index 8ab48fb65a8..63afdceadee 100644
--- a/chromium/content/renderer/media/video_capture/video_capture_impl.h
+++ b/chromium/content/renderer/media/video_capture/video_capture_impl.h
@@ -56,13 +56,11 @@ class CONTENT_EXPORT VideoCaptureImpl
// Get capturing formats supported by this device.
// |callback| will be invoked with the results.
- void GetDeviceSupportedFormats(
- const blink::VideoCaptureDeviceFormatsCB& callback);
+ void GetDeviceSupportedFormats(blink::VideoCaptureDeviceFormatsCB callback);
// Get capturing formats currently in use by this device.
// |callback| will be invoked with the results.
- void GetDeviceFormatsInUse(
- const blink::VideoCaptureDeviceFormatsCB& callback);
+ void GetDeviceFormatsInUse(blink::VideoCaptureDeviceFormatsCB callback);
void OnFrameDropped(media::VideoCaptureFrameDropReason reason);
void OnLog(const std::string& message);
@@ -105,9 +103,9 @@ class CONTENT_EXPORT VideoCaptureImpl
void StartCaptureInternal();
void OnDeviceSupportedFormats(
- const blink::VideoCaptureDeviceFormatsCB& callback,
+ blink::VideoCaptureDeviceFormatsCB callback,
const media::VideoCaptureFormats& supported_formats);
- void OnDeviceFormatsInUse(const blink::VideoCaptureDeviceFormatsCB& callback,
+ void OnDeviceFormatsInUse(blink::VideoCaptureDeviceFormatsCB callback,
const media::VideoCaptureFormats& formats_in_use);
// Tries to remove |client_id| from |clients|, returning false if not found.
diff --git a/chromium/content/renderer/media/video_capture/video_capture_impl_manager.cc b/chromium/content/renderer/media/video_capture/video_capture_impl_manager.cc
index 1b5e7838ee3..bc42c232039 100644
--- a/chromium/content/renderer/media/video_capture/video_capture_impl_manager.cc
+++ b/chromium/content/renderer/media/video_capture/video_capture_impl_manager.cc
@@ -75,7 +75,7 @@ VideoCaptureImplManager::~VideoCaptureImplManager() {
devices_.clear();
}
-base::Closure VideoCaptureImplManager::UseDevice(
+base::OnceClosure VideoCaptureImplManager::UseDevice(
media::VideoCaptureSessionId id) {
DVLOG(1) << __func__ << " session id: " << id;
DCHECK(render_main_task_runner_->BelongsToCurrentThread());
@@ -101,11 +101,11 @@ base::Closure VideoCaptureImplManager::UseDevice(
if (it->is_individually_suspended)
Resume(id);
- return base::Bind(&VideoCaptureImplManager::UnrefDevice,
- weak_factory_.GetWeakPtr(), id);
+ return base::BindOnce(&VideoCaptureImplManager::UnrefDevice,
+ weak_factory_.GetWeakPtr(), id);
}
-base::Closure VideoCaptureImplManager::StartCapture(
+base::OnceClosure VideoCaptureImplManager::StartCapture(
media::VideoCaptureSessionId id,
const media::VideoCaptureParams& params,
const blink::VideoCaptureStateUpdateCB& state_update_cb,
@@ -125,8 +125,8 @@ base::Closure VideoCaptureImplManager::StartCapture(
FROM_HERE, base::BindOnce(&VideoCaptureImpl::StartCapture,
base::Unretained(it->impl.get()), client_id,
params, state_update_cb, deliver_frame_cb));
- return base::Bind(&VideoCaptureImplManager::StopCapture,
- weak_factory_.GetWeakPtr(), client_id, id);
+ return base::BindOnce(&VideoCaptureImplManager::StopCapture,
+ weak_factory_.GetWeakPtr(), client_id, id);
}
void VideoCaptureImplManager::RequestRefreshFrame(
@@ -183,7 +183,7 @@ void VideoCaptureImplManager::Resume(media::VideoCaptureSessionId id) {
void VideoCaptureImplManager::GetDeviceSupportedFormats(
media::VideoCaptureSessionId id,
- const blink::VideoCaptureDeviceFormatsCB& callback) {
+ blink::VideoCaptureDeviceFormatsCB callback) {
DCHECK(render_main_task_runner_->BelongsToCurrentThread());
const auto it = std::find_if(
devices_.begin(), devices_.end(),
@@ -192,13 +192,14 @@ void VideoCaptureImplManager::GetDeviceSupportedFormats(
// Use of base::Unretained() is safe because |devices_| is released on the
// |io_task_runner()| as well.
ChildProcess::current()->io_task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&VideoCaptureImpl::GetDeviceSupportedFormats,
- base::Unretained(it->impl.get()), callback));
+ FROM_HERE,
+ base::BindOnce(&VideoCaptureImpl::GetDeviceSupportedFormats,
+ base::Unretained(it->impl.get()), std::move(callback)));
}
void VideoCaptureImplManager::GetDeviceFormatsInUse(
media::VideoCaptureSessionId id,
- const blink::VideoCaptureDeviceFormatsCB& callback) {
+ blink::VideoCaptureDeviceFormatsCB callback) {
DCHECK(render_main_task_runner_->BelongsToCurrentThread());
const auto it = std::find_if(
devices_.begin(), devices_.end(),
@@ -207,8 +208,9 @@ void VideoCaptureImplManager::GetDeviceFormatsInUse(
// Use of base::Unretained() is safe because |devices_| is released on the
// |io_task_runner()| as well.
ChildProcess::current()->io_task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&VideoCaptureImpl::GetDeviceFormatsInUse,
- base::Unretained(it->impl.get()), callback));
+ FROM_HERE,
+ base::BindOnce(&VideoCaptureImpl::GetDeviceFormatsInUse,
+ base::Unretained(it->impl.get()), std::move(callback)));
}
std::unique_ptr<VideoCaptureImpl>
diff --git a/chromium/content/renderer/media/video_capture/video_capture_impl_manager.h b/chromium/content/renderer/media/video_capture/video_capture_impl_manager.h
index 2db45a8a457..76be1e4a8fb 100644
--- a/chromium/content/renderer/media/video_capture/video_capture_impl_manager.h
+++ b/chromium/content/renderer/media/video_capture/video_capture_impl_manager.h
@@ -48,7 +48,7 @@ class CONTENT_EXPORT VideoCaptureImplManager {
// is used.
// Returns a callback that should be used to release the acquired
// resources.
- base::Closure UseDevice(media::VideoCaptureSessionId id);
+ base::OnceClosure UseDevice(media::VideoCaptureSessionId id);
// Start receiving video frames for the given session ID.
//
@@ -67,7 +67,7 @@ class CONTENT_EXPORT VideoCaptureImplManager {
// video capture is not synchronous. Client should handle the case where
// callbacks are called after capturing is instructed to stop, typically
// by binding the passed callbacks on a WeakPtr.
- base::Closure StartCapture(
+ base::OnceClosure StartCapture(
media::VideoCaptureSessionId id,
const media::VideoCaptureParams& params,
const blink::VideoCaptureStateUpdateCB& state_update_cb,
@@ -83,15 +83,13 @@ class CONTENT_EXPORT VideoCaptureImplManager {
// Get supported formats supported by the device for the given session
// ID. |callback| will be called on the IO thread.
- void GetDeviceSupportedFormats(
- media::VideoCaptureSessionId id,
- const blink::VideoCaptureDeviceFormatsCB& callback);
+ void GetDeviceSupportedFormats(media::VideoCaptureSessionId id,
+ blink::VideoCaptureDeviceFormatsCB callback);
// Get supported formats currently in use for the given session ID.
// |callback| will be called on the IO thread.
- void GetDeviceFormatsInUse(
- media::VideoCaptureSessionId id,
- const blink::VideoCaptureDeviceFormatsCB& callback);
+ void GetDeviceFormatsInUse(media::VideoCaptureSessionId id,
+ blink::VideoCaptureDeviceFormatsCB callback);
// Make all VideoCaptureImpl instances in the input |video_devices|
// stop/resume delivering video frames to their clients, depends on flag
diff --git a/chromium/content/renderer/media/video_capture/video_capture_impl_manager_unittest.cc b/chromium/content/renderer/media/video_capture/video_capture_impl_manager_unittest.cc
index dc05a7fe332..be0be6fa9f4 100644
--- a/chromium/content/renderer/media/video_capture/video_capture_impl_manager_unittest.cc
+++ b/chromium/content/renderer/media/video_capture/video_capture_impl_manager_unittest.cc
@@ -142,10 +142,11 @@ class VideoCaptureImplManagerTest : public ::testing::Test,
protected:
static constexpr size_t kNumClients = 3;
- std::array<base::Closure, kNumClients> StartCaptureForAllClients(
+ std::array<base::OnceClosure, kNumClients> StartCaptureForAllClients(
bool same_session_id) {
base::RunLoop run_loop;
- base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
+ base::RepeatingClosure quit_closure =
+ BindToCurrentLoop(run_loop.QuitClosure());
InSequence s;
if (!same_session_id) {
@@ -158,7 +159,7 @@ class VideoCaptureImplManagerTest : public ::testing::Test,
EXPECT_CALL(*this, OnStarted(_))
.WillOnce(RunClosure(std::move(quit_closure)))
.RetiresOnSaturation();
- std::array<base::Closure, kNumClients> stop_callbacks;
+ std::array<base::OnceClosure, kNumClients> stop_callbacks;
media::VideoCaptureParams params;
params.requested_format = media::VideoCaptureFormat(
gfx::Size(176, 144), 30, media::PIXEL_FORMAT_I420);
@@ -172,22 +173,23 @@ class VideoCaptureImplManagerTest : public ::testing::Test,
}
void StopCaptureForAllClients(
- std::array<base::Closure, kNumClients>* stop_callbacks) {
+ std::array<base::OnceClosure, kNumClients>* stop_callbacks) {
base::RunLoop run_loop;
- base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
+ base::RepeatingClosure quit_closure =
+ BindToCurrentLoop(run_loop.QuitClosure());
EXPECT_CALL(*this, OnStopped(_))
.Times(kNumClients - 1)
.RetiresOnSaturation();
EXPECT_CALL(*this, OnStopped(_))
.WillOnce(RunClosure(std::move(quit_closure)))
.RetiresOnSaturation();
- for (const auto& stop_callback : *stop_callbacks)
- stop_callback.Run();
+ for (auto& stop_callback : *stop_callbacks)
+ std::move(stop_callback).Run();
run_loop.Run();
}
MOCK_METHOD2(OnFrameReady,
- void(const scoped_refptr<media::VideoFrame>&,
+ void(scoped_refptr<media::VideoFrame>,
base::TimeTicks estimated_capture_time));
MOCK_METHOD1(OnStarted, void(media::VideoCaptureSessionId id));
MOCK_METHOD1(OnStopped, void(media::VideoCaptureSessionId id));
@@ -204,8 +206,8 @@ class VideoCaptureImplManagerTest : public ::testing::Test,
NOTREACHED();
}
- base::Closure StartCapture(media::VideoCaptureSessionId id,
- const media::VideoCaptureParams& params) {
+ base::OnceClosure StartCapture(media::VideoCaptureSessionId id,
+ const media::VideoCaptureParams& params) {
return manager_->StartCapture(
id, params,
base::Bind(&VideoCaptureImplManagerTest::OnStateUpdate,
@@ -226,14 +228,14 @@ class VideoCaptureImplManagerTest : public ::testing::Test,
// Multiple clients with the same session id. There is only one
// media::VideoCapture object.
TEST_F(VideoCaptureImplManagerTest, MultipleClients) {
- std::array<base::Closure, kNumClients> release_callbacks;
+ std::array<base::OnceClosure, kNumClients> release_callbacks;
for (size_t i = 0; i < kNumClients; ++i)
release_callbacks[i] = manager_->UseDevice(0);
- std::array<base::Closure, kNumClients> stop_callbacks =
+ std::array<base::OnceClosure, kNumClients> stop_callbacks =
StartCaptureForAllClients(true);
StopCaptureForAllClients(&stop_callbacks);
- for (const auto& release_callback : release_callbacks)
- release_callback.Run();
+ for (auto& release_callback : release_callbacks)
+ std::move(release_callback).Run();
cleanup_run_loop_.Run();
}
@@ -244,7 +246,7 @@ TEST_F(VideoCaptureImplManagerTest, NoLeak) {
}
TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
- std::array<base::Closure, kNumClients> release_callbacks;
+ std::array<base::OnceClosure, kNumClients> release_callbacks;
blink::MediaStreamDevices video_devices;
for (size_t i = 0; i < kNumClients; ++i) {
release_callbacks[i] =
@@ -253,14 +255,15 @@ TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
video_device.session_id = static_cast<media::VideoCaptureSessionId>(i);
video_devices.push_back(video_device);
}
- std::array<base::Closure, kNumClients> stop_callbacks =
+ std::array<base::OnceClosure, kNumClients> stop_callbacks =
StartCaptureForAllClients(false);
// Call SuspendDevices(true) to suspend all clients, and expect all to be
// paused.
{
base::RunLoop run_loop;
- base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
+ base::RepeatingClosure quit_closure =
+ BindToCurrentLoop(run_loop.QuitClosure());
EXPECT_CALL(*this, OnPaused(0)).Times(1).RetiresOnSaturation();
EXPECT_CALL(*this, OnPaused(1)).Times(1).RetiresOnSaturation();
EXPECT_CALL(*this, OnPaused(2))
@@ -273,7 +276,8 @@ TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
// Call SuspendDevices(false) and expect all to be resumed.
{
base::RunLoop run_loop;
- base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
+ base::RepeatingClosure quit_closure =
+ BindToCurrentLoop(run_loop.QuitClosure());
EXPECT_CALL(*this, OnResumed(0)).Times(1).RetiresOnSaturation();
EXPECT_CALL(*this, OnResumed(1)).Times(1).RetiresOnSaturation();
EXPECT_CALL(*this, OnResumed(2))
@@ -287,7 +291,8 @@ TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
// paused.
{
base::RunLoop run_loop;
- base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
+ base::RepeatingClosure quit_closure =
+ BindToCurrentLoop(run_loop.QuitClosure());
EXPECT_CALL(*this, OnPaused(0))
.WillOnce(RunClosure(std::move(quit_closure)))
.RetiresOnSaturation();
@@ -299,7 +304,8 @@ TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
// clients to be paused.
{
base::RunLoop run_loop;
- base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
+ base::RepeatingClosure quit_closure =
+ BindToCurrentLoop(run_loop.QuitClosure());
EXPECT_CALL(*this, OnPaused(1)).Times(1).RetiresOnSaturation();
EXPECT_CALL(*this, OnPaused(2))
.WillOnce(RunClosure(std::move(quit_closure)))
@@ -318,7 +324,8 @@ TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
// Now, call SuspendDevices(false) and expect all to be resumed.
{
base::RunLoop run_loop;
- base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
+ base::RepeatingClosure quit_closure =
+ BindToCurrentLoop(run_loop.QuitClosure());
EXPECT_CALL(*this, OnResumed(0)).Times(1).RetiresOnSaturation();
EXPECT_CALL(*this, OnResumed(1)).Times(1).RetiresOnSaturation();
EXPECT_CALL(*this, OnResumed(2))
@@ -329,8 +336,8 @@ TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
}
StopCaptureForAllClients(&stop_callbacks);
- for (const auto& release_callback : release_callbacks)
- release_callback.Run();
+ for (auto& release_callback : release_callbacks)
+ std::move(release_callback).Run();
cleanup_run_loop_.Run();
}
diff --git a/chromium/content/renderer/media/video_capture/video_capture_impl_unittest.cc b/chromium/content/renderer/media/video_capture/video_capture_impl_unittest.cc
index 720b2f594db..016a43a241c 100644
--- a/chromium/content/renderer/media/video_capture/video_capture_impl_unittest.cc
+++ b/chromium/content/renderer/media/video_capture/video_capture_impl_unittest.cc
@@ -125,7 +125,7 @@ class VideoCaptureImplTest : public ::testing::Test {
protected:
// These four mocks are used to create callbacks for the different oeprations.
MOCK_METHOD2(OnFrameReady,
- void(const scoped_refptr<media::VideoFrame>&, base::TimeTicks));
+ void(scoped_refptr<media::VideoFrame>, base::TimeTicks));
MOCK_METHOD1(OnStateUpdate, void(blink::VideoCaptureState));
MOCK_METHOD1(OnDeviceFormatsInUse, void(const media::VideoCaptureFormats&));
MOCK_METHOD1(OnDeviceSupportedFormats,
diff --git a/chromium/content/renderer/media/webrtc/audio_codec_factory.cc b/chromium/content/renderer/media/webrtc/audio_codec_factory.cc
index 73abab19515..0a6a3c42625 100644
--- a/chromium/content/renderer/media/webrtc/audio_codec_factory.cc
+++ b/chromium/content/renderer/media/webrtc/audio_codec_factory.cc
@@ -17,7 +17,9 @@
#include "third_party/webrtc/api/audio_codecs/g722/audio_encoder_g722.h"
#include "third_party/webrtc/api/audio_codecs/isac/audio_decoder_isac.h"
#include "third_party/webrtc/api/audio_codecs/isac/audio_encoder_isac.h"
+#include "third_party/webrtc/api/audio_codecs/opus/audio_decoder_multi_channel_opus.h"
#include "third_party/webrtc/api/audio_codecs/opus/audio_decoder_opus.h"
+#include "third_party/webrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus.h"
#include "third_party/webrtc/api/audio_codecs/opus/audio_encoder_opus.h"
namespace content {
@@ -73,7 +75,8 @@ CreateWebrtcAudioEncoderFactory() {
return webrtc::CreateAudioEncoderFactory<
webrtc::AudioEncoderOpus, webrtc::AudioEncoderIsac,
webrtc::AudioEncoderG722, webrtc::AudioEncoderG711,
- NotAdvertisedEncoder<webrtc::AudioEncoderL16>>();
+ NotAdvertisedEncoder<webrtc::AudioEncoderL16>,
+ NotAdvertisedEncoder<webrtc::AudioEncoderMultiChannelOpus>>();
}
rtc::scoped_refptr<webrtc::AudioDecoderFactory>
@@ -81,7 +84,8 @@ CreateWebrtcAudioDecoderFactory() {
return webrtc::CreateAudioDecoderFactory<
webrtc::AudioDecoderOpus, webrtc::AudioDecoderIsac,
webrtc::AudioDecoderG722, webrtc::AudioDecoderG711,
- NotAdvertisedDecoder<webrtc::AudioDecoderL16>>();
+ NotAdvertisedDecoder<webrtc::AudioDecoderL16>,
+ NotAdvertisedDecoder<webrtc::AudioDecoderMultiChannelOpus>>();
}
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc b/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc
index 67f30de0acc..9263166edf2 100644
--- a/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc
+++ b/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <utility>
+
#include "content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h"
#include "content/renderer/media/webrtc/webrtc_util.h"
-#include <vector>
-
namespace content {
blink::WebMediaStreamTrack CreateWebMediaStreamTrack(
@@ -108,6 +108,11 @@ void FakeRTCRtpSender::GetStats(
NOTIMPLEMENTED();
}
+void FakeRTCRtpSender::SetStreams(
+ const blink::WebVector<blink::WebString>& stream_ids) {
+ NOTIMPLEMENTED();
+}
+
FakeRTCRtpReceiver::FakeRTCRtpReceiver(
const std::string& track_id,
std::vector<std::string> stream_ids,
diff --git a/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h b/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h
index e52e97439f8..bb7e968a0ca 100644
--- a/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h
+++ b/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h
@@ -6,6 +6,8 @@
#define CONTENT_RENDERER_MEDIA_WEBRTC_FAKE_RTC_RTP_TRANSCEIVER_H_
#include <memory>
+#include <string>
+#include <vector>
#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
#include "third_party/blink/public/platform/web_media_constraints.h"
@@ -50,6 +52,8 @@ class FakeRTCRtpSender : public blink::WebRTCRtpSender {
blink::WebRTCVoidRequest) override;
void GetStats(blink::WebRTCStatsReportCallback,
const std::vector<webrtc::NonStandardGroupId>&) override;
+ void SetStreams(
+ const blink::WebVector<blink::WebString>& stream_ids) override;
private:
base::Optional<std::string> track_id_;
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
index 06377b31b4b..b2ce1207c64 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
@@ -43,8 +43,7 @@ class MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate
// thread.
void OnFrame(const webrtc::VideoFrame& frame) override;
- void DoRenderFrameOnIOThread(
- const scoped_refptr<media::VideoFrame>& video_frame);
+ void DoRenderFrameOnIOThread(scoped_refptr<media::VideoFrame> video_frame);
private:
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
@@ -123,8 +122,7 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
break;
}
case webrtc::VideoFrameBuffer::Type::kI420: {
- rtc::scoped_refptr<webrtc::I420BufferInterface> yuv_buffer =
- buffer->ToI420();
+ const webrtc::I420BufferInterface* yuv_buffer = buffer->GetI420();
video_frame = media::VideoFrame::WrapExternalYuvData(
media::PIXEL_FORMAT_I420, size, gfx::Rect(size), size,
yuv_buffer->StrideY(), yuv_buffer->StrideU(), yuv_buffer->StrideV(),
@@ -134,7 +132,7 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
break;
}
case webrtc::VideoFrameBuffer::Type::kI444: {
- webrtc::I444BufferInterface* yuv_buffer = buffer->GetI444();
+ const webrtc::I444BufferInterface* yuv_buffer = buffer->GetI444();
video_frame = media::VideoFrame::WrapExternalYuvData(
media::PIXEL_FORMAT_I444, size, gfx::Rect(size), size,
yuv_buffer->StrideY(), yuv_buffer->StrideU(), yuv_buffer->StrideV(),
@@ -144,7 +142,7 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
break;
}
case webrtc::VideoFrameBuffer::Type::kI010: {
- webrtc::I010BufferInterface* yuv_buffer = buffer->GetI010();
+ const webrtc::I010BufferInterface* yuv_buffer = buffer->GetI010();
// WebRTC defines I010 data as uint16 whereas Chromium uses uint8 for all
// video formats, so conversion and cast is needed.
video_frame = media::VideoFrame::WrapExternalYuvData(
@@ -190,9 +188,8 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
video_frame->metadata()->SetTimeTicks(
media::VideoFrameMetadata::REFERENCE_TIME, render_time);
}
- video_frame->metadata()->SetTimeTicks(
- media::VideoFrameMetadata::DECODE_COMPLETE_TIMESTAMP,
- base::TimeTicks::Now());
+ video_frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::DECODE_TIME,
+ base::TimeTicks::Now());
io_task_runner_->PostTask(
FROM_HERE,
@@ -200,13 +197,12 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
video_frame));
}
-void MediaStreamRemoteVideoSource::
-RemoteVideoSourceDelegate::DoRenderFrameOnIOThread(
- const scoped_refptr<media::VideoFrame>& video_frame) {
+void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::
+ DoRenderFrameOnIOThread(scoped_refptr<media::VideoFrame> video_frame) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
TRACE_EVENT0("webrtc", "RemoteVideoSourceDelegate::DoRenderFrameOnIOThread");
// TODO(hclam): Give the estimated capture time.
- frame_callback_.Run(video_frame, base::TimeTicks());
+ frame_callback_.Run(std::move(video_frame), base::TimeTicks());
}
MediaStreamRemoteVideoSource::MediaStreamRemoteVideoSource(
@@ -214,8 +210,8 @@ MediaStreamRemoteVideoSource::MediaStreamRemoteVideoSource(
: observer_(std::move(observer)) {
// The callback will be automatically cleared when 'observer_' goes out of
// scope and no further callbacks will occur.
- observer_->SetCallback(base::Bind(&MediaStreamRemoteVideoSource::OnChanged,
- base::Unretained(this)));
+ observer_->SetCallback(base::BindRepeating(
+ &MediaStreamRemoteVideoSource::OnChanged, base::Unretained(this)));
}
MediaStreamRemoteVideoSource::~MediaStreamRemoteVideoSource() {
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
index 0386ff0b152..93aff41f6e4 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
@@ -176,7 +176,11 @@ TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) {
webrtc::I420Buffer::SetBlack(buffer);
source()->SinkInterfaceForTesting()->OnFrame(
- webrtc::VideoFrame(buffer, webrtc::kVideoRotation_0, 1000));
+ webrtc::VideoFrame::Builder()
+ .set_video_frame_buffer(buffer)
+ .set_rotation(webrtc::kVideoRotation_0)
+ .set_timestamp_us(1000)
+ .build());
run_loop.Run();
EXPECT_EQ(1, sink.number_of_frames());
diff --git a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
index cb4cee1bfd2..09c5bc19933 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
@@ -91,14 +91,13 @@ class MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter
// destroyed.
void ReleaseSourceOnMainThread();
- void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
+ void OnVideoFrameOnIO(scoped_refptr<media::VideoFrame> frame,
base::TimeTicks estimated_capture_time);
private:
friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>;
- void OnVideoFrameOnWorkerThread(
- const scoped_refptr<media::VideoFrame>& frame);
+ void OnVideoFrameOnWorkerThread(scoped_refptr<media::VideoFrame> frame);
virtual ~WebRtcVideoSourceAdapter();
@@ -188,7 +187,7 @@ void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
}
void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::OnVideoFrameOnIO(
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
base::TimeTicks estimated_capture_time) {
DCHECK(io_thread_checker_.CalledOnValidThread());
render_task_runner_->PostTask(
@@ -198,15 +197,15 @@ void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::OnVideoFrameOnIO(
libjingle_worker_thread_->PostTask(
FROM_HERE,
base::BindOnce(&WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread,
- this, frame));
+ this, std::move(frame)));
}
void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
- OnVideoFrameOnWorkerThread(const scoped_refptr<media::VideoFrame>& frame) {
+ OnVideoFrameOnWorkerThread(scoped_refptr<media::VideoFrame> frame) {
DCHECK(libjingle_worker_thread_->BelongsToCurrentThread());
base::AutoLock auto_lock(video_source_stop_lock_);
if (video_source_)
- video_source_->OnFrameCaptured(frame);
+ video_source_->OnFrameCaptured(std::move(frame));
}
MediaStreamVideoWebRtcSink::MediaStreamVideoWebRtcSink(
diff --git a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h
index 4874874da6a..a5156d8c67a 100644
--- a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h
+++ b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h
@@ -207,8 +207,8 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
return PeerConnectionInterface::kIceGatheringNew;
}
- bool StartRtcEventLog(rtc::PlatformFile file,
- int64_t max_size_bytes) override {
+ bool StartRtcEventLog(std::unique_ptr<webrtc::RtcEventLogOutput> output,
+ int64_t output_period_ms) override {
NOTIMPLEMENTED();
return false;
}
diff --git a/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h b/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h
index 00026e31c8c..a0ec3183ac5 100644
--- a/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h
+++ b/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h
@@ -36,6 +36,9 @@ class MockWebRTCPeerConnectionHandlerClient
void(webrtc::PeerConnectionInterface::IceGatheringState state));
MOCK_METHOD1(DidChangeIceConnectionState,
void(webrtc::PeerConnectionInterface::IceConnectionState state));
+ MOCK_METHOD1(
+ DidChangePeerConnectionState,
+ void(webrtc::PeerConnectionInterface::PeerConnectionState state));
void DidAddReceiverPlanB(
std::unique_ptr<blink::WebRTCRtpReceiver> web_rtp_receiver) override {
DidAddReceiverPlanBForMock(&web_rtp_receiver);
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index 393926e6f89..f9edc70eb11 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -59,13 +59,18 @@
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_local_frame.h"
-#include "third_party/webrtc/api/create_peerconnection_factory.h"
+#include "third_party/webrtc/api/call/call_factory_interface.h"
+#include "third_party/webrtc/api/peer_connection_interface.h"
+#include "third_party/webrtc/api/rtc_event_log/rtc_event_log_factory.h"
#include "third_party/webrtc/api/video_track_source_proxy.h"
#include "third_party/webrtc/media/engine/fake_video_codec_factory.h"
#include "third_party/webrtc/media/engine/multiplex_codec_factory.h"
+#include "third_party/webrtc/media/engine/webrtc_media_engine.h"
+#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
#include "third_party/webrtc/modules/video_coding/codecs/h264/include/h264.h"
#include "third_party/webrtc/rtc_base/ref_counted_object.h"
#include "third_party/webrtc/rtc_base/ssl_adapter.h"
+#include "third_party/webrtc_overrides/task_queue_factory.h"
namespace content {
@@ -313,12 +318,24 @@ void PeerConnectionDependencyFactory::InitializeSignalingThread(
std::make_unique<webrtc::FakeVideoDecoderFactory>();
}
- pc_factory_ = webrtc::CreatePeerConnectionFactory(
- worker_thread_ /* network thread */, worker_thread_, signaling_thread_,
- audio_device_.get(), CreateWebrtcAudioEncoderFactory(),
- CreateWebrtcAudioDecoderFactory(), std::move(webrtc_encoder_factory),
- std::move(webrtc_decoder_factory), nullptr /* audio_mixer */,
- nullptr /* audio_processing */);
+ webrtc::PeerConnectionFactoryDependencies pcf_deps;
+ pcf_deps.worker_thread = worker_thread_;
+ pcf_deps.network_thread = worker_thread_;
+ pcf_deps.signaling_thread = signaling_thread_;
+ pcf_deps.task_queue_factory = CreateWebRtcTaskQueueFactory();
+ pcf_deps.call_factory = webrtc::CreateCallFactory();
+ pcf_deps.event_log_factory = std::make_unique<webrtc::RtcEventLogFactory>(
+ pcf_deps.task_queue_factory.get());
+ cricket::MediaEngineDependencies media_deps;
+ media_deps.task_queue_factory = pcf_deps.task_queue_factory.get();
+ media_deps.adm = audio_device_.get();
+ media_deps.audio_encoder_factory = CreateWebrtcAudioEncoderFactory();
+ media_deps.audio_decoder_factory = CreateWebrtcAudioDecoderFactory();
+ media_deps.video_encoder_factory = std::move(webrtc_encoder_factory);
+ media_deps.video_decoder_factory = std::move(webrtc_decoder_factory);
+ media_deps.audio_processing = webrtc::AudioProcessingBuilder().Create();
+ pcf_deps.media_engine = cricket::CreateMediaEngine(std::move(media_deps));
+ pc_factory_ = webrtc::CreateModularPeerConnectionFactory(std::move(pcf_deps));
CHECK(pc_factory_.get());
webrtc::PeerConnectionFactoryInterface::Options factory_options;
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc b/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc
index c21bed75708..c8e1637cf0d 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc
@@ -335,6 +335,27 @@ static const char* GetIceConnectionStateString(
}
}
+static const char* GetConnectionStateString(
+ webrtc::PeerConnectionInterface::PeerConnectionState state) {
+ switch (state) {
+ case webrtc::PeerConnectionInterface::PeerConnectionState::kNew:
+ return "new";
+ case webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting:
+ return "connecting";
+ case webrtc::PeerConnectionInterface::PeerConnectionState::kConnected:
+ return "connected";
+ case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected:
+ return "disconnected";
+ case webrtc::PeerConnectionInterface::PeerConnectionState::kFailed:
+ return "failed";
+ case webrtc::PeerConnectionInterface::PeerConnectionState::kClosed:
+ return "closed";
+ default:
+ NOTREACHED();
+ return "";
+ }
+}
+
static const char* GetIceGatheringStateString(
webrtc::PeerConnectionInterface::IceGatheringState state) {
switch (state) {
@@ -923,6 +944,17 @@ void PeerConnectionTracker::TrackSignalingStateChange(
id, "signalingStateChange", GetSignalingStateString(state));
}
+void PeerConnectionTracker::TrackLegacyIceConnectionStateChange(
+ RTCPeerConnectionHandler* pc_handler,
+ webrtc::PeerConnectionInterface::IceConnectionState state) {
+ DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
+ SendPeerConnectionUpdate(id, "legacyIceConnectionStateChange",
+ GetIceConnectionStateString(state));
+}
+
void PeerConnectionTracker::TrackIceConnectionStateChange(
RTCPeerConnectionHandler* pc_handler,
webrtc::PeerConnectionInterface::IceConnectionState state) {
@@ -935,6 +967,17 @@ void PeerConnectionTracker::TrackIceConnectionStateChange(
GetIceConnectionStateString(state));
}
+void PeerConnectionTracker::TrackConnectionStateChange(
+ RTCPeerConnectionHandler* pc_handler,
+ webrtc::PeerConnectionInterface::PeerConnectionState state) {
+ DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
+ SendPeerConnectionUpdate(id, "connectionStateChange",
+ GetConnectionStateString(state));
+}
+
void PeerConnectionTracker::TrackIceGatheringStateChange(
RTCPeerConnectionHandler* pc_handler,
webrtc::PeerConnectionInterface::IceGatheringState state) {
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_tracker.h b/chromium/content/renderer/media/webrtc/peer_connection_tracker.h
index ee338307d42..3d81e5f1aa5 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_tracker.h
+++ b/chromium/content/renderer/media/webrtc/peer_connection_tracker.h
@@ -169,12 +169,30 @@ class CONTENT_EXPORT PeerConnectionTracker
RTCPeerConnectionHandler* pc_handler,
webrtc::PeerConnectionInterface::SignalingState state);
- // Sends an update when the Ice connection state
- // of a PeerConnection has changed.
+ // Sends an update when the ICE connection state of a PeerConnection has
+ // changed. There's a legacy and non-legacy version. The non-legacy version
+ // reflects the blink::RTCPeerConnection::iceConnectionState.
+ //
+ // "Legacy" usage: In Unifed Plan, TrackLegacyIceConnectionStateChange() is
+ // used to report the webrtc::PeerConnection layer implementation of the
+ // state, which might not always be the same as the
+ // blink::RTCPeerConnection::iceConnectionState reported with
+ // TrackIceConnectionStateChange(). In Plan B, the webrtc::PeerConnection
+ // layer implementation is the only iceConnectionState version, and
+ // TrackLegacyIceConnectionStateChange() is not applicable.
+ virtual void TrackLegacyIceConnectionStateChange(
+ RTCPeerConnectionHandler* pc_handler,
+ webrtc::PeerConnectionInterface::IceConnectionState state);
virtual void TrackIceConnectionStateChange(
RTCPeerConnectionHandler* pc_handler,
webrtc::PeerConnectionInterface::IceConnectionState state);
+ // Sends an update when the connection state
+ // of a PeerConnection has changed.
+ virtual void TrackConnectionStateChange(
+ RTCPeerConnectionHandler* pc_handler,
+ webrtc::PeerConnectionInterface::PeerConnectionState state);
+
// Sends an update when the Ice gathering state
// of a PeerConnection has changed.
virtual void TrackIceGatheringStateChange(
diff --git a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
index 390c837dddc..c5a8fd25eb4 100644
--- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
@@ -2063,16 +2063,32 @@ void RTCPeerConnectionHandler::OnIceConnectionChange(
}
track_metrics_.IceConnectionChange(new_state);
- if (peer_connection_tracker_)
- peer_connection_tracker_->TrackIceConnectionStateChange(this, new_state);
if (!is_closed_)
client_->DidChangeIceConnectionState(new_state);
}
+void RTCPeerConnectionHandler::TrackIceConnectionStateChange(
+ WebRTCPeerConnectionHandler::IceConnectionStateVersion version,
+ webrtc::PeerConnectionInterface::IceConnectionState state) {
+ if (!peer_connection_tracker_)
+ return;
+ switch (version) {
+ case WebRTCPeerConnectionHandler::IceConnectionStateVersion::kLegacy:
+ peer_connection_tracker_->TrackLegacyIceConnectionStateChange(this,
+ state);
+ break;
+ case WebRTCPeerConnectionHandler::IceConnectionStateVersion::kDefault:
+ peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
+ break;
+ }
+}
+
// Called any time the combined peerconnection state changes
void RTCPeerConnectionHandler::OnConnectionChange(
webrtc::PeerConnectionInterface::PeerConnectionState new_state) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ if (peer_connection_tracker_)
+ peer_connection_tracker_->TrackConnectionStateChange(this, new_state);
if (!is_closed_)
client_->DidChangePeerConnectionState(new_state);
}
diff --git a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h
index 69c3fb11dbd..93d5bf988d1 100644
--- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h
+++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h
@@ -180,6 +180,10 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
const base::RepeatingClosure& closure,
const char* trace_event_name) override;
+ void TrackIceConnectionStateChange(
+ WebRTCPeerConnectionHandler::IceConnectionStateVersion version,
+ webrtc::PeerConnectionInterface::IceConnectionState state) override;
+
// Delegate functions to allow for mocking of WebKit interfaces.
// getStats takes ownership of request parameter.
virtual void getStats(const scoped_refptr<LocalRTCStatsRequest>& request);
diff --git a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
index ee2e33d6ad7..2dead862284 100644
--- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
@@ -203,6 +203,10 @@ class MockPeerConnectionTracker : public PeerConnectionTracker {
MOCK_METHOD2(TrackIceConnectionStateChange,
void(RTCPeerConnectionHandler* pc_handler,
webrtc::PeerConnectionInterface::IceConnectionState state));
+ MOCK_METHOD2(
+ TrackConnectionStateChange,
+ void(RTCPeerConnectionHandler* pc_handler,
+ webrtc::PeerConnectionInterface::PeerConnectionState state));
MOCK_METHOD2(TrackIceGatheringStateChange,
void(RTCPeerConnectionHandler* pc_handler,
webrtc::PeerConnectionInterface::IceGatheringState state));
@@ -312,8 +316,7 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
media::CHANNEL_LAYOUT_STEREO,
media::AudioParameters::kAudioCDSampleRate / 100),
false /* disable_local_echo */, blink::AudioProcessingProperties(),
- base::Bind(&RTCPeerConnectionHandlerTest::OnAudioSourceStarted),
- mock_dependency_factory_.get(),
+ base::DoNothing(), mock_dependency_factory_.get(),
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
audio_source->SetAllowInvalidRenderFrameIdForTesting(true);
blink_audio_source.SetPlatformSource(
@@ -377,10 +380,6 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
blink::MediaStreamVideoTrack::GetVideoTrack(track)->Stop();
}
- static void OnAudioSourceStarted(blink::WebPlatformMediaStreamSource* source,
- blink::MediaStreamRequestResult result,
- const blink::WebString& result_name) {}
-
bool AddStream(const blink::WebMediaStream& web_stream) {
size_t senders_size_before_add = senders_.size();
for (const auto& web_audio_track : web_stream.AudioTracks()) {
@@ -1028,76 +1027,124 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
webrtc::PeerConnectionInterface::IceConnectionState new_state =
webrtc::PeerConnectionInterface::kIceConnectionNew;
- EXPECT_CALL(*mock_tracker_.get(),
- TrackIceConnectionStateChange(
- pc_handler_.get(),
- webrtc::PeerConnectionInterface::kIceConnectionNew));
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionNew));
pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionChecking;
- EXPECT_CALL(*mock_tracker_.get(),
- TrackIceConnectionStateChange(
- pc_handler_.get(),
- webrtc::PeerConnectionInterface::kIceConnectionChecking));
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionChecking));
pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionConnected;
- EXPECT_CALL(*mock_tracker_.get(),
- TrackIceConnectionStateChange(
- pc_handler_.get(),
- webrtc::PeerConnectionInterface::kIceConnectionConnected));
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionConnected));
pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionCompleted;
- EXPECT_CALL(*mock_tracker_.get(),
- TrackIceConnectionStateChange(
- pc_handler_.get(),
- webrtc::PeerConnectionInterface::kIceConnectionCompleted));
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionCompleted));
pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionFailed;
- EXPECT_CALL(*mock_tracker_.get(),
- TrackIceConnectionStateChange(
- pc_handler_.get(),
- webrtc::PeerConnectionInterface::kIceConnectionFailed));
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionFailed));
pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionDisconnected;
- EXPECT_CALL(*mock_tracker_.get(),
- TrackIceConnectionStateChange(
- pc_handler_.get(),
- webrtc::PeerConnectionInterface::kIceConnectionDisconnected));
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionDisconnected));
pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionClosed;
- EXPECT_CALL(*mock_tracker_.get(),
- TrackIceConnectionStateChange(
- pc_handler_.get(),
- webrtc::PeerConnectionInterface::kIceConnectionClosed));
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionClosed));
pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
}
+TEST_F(RTCPeerConnectionHandlerTest, OnConnectionChange) {
+ testing::InSequence sequence;
+
+ webrtc::PeerConnectionInterface::PeerConnectionState new_state =
+ webrtc::PeerConnectionInterface::PeerConnectionState::kNew;
+ EXPECT_CALL(*mock_tracker_.get(),
+ TrackConnectionStateChange(
+ pc_handler_.get(),
+ webrtc::PeerConnectionInterface::PeerConnectionState::kNew));
+ EXPECT_CALL(*mock_client_.get(),
+ DidChangePeerConnectionState(
+ webrtc::PeerConnectionInterface::PeerConnectionState::kNew));
+ pc_handler_->observer()->OnConnectionChange(new_state);
+
+ new_state = webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting;
+ EXPECT_CALL(
+ *mock_tracker_.get(),
+ TrackConnectionStateChange(
+ pc_handler_.get(),
+ webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting));
+ EXPECT_CALL(
+ *mock_client_.get(),
+ DidChangePeerConnectionState(
+ webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting));
+ pc_handler_->observer()->OnConnectionChange(new_state);
+
+ new_state = webrtc::PeerConnectionInterface::PeerConnectionState::kConnected;
+ EXPECT_CALL(
+ *mock_tracker_.get(),
+ TrackConnectionStateChange(
+ pc_handler_.get(),
+ webrtc::PeerConnectionInterface::PeerConnectionState::kConnected));
+ EXPECT_CALL(
+ *mock_client_.get(),
+ DidChangePeerConnectionState(
+ webrtc::PeerConnectionInterface::PeerConnectionState::kConnected));
+ pc_handler_->observer()->OnConnectionChange(new_state);
+
+ new_state =
+ webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected;
+ EXPECT_CALL(
+ *mock_tracker_.get(),
+ TrackConnectionStateChange(
+ pc_handler_.get(),
+ webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected));
+ EXPECT_CALL(
+ *mock_client_.get(),
+ DidChangePeerConnectionState(
+ webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected));
+ pc_handler_->observer()->OnConnectionChange(new_state);
+
+ new_state = webrtc::PeerConnectionInterface::PeerConnectionState::kFailed;
+ EXPECT_CALL(
+ *mock_tracker_.get(),
+ TrackConnectionStateChange(
+ pc_handler_.get(),
+ webrtc::PeerConnectionInterface::PeerConnectionState::kFailed));
+ EXPECT_CALL(
+ *mock_client_.get(),
+ DidChangePeerConnectionState(
+ webrtc::PeerConnectionInterface::PeerConnectionState::kFailed));
+ pc_handler_->observer()->OnConnectionChange(new_state);
+
+ new_state = webrtc::PeerConnectionInterface::PeerConnectionState::kClosed;
+ EXPECT_CALL(
+ *mock_tracker_.get(),
+ TrackConnectionStateChange(
+ pc_handler_.get(),
+ webrtc::PeerConnectionInterface::PeerConnectionState::kClosed));
+ EXPECT_CALL(
+ *mock_client_.get(),
+ DidChangePeerConnectionState(
+ webrtc::PeerConnectionInterface::PeerConnectionState::kClosed));
+ pc_handler_->observer()->OnConnectionChange(new_state);
+}
+
TEST_F(RTCPeerConnectionHandlerTest, OnIceGatheringChange) {
testing::InSequence sequence;
EXPECT_CALL(*mock_tracker_.get(),
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc
index f8c8d55c4d0..2af21e90e01 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc
@@ -373,4 +373,9 @@ RTCRtpReceiverOnlyTransceiver::FiredDirection() const {
return webrtc::RtpTransceiverDirection::kSendOnly;
}
+webrtc::RTCError RTCRtpReceiverOnlyTransceiver::SetCodecPreferences(
+ blink::WebVector<webrtc::RtpCodecCapability>) {
+ NOTIMPLEMENTED();
+ return {};
+}
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h
index d7e3f3abfb1..f0e0ca09cca 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h
@@ -162,6 +162,8 @@ class CONTENT_EXPORT RTCRtpReceiverOnlyTransceiver
const override;
base::Optional<webrtc::RtpTransceiverDirection> FiredDirection()
const override;
+ webrtc::RTCError SetCodecPreferences(
+ blink::WebVector<webrtc::RtpCodecCapability>) override;
private:
std::unique_ptr<blink::WebRTCRtpReceiver> receiver_;
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc
index cd9517f63e7..c75144455eb 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc
@@ -277,6 +277,15 @@ class RTCRtpSender::RTCRtpSenderInternal
return true;
}
+ void SetStreams(std::vector<std::string> stream_ids) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ signaling_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &RTCRtpSender::RTCRtpSenderInternal::SetStreamsOnSignalingThread,
+ this, std::move(stream_ids)));
+ }
+
private:
friend struct RTCRtpSender::RTCRtpSenderInternalTraits;
@@ -338,6 +347,11 @@ class RTCRtpSender::RTCRtpSenderInternal
std::move(callback).Run(std::move(result));
}
+ void SetStreamsOnSignalingThread(std::vector<std::string> stream_ids) {
+ DCHECK(signaling_task_runner_->BelongsToCurrentThread());
+ webrtc_sender_->SetStreams(stream_ids);
+ }
+
const scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection_;
const scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map_;
// Task runners and webrtc sender: Same information as stored in
@@ -460,6 +474,15 @@ void RTCRtpSender::GetStats(
internal_->GetStats(std::move(callback), exposed_group_ids);
}
+void RTCRtpSender::SetStreams(
+ const blink::WebVector<blink::WebString>& stream_ids) {
+ std::vector<std::string> ids;
+ for (auto stream_id : stream_ids)
+ ids.emplace_back(stream_id.Utf8());
+
+ internal_->SetStreams(std::move(ids));
+}
+
void RTCRtpSender::ReplaceTrack(blink::WebMediaStreamTrack with_track,
base::OnceCallback<void(bool)> callback) {
internal_->ReplaceTrack(std::move(with_track), std::move(callback));
@@ -531,4 +554,10 @@ RTCRtpSenderOnlyTransceiver::FiredDirection() const {
return webrtc::RtpTransceiverDirection::kSendOnly;
}
+webrtc::RTCError RTCRtpSenderOnlyTransceiver::SetCodecPreferences(
+ blink::WebVector<webrtc::RtpCodecCapability>) {
+ NOTIMPLEMENTED();
+ return {};
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h
index 2c026e53852..c8babf98935 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_MEDIA_WEBRTC_RTC_RTP_SENDER_H_
#include <memory>
+#include <string>
#include <vector>
#include "base/callback.h"
@@ -141,6 +142,8 @@ class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender {
blink::WebRTCVoidRequest) override;
void GetStats(blink::WebRTCStatsReportCallback,
const std::vector<webrtc::NonStandardGroupId>&) override;
+ void SetStreams(
+ const blink::WebVector<blink::WebString>& stream_ids) override;
// The ReplaceTrack() that takes a blink::WebRTCVoidRequest is implemented on
// top of this, which returns the result in a callback instead. Allows doing
@@ -160,7 +163,8 @@ class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender {
class CONTENT_EXPORT RTCRtpSenderOnlyTransceiver
: public blink::WebRTCRtpTransceiver {
public:
- RTCRtpSenderOnlyTransceiver(std::unique_ptr<blink::WebRTCRtpSender> sender);
+ explicit RTCRtpSenderOnlyTransceiver(
+ std::unique_ptr<blink::WebRTCRtpSender> sender);
~RTCRtpSenderOnlyTransceiver() override;
blink::WebRTCRtpTransceiverImplementationType ImplementationType()
@@ -176,6 +180,8 @@ class CONTENT_EXPORT RTCRtpSenderOnlyTransceiver
const override;
base::Optional<webrtc::RtpTransceiverDirection> FiredDirection()
const override;
+ webrtc::RTCError SetCodecPreferences(
+ blink::WebVector<webrtc::RtpCodecCapability>) override;
private:
std::unique_ptr<blink::WebRTCRtpSender> sender_;
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_source.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_source.cc
index 0a4ace31387..9b7bee96636 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_source.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_source.cc
@@ -49,4 +49,8 @@ base::Optional<double> RTCRtpSource::AudioLevel() const {
return std::pow(10.0, -(double)rfc_level / 20.0);
}
+uint32_t RTCRtpSource::RtpTimestamp() const {
+ return source_.rtp_timestamp();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_source.h b/chromium/content/renderer/media/webrtc/rtc_rtp_source.h
index 353d4de2628..8821d2d4c56 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_source.h
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_source.h
@@ -22,6 +22,7 @@ class CONTENT_EXPORT RTCRtpSource : public blink::WebRTCRtpSource {
double TimestampMs() const override;
uint32_t Source() const override;
base::Optional<double> AudioLevel() const override;
+ uint32_t RtpTimestamp() const override;
private:
const webrtc::RtpSource source_;
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.cc
index 23cd9de013e..ab36db44b25 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.cc
@@ -240,6 +240,11 @@ class RTCRtpTransceiver::RTCRtpTransceiverInternal
state_.set_direction(webrtc_transceiver_->direction());
}
+ webrtc::RTCError setCodecPreferences(
+ std::vector<webrtc::RtpCodecCapability> codec_preferences) {
+ return webrtc_transceiver_->SetCodecPreferences(codec_preferences);
+ }
+
private:
friend struct RTCRtpTransceiver::RTCRtpTransceiverInternalTraits;
@@ -370,4 +375,8 @@ RTCRtpTransceiver::FiredDirection() const {
return internal_->state().fired_direction();
}
+webrtc::RTCError RTCRtpTransceiver::SetCodecPreferences(
+ blink::WebVector<webrtc::RtpCodecCapability> codec_preferences) {
+ return internal_->setCodecPreferences(codec_preferences.ReleaseVector());
+}
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.h b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.h
index 0667322b869..e99719e2054 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.h
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.h
@@ -178,6 +178,8 @@ class CONTENT_EXPORT RTCRtpTransceiver : public blink::WebRTCRtpTransceiver {
const override;
base::Optional<webrtc::RtpTransceiverDirection> FiredDirection()
const override;
+ webrtc::RTCError SetCodecPreferences(
+ blink::WebVector<webrtc::RtpCodecCapability>) override;
private:
class RTCRtpTransceiverInternal;
diff --git a/chromium/content/renderer/media/webrtc/rtc_stats.cc b/chromium/content/renderer/media/webrtc/rtc_stats.cc
index 0d8bde55598..7ac45d214ef 100644
--- a/chromium/content/renderer/media/webrtc/rtc_stats.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_stats.cc
@@ -35,6 +35,11 @@ class RTCStatsWhitelist {
whitelisted_stats_types_.insert(webrtc::RTCRTPStreamStats::kType);
whitelisted_stats_types_.insert(webrtc::RTCInboundRTPStreamStats::kType);
whitelisted_stats_types_.insert(webrtc::RTCOutboundRTPStreamStats::kType);
+ whitelisted_stats_types_.insert(
+ webrtc::RTCRemoteInboundRtpStreamStats::kType);
+ whitelisted_stats_types_.insert(webrtc::RTCMediaSourceStats::kType);
+ whitelisted_stats_types_.insert(webrtc::RTCAudioSourceStats::kType);
+ whitelisted_stats_types_.insert(webrtc::RTCVideoSourceStats::kType);
whitelisted_stats_types_.insert(webrtc::RTCTransportStats::kType);
}
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder.cc b/chromium/content/renderer/media/webrtc/rtc_video_decoder.cc
deleted file mode 100644
index 7d692a5c758..00000000000
--- a/chromium/content/renderer/media/webrtc/rtc_video_decoder.cc
+++ /dev/null
@@ -1,944 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/webrtc/rtc_video_decoder.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_runner_util.h"
-#include "base/threading/thread_restrictions.h"
-#include "build/build_config.h"
-#include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
-#include "gpu/command_buffer/common/mailbox_holder.h"
-#include "media/base/bind_to_current_loop.h"
-#include "media/video/gpu_video_accelerator_factories.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/webrtc/api/video/video_frame.h"
-#include "third_party/webrtc/media/base/vp9_profile.h"
-#include "third_party/webrtc/modules/video_coding/codecs/h264/include/h264.h"
-#include "third_party/webrtc/rtc_base/bind.h"
-#include "third_party/webrtc/rtc_base/ref_count.h"
-#include "third_party/webrtc/rtc_base/ref_counted_object.h"
-
-#if defined(OS_WIN)
-#include "base/command_line.h"
-#include "base/win/windows_version.h"
-#include "content/public/common/content_switches.h"
-#endif // defined(OS_WIN)
-
-namespace content {
-
-const int32_t RTCVideoDecoder::ID_LAST = 0x3FFFFFFF;
-const int32_t RTCVideoDecoder::ID_HALF = 0x20000000;
-const int32_t RTCVideoDecoder::ID_INVALID = -1;
-
-// Number of consecutive frames that can be lost due to a VDA error before
-// falling back to SW implementation.
-const uint32_t kNumVDAErrorsBeforeSWFallback = 5;
-
-// Maximum number of concurrent VDA::Decode() operations RVD will maintain.
-// Higher values allow better pipelining in the GPU, but also require more
-// resources.
-static const size_t kMaxInFlightDecodes = 8;
-
-// Maximum number of pending WebRTC buffers that are waiting for shared memory.
-static const size_t kMaxNumOfPendingBuffers = 8;
-
-// Number of allocated shared memory segments.
-static const size_t kNumSharedMemorySegments = 16;
-
-RTCVideoDecoder::BufferData::BufferData(int32_t bitstream_buffer_id,
- uint32_t timestamp,
- size_t size,
- const gfx::Rect& visible_rect)
- : bitstream_buffer_id(bitstream_buffer_id),
- timestamp(timestamp),
- size(size),
- visible_rect(visible_rect) {}
-
-RTCVideoDecoder::BufferData::BufferData() {}
-
-RTCVideoDecoder::BufferData::~BufferData() {}
-
-RTCVideoDecoder::RTCVideoDecoder(webrtc::VideoCodecType type,
- media::GpuVideoAcceleratorFactories* factories)
- : vda_error_counter_(0),
- video_codec_type_(type),
- factories_(factories),
- next_picture_buffer_id_(0),
- state_(UNINITIALIZED),
- decode_complete_callback_(nullptr),
- num_shm_buffers_(0),
- next_bitstream_buffer_id_(0),
- reset_bitstream_buffer_id_(ID_INVALID),
- weak_factory_(this) {
- DCHECK(!factories_->GetTaskRunner()->BelongsToCurrentThread());
-}
-
-RTCVideoDecoder::~RTCVideoDecoder() {
- DVLOG(2) << "~RTCVideoDecoder";
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
- DestroyVDA();
-
- // Delete all shared memories.
- ClearPendingBuffers();
-}
-
-// static
-std::unique_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
- const webrtc::SdpVideoFormat& format,
- media::GpuVideoAcceleratorFactories* factories) {
- const webrtc::VideoCodecType type =
- webrtc::PayloadStringToCodecType(format.name);
- std::unique_ptr<RTCVideoDecoder> decoder;
-// See https://bugs.chromium.org/p/webrtc/issues/detail?id=5717.
-#if defined(OS_WIN)
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableWin7WebRtcHWH264Decoding) &&
- type == webrtc::kVideoCodecH264 &&
- base::win::GetVersion() == base::win::VERSION_WIN7) {
- DLOG(ERROR) << "H264 HW decoding on Win7 is not supported.";
- return decoder;
- }
-#endif // defined(OS_WIN)
- // Convert WebRTC codec type to media codec profile.
- media::VideoCodecProfile profile;
- switch (type) {
- case webrtc::kVideoCodecVP8:
- profile = media::VP8PROFILE_ANY;
- break;
- case webrtc::kVideoCodecVP9: {
- const webrtc::VP9Profile vp9_profile =
- webrtc::ParseSdpForVP9Profile(format.parameters)
- .value_or(webrtc::VP9Profile::kProfile0);
- switch (vp9_profile) {
- case webrtc::VP9Profile::kProfile2:
- profile = media::VP9PROFILE_PROFILE2;
- break;
- case webrtc::VP9Profile::kProfile0:
- default:
- profile = media::VP9PROFILE_PROFILE0;
- break;
- }
- break;
- }
- case webrtc::kVideoCodecH264:
- profile = media::H264PROFILE_MAIN;
- break;
- default:
- DVLOG(2) << "Video codec not supported:" << type;
- return decoder;
- }
-
- // This wait is necessary because this task is completed in GPU process
- // asynchronously but WebRTC API is synchronous.
- base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
- base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- decoder.reset(new RTCVideoDecoder(type, factories));
- decoder->factories_->GetTaskRunner()->PostTask(
- FROM_HERE,
- base::BindOnce(&RTCVideoDecoder::CreateVDA,
- base::Unretained(decoder.get()), profile, &waiter));
- waiter.Wait();
- // |decoder->vda_| is nullptr if the codec is not supported.
- if (decoder->vda_)
- decoder->state_ = INITIALIZED;
- else
- factories->GetTaskRunner()->DeleteSoon(FROM_HERE, decoder.release());
- return decoder;
-}
-
-int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings,
- int32_t /*numberOfCores*/) {
- DVLOG(2) << "InitDecode";
- DCHECK_EQ(video_codec_type_, codecSettings->codecType);
-
- base::AutoLock auto_lock(lock_);
- if (state_ == UNINITIALIZED || state_ == DECODE_ERROR) {
- LOG(ERROR) << "VDA is not initialized. state=" << state_;
- return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_UNINITIALIZED);
- }
-
- return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_OK);
-}
-
-int32_t RTCVideoDecoder::Decode(
- const webrtc::EncodedImage& input_image,
- bool missing_frames,
- int64_t render_time_ms) {
- DVLOG(3) << "Decode";
-
- // Hardware VP9 decoders don't handle more than one spatial layer. Fall back
- // to software decoding. See https://crbug.com/webrtc/9304,
- // https://crbug.com/webrtc/9518.
- if (video_codec_type_ == webrtc::kVideoCodecVP9 &&
- input_image.SpatialIndex().value_or(0) > 0) {
- return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
- }
-
- base::AutoLock auto_lock(lock_);
- if (state_ == UNINITIALIZED || !decode_complete_callback_) {
- LOG(ERROR) << "The decoder has not initialized.";
- return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
- }
-
- if (state_ == DECODE_ERROR) {
- LOG(ERROR) << "Decoding error occurred.";
- // Try reseting the session up to |kNumVDAErrorsHandled| times.
- if (ShouldFallbackToSoftwareDecode())
- return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
- base::AutoUnlock auto_unlock(lock_);
- Release();
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
-
- if (missing_frames || !input_image._completeFrame) {
- DLOG(ERROR) << "Missing or incomplete frames.";
- // Unlike the SW decoder in libvpx, hw decoder cannot handle broken frames.
- // Return an error to request a key frame.
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
-
- // Most platforms' VDA implementations support mid-stream resolution change
- // internally. Platforms whose VDAs fail to support mid-stream resolution
- // change gracefully need to have their clients cover for them, and we do that
- // here.
-#ifdef ANDROID
- const bool kVDACanHandleMidstreamResize = false;
-#else
- const bool kVDACanHandleMidstreamResize = true;
-#endif
-
- bool need_to_reset_for_midstream_resize = false;
- const gfx::Size new_frame_size(input_image._encodedWidth,
- input_image._encodedHeight);
- if (!new_frame_size.IsEmpty() && new_frame_size != frame_size_) {
- DVLOG(2) << "Got new size=" << new_frame_size.ToString();
-
- if (new_frame_size.width() > max_resolution_.width() ||
- new_frame_size.width() < min_resolution_.width() ||
- new_frame_size.height() > max_resolution_.height() ||
- new_frame_size.height() < min_resolution_.height()) {
- DVLOG(1) << "Resolution unsupported, falling back to software decode";
- return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
- }
-
- gfx::Size prev_frame_size = frame_size_;
- frame_size_ = new_frame_size;
- if (!kVDACanHandleMidstreamResize && !prev_frame_size.IsEmpty() &&
- prev_frame_size != frame_size_) {
- need_to_reset_for_midstream_resize = true;
- }
- } else if (IsFirstBufferAfterReset(next_bitstream_buffer_id_,
- reset_bitstream_buffer_id_)) {
- // TODO(wuchengli): VDA should handle it. Remove this when
- // http://crosbug.com/p/21913 is fixed.
-
- DCHECK(new_frame_size.IsEmpty());
- if (vda_error_counter_ ||
- input_image._frameType == webrtc::VideoFrameType::kVideoFrameKey) {
- ++vda_error_counter_;
- }
-
- if (ShouldFallbackToSoftwareDecode())
- return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
- DVLOG(1) << "The first frame should have resolution. Drop this.";
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
-
- // Create buffer metadata.
- BufferData buffer_data(next_bitstream_buffer_id_, input_image.Timestamp(),
- input_image.size(), gfx::Rect(frame_size_));
- // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
- next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & ID_LAST;
-
- // If a shared memory segment is available, there are no pending buffers, and
- // this isn't a mid-stream resolution change, then send the buffer for decode
- // immediately. Otherwise, save the buffer in the queue for later decode.
- std::unique_ptr<base::SharedMemory> shm_buffer;
- if (!need_to_reset_for_midstream_resize && pending_buffers_.empty())
- shm_buffer = GetSHM_Locked(input_image.size());
- if (!shm_buffer) {
- if (!SaveToPendingBuffers_Locked(input_image, buffer_data)) {
- // We have exceeded the pending buffers count, we are severely behind.
- // Since we are returning ERROR, WebRTC will not be interested in the
- // remaining buffers, and will provide us with a new keyframe instead.
- // Better to drop any pending buffers and start afresh to catch up faster.
- DVLOG(1) << "Exceeded maximum pending buffer count, dropping";
- ++vda_error_counter_;
- if (ShouldFallbackToSoftwareDecode())
- return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
- ClearPendingBuffers();
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
-
- if (need_to_reset_for_midstream_resize) {
- Reset_Locked();
- }
- return WEBRTC_VIDEO_CODEC_OK;
- }
-
- SaveToDecodeBuffers_Locked(input_image, std::move(shm_buffer), buffer_data);
- factories_->GetTaskRunner()->PostTask(
- FROM_HERE, base::BindOnce(&RTCVideoDecoder::RequestBufferDecode,
- weak_factory_.GetWeakPtr()));
- return WEBRTC_VIDEO_CODEC_OK;
-}
-
-int32_t RTCVideoDecoder::RegisterDecodeCompleteCallback(
- webrtc::DecodedImageCallback* callback) {
- DVLOG(2) << "RegisterDecodeCompleteCallback";
- DCHECK(callback);
- base::AutoLock auto_lock(lock_);
- decode_complete_callback_ = callback;
- return WEBRTC_VIDEO_CODEC_OK;
-}
-
-int32_t RTCVideoDecoder::Release() {
- DVLOG(2) << "Release";
- // Do not destroy VDA because WebRTC can call InitDecode and start decoding
- // again.
- base::AutoLock auto_lock(lock_);
- if (state_ == UNINITIALIZED) {
- LOG(ERROR) << "Decoder not initialized.";
- return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
- }
- if (next_bitstream_buffer_id_ != 0)
- reset_bitstream_buffer_id_ = next_bitstream_buffer_id_ - 1;
- else
- reset_bitstream_buffer_id_ = ID_LAST;
- frame_size_.SetSize(0, 0);
- Reset_Locked();
- return WEBRTC_VIDEO_CODEC_OK;
-}
-
-void RTCVideoDecoder::ProvidePictureBuffers(uint32_t buffer_count,
- media::VideoPixelFormat format,
- uint32_t textures_per_buffer,
- const gfx::Size& size,
- uint32_t texture_target) {
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
- DVLOG(3) << "ProvidePictureBuffers. texture_target=" << texture_target;
-
- if (!vda_)
- return;
-
- std::vector<uint32_t> texture_ids;
- std::vector<gpu::Mailbox> texture_mailboxes;
-
- if (format == media::PIXEL_FORMAT_UNKNOWN)
- format = media::PIXEL_FORMAT_ARGB;
-
- const uint32_t texture_count = buffer_count * textures_per_buffer;
- if (!factories_->CreateTextures(texture_count, size, &texture_ids,
- &texture_mailboxes, texture_target)) {
- NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
- return;
- }
- DCHECK_EQ(texture_count, texture_ids.size());
- DCHECK_EQ(texture_count, texture_mailboxes.size());
-
- std::vector<media::PictureBuffer> picture_buffers;
- for (size_t buffer_index = 0; buffer_index < buffer_count; ++buffer_index) {
- media::PictureBuffer::TextureIds ids;
- std::vector<gpu::Mailbox> mailboxes;
- for (size_t texture_index = 0; texture_index < textures_per_buffer;
- ++texture_index) {
- const size_t texture_id =
- texture_index + textures_per_buffer * buffer_index;
- ids.push_back(texture_ids[texture_id]);
- mailboxes.push_back(texture_mailboxes[texture_id]);
- }
-
- picture_buffers.push_back(media::PictureBuffer(next_picture_buffer_id_++,
- size, ids, mailboxes,
- texture_target, format));
- picture_buffers_at_display_.emplace(picture_buffers.back().id(), 0);
- const bool inserted =
- assigned_picture_buffers_
- .insert(std::make_pair(picture_buffers.back().id(),
- picture_buffers.back()))
- .second;
- DCHECK(inserted);
- }
- vda_->AssignPictureBuffers(picture_buffers);
-}
-
-void RTCVideoDecoder::DismissPictureBuffer(int32_t id) {
- DVLOG(3) << "DismissPictureBuffer. id=" << id;
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
- auto it = assigned_picture_buffers_.find(id);
- if (it == assigned_picture_buffers_.end()) {
- NOTREACHED() << "Missing picture buffer: " << id;
- return;
- }
-
- // Not destroying a texture in display in |picture_buffers_at_display_|.
- // Postpone deletion until after it's returned to us.
- media::PictureBuffer::TextureIds texture_ids =
- (it->second).client_texture_ids();
- auto picture_buffer_it = picture_buffers_at_display_.find(id);
- if (picture_buffer_it != picture_buffers_at_display_.end() &&
- picture_buffer_it->second > 0) {
- DCHECK(!textures_to_be_deleted_.count(id));
- textures_to_be_deleted_[id] = texture_ids;
- } else {
- // Otherwise, we can delete the texture immediately.
- for (const auto texture_id : texture_ids)
- factories_->DeleteTexture(texture_id);
- if (picture_buffer_it != picture_buffers_at_display_.end())
- picture_buffers_at_display_.erase(picture_buffer_it);
- }
- assigned_picture_buffers_.erase(it);
-}
-
-void RTCVideoDecoder::PictureReady(const media::Picture& picture) {
- DVLOG(3) << "PictureReady";
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
- auto it = assigned_picture_buffers_.find(picture.picture_buffer_id());
- if (it == assigned_picture_buffers_.end()) {
- NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id();
- NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
- return;
- }
-
- media::PictureBuffer& pb = it->second;
- if (picture.size_changed()) {
- DCHECK(pb.size() != picture.visible_rect().size());
- DVLOG(3) << __func__ << " Updating size of PictureBuffer[" << pb.id()
- << "] from:" << pb.size().ToString()
- << " to:" << picture.visible_rect().size().ToString();
- pb.set_size(picture.visible_rect().size());
- }
-
- uint32_t timestamp = 0;
- gfx::Rect visible_rect;
- GetBufferData(picture.bitstream_buffer_id(), &timestamp, &visible_rect);
- if (!picture.visible_rect().IsEmpty())
- visible_rect = picture.visible_rect();
-
- if (visible_rect.IsEmpty() || !gfx::Rect(pb.size()).Contains(visible_rect)) {
- LOG(ERROR) << "Invalid picture size: " << visible_rect.ToString()
- << " should fit in " << pb.size().ToString();
- NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
- return;
- }
-
- scoped_refptr<media::VideoFrame> frame =
- CreateVideoFrame(picture, pb, timestamp, visible_rect, pb.pixel_format());
- if (!frame) {
- NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
- return;
- }
-
- ++picture_buffers_at_display_[picture.picture_buffer_id()];
-
- // Create a WebRTC video frame.
- webrtc::VideoFrame decoded_image(
- new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(frame), timestamp, 0,
- webrtc::kVideoRotation_0);
-
- // Invoke decode callback. WebRTC expects no callback after Release.
- {
- base::AutoLock auto_lock(lock_);
- DCHECK(decode_complete_callback_);
- if (IsBufferAfterReset(picture.bitstream_buffer_id(),
- reset_bitstream_buffer_id_)) {
- decode_complete_callback_->Decoded(decoded_image);
- }
- // Reset error counter as we successfully decoded a frame.
- vda_error_counter_ = 0;
- }
-}
-
-scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame(
- const media::Picture& picture,
- const media::PictureBuffer& pb,
- uint32_t timestamp,
- const gfx::Rect& visible_rect,
- media::VideoPixelFormat pixel_format) {
- DCHECK(pb.texture_target());
- // Convert timestamp from 90KHz to ms.
- base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue(
- base::checked_cast<uint64_t>(timestamp) * 1000 / 90);
- // TODO(mcasas): The incoming data may actually be in a YUV format, but may be
- // labelled as ARGB. This may or may not be reported by VDA, depending on
- // whether it provides an implementation of VDA::GetOutputFormat().
- // This prevents the compositor from messing with it, since the underlying
- // platform can handle the former format natively. Make sure the
- // correct format is used and everyone down the line understands it.
- gpu::MailboxHolder holders[media::VideoFrame::kMaxPlanes];
- for (size_t i = 0; i < pb.client_texture_ids().size(); ++i) {
- holders[i].mailbox = pb.texture_mailbox(i);
- holders[i].texture_target = pb.texture_target();
- }
- scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::WrapNativeTextures(
- pixel_format, holders,
- media::BindToCurrentLoop(
- base::Bind(&RTCVideoDecoder::ReleaseMailbox,
- weak_factory_.GetWeakPtr(), factories_,
- picture.picture_buffer_id(), pb.client_texture_ids())),
- pb.size(), visible_rect, visible_rect.size(), timestamp_ms);
- if (frame) {
- frame->metadata()->SetBoolean(media::VideoFrameMetadata::ALLOW_OVERLAY,
- picture.allow_overlay());
-#if defined(OS_ANDROID)
- frame->metadata()->SetBoolean(media::VideoFrameMetadata::TEXTURE_OWNER,
- picture.texture_owner());
- frame->metadata()->SetBoolean(
- media::VideoFrameMetadata::WANTS_PROMOTION_HINT,
- picture.wants_promotion_hint());
-#endif
- }
- return frame;
-}
-
-void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32_t id) {
- DVLOG(3) << "NotifyEndOfBitstreamBuffer. id=" << id;
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
- auto it = bitstream_buffers_in_decoder_.find(id);
- if (it == bitstream_buffers_in_decoder_.end()) {
- NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
- NOTREACHED() << "Missing bitstream buffer: " << id;
- return;
- }
-
- {
- base::AutoLock auto_lock(lock_);
- PutSHM_Locked(std::move(it->second));
- }
- bitstream_buffers_in_decoder_.erase(it);
-
- RequestBufferDecode();
-}
-
-void RTCVideoDecoder::NotifyFlushDone() {
- DVLOG(3) << "NotifyFlushDone";
- NOTREACHED() << "Unexpected flush done notification.";
-}
-
-void RTCVideoDecoder::NotifyResetDone() {
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
- DVLOG(3) << "NotifyResetDone";
-
- if (!vda_)
- return;
-
- input_buffer_data_.clear();
- {
- base::AutoLock auto_lock(lock_);
- state_ = INITIALIZED;
- }
- // Send the pending buffers for decoding.
- RequestBufferDecode();
-}
-
-void RTCVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
- if (!vda_)
- return;
-
- LOG(ERROR) << "VDA Error:" << error;
- UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", error,
- media::VideoDecodeAccelerator::ERROR_MAX + 1);
- DestroyVDA();
-
- base::AutoLock auto_lock(lock_);
- state_ = DECODE_ERROR;
- ++vda_error_counter_;
-}
-
-const char* RTCVideoDecoder::ImplementationName() const {
- return "ExternalDecoder";
-}
-
-void RTCVideoDecoder::RequestBufferDecode() {
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
- if (!vda_)
- return;
-
- MovePendingBuffersToDecodeBuffers();
-
- while (CanMoreDecodeWorkBeDone()) {
- // Get a buffer and data from the queue.
- std::unique_ptr<base::SharedMemory> shm_buffer;
- BufferData buffer_data;
- {
- base::AutoLock auto_lock(lock_);
- // Do not request decode if VDA is resetting.
- if (decode_buffers_.empty() || state_ == RESETTING)
- return;
- shm_buffer = std::move(decode_buffers_.front().first);
- buffer_data = decode_buffers_.front().second;
- decode_buffers_.pop_front();
- // Drop the buffers before Release is called.
- if (!IsBufferAfterReset(buffer_data.bitstream_buffer_id,
- reset_bitstream_buffer_id_)) {
- PutSHM_Locked(std::move(shm_buffer));
- continue;
- }
- }
-
- // Create a BitstreamBuffer and send to VDA to decode.
- media::BitstreamBuffer bitstream_buffer(
- buffer_data.bitstream_buffer_id, shm_buffer->handle(), buffer_data.size,
- 0, base::TimeDelta::FromInternalValue(buffer_data.timestamp));
- const bool inserted = bitstream_buffers_in_decoder_
- .insert(std::make_pair(bitstream_buffer.id(),
- std::move(shm_buffer)))
- .second;
- DCHECK(inserted) << "bitstream_buffer_id " << bitstream_buffer.id()
- << " existed already in bitstream_buffers_in_decoder_";
- RecordBufferData(buffer_data);
- vda_->Decode(bitstream_buffer);
- }
-}
-
-bool RTCVideoDecoder::CanMoreDecodeWorkBeDone() {
- return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes;
-}
-
-bool RTCVideoDecoder::IsBufferAfterReset(int32_t id_buffer, int32_t id_reset) {
- if (id_reset == ID_INVALID)
- return true;
- int32_t diff = id_buffer - id_reset;
- if (diff <= 0)
- diff += ID_LAST + 1;
- return diff < ID_HALF;
-}
-
-bool RTCVideoDecoder::IsFirstBufferAfterReset(int32_t id_buffer,
- int32_t id_reset) {
- if (id_reset == ID_INVALID)
- return id_buffer == 0;
- return id_buffer == ((id_reset + 1) & ID_LAST);
-}
-
-void RTCVideoDecoder::SaveToDecodeBuffers_Locked(
- const webrtc::EncodedImage& input_image,
- std::unique_ptr<base::SharedMemory> shm_buffer,
- const BufferData& buffer_data) {
- memcpy(shm_buffer->memory(), input_image.data(), input_image.size());
-
- // Store the buffer and the metadata to the queue.
- decode_buffers_.emplace_back(std::move(shm_buffer), buffer_data);
-}
-
-bool RTCVideoDecoder::SaveToPendingBuffers_Locked(
- const webrtc::EncodedImage& input_image,
- const BufferData& buffer_data) {
- DVLOG(2) << "SaveToPendingBuffers_Locked"
- << ". pending_buffers size=" << pending_buffers_.size()
- << ". decode_buffers_ size=" << decode_buffers_.size()
- << ". available_shm size=" << available_shm_segments_.size();
- // Queued too many buffers. Something goes wrong.
- if (pending_buffers_.size() >= kMaxNumOfPendingBuffers) {
- LOG(WARNING) << "Too many pending buffers!";
- return false;
- }
-
- // Clone the input image and save it to the queue.
- uint8_t* buffer = new uint8_t[input_image.size()];
- // TODO(wuchengli): avoid memcpy. Extend webrtc::VideoDecoder::Decode()
- // interface to take a non-const ptr to the frame and add a method to the
- // frame that will swap buffers with another.
- memcpy(buffer, input_image.data(), input_image.size());
- webrtc::EncodedImage encoded_image(buffer, input_image.size(),
- input_image.size());
- std::pair<webrtc::EncodedImage, BufferData> buffer_pair =
- std::make_pair(encoded_image, buffer_data);
-
- pending_buffers_.push_back(buffer_pair);
- return true;
-}
-
-void RTCVideoDecoder::MovePendingBuffersToDecodeBuffers() {
- base::AutoLock auto_lock(lock_);
- while (pending_buffers_.size() > 0) {
- // Get a pending buffer from the queue.
- const webrtc::EncodedImage& input_image = pending_buffers_.front().first;
- const BufferData& buffer_data = pending_buffers_.front().second;
-
- // Drop the frame if it comes before Release.
- if (!IsBufferAfterReset(buffer_data.bitstream_buffer_id,
- reset_bitstream_buffer_id_)) {
- delete[] input_image.data();
- pending_buffers_.pop_front();
- continue;
- }
- // Get shared memory and save it to decode buffers.
- std::unique_ptr<base::SharedMemory> shm_buffer =
- GetSHM_Locked(input_image.size());
- if (!shm_buffer)
- return;
- SaveToDecodeBuffers_Locked(input_image, std::move(shm_buffer), buffer_data);
- delete[] input_image.data();
- pending_buffers_.pop_front();
- }
-}
-
-void RTCVideoDecoder::Reset_Locked() {
- DVLOG(2) << __func__;
- lock_.AssertAcquired();
- // If VDA is already resetting, no need to request the reset again.
- if (state_ != RESETTING) {
- state_ = RESETTING;
- factories_->GetTaskRunner()->PostTask(
- FROM_HERE, base::BindOnce(&RTCVideoDecoder::ResetInternal,
- weak_factory_.GetWeakPtr()));
- }
-}
-
-void RTCVideoDecoder::ResetInternal() {
- DVLOG(2) << __func__;
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
- if (vda_) {
- vda_->Reset();
- } else {
- CreateVDA(vda_codec_profile_, nullptr);
- if (vda_) {
- base::AutoLock auto_lock(lock_);
- state_ = INITIALIZED;
- }
- }
-}
-
-// static
-void RTCVideoDecoder::ReleaseMailbox(
- base::WeakPtr<RTCVideoDecoder> decoder,
- media::GpuVideoAcceleratorFactories* factories,
- int64_t picture_buffer_id,
- const media::PictureBuffer::TextureIds& texture_ids,
- const gpu::SyncToken& release_sync_token) {
- DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread());
- factories->WaitSyncToken(release_sync_token);
-
- if (decoder) {
- decoder->ReusePictureBuffer(picture_buffer_id);
- return;
- }
- // It's the last chance to delete the texture after display,
- // because RTCVideoDecoder was destructed.
- for (const auto& id : texture_ids)
- factories->DeleteTexture(id);
-}
-
-void RTCVideoDecoder::ReusePictureBuffer(int64_t picture_buffer_id) {
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
- DVLOG(3) << "ReusePictureBuffer. id=" << picture_buffer_id;
-
- auto picture_buffer_it = picture_buffers_at_display_.find(picture_buffer_id);
- DCHECK(picture_buffer_it != picture_buffers_at_display_.end());
- DCHECK_GT(picture_buffer_it->second, 0u);
- --picture_buffer_it->second;
-
- if (picture_buffer_it->second == 0) {
- auto iter = textures_to_be_deleted_.find(picture_buffer_id);
- if (iter != textures_to_be_deleted_.end()) {
- // This picture was dismissed while in display, so we postponed deletion.
- for (const auto id : iter->second)
- factories_->DeleteTexture(id);
- textures_to_be_deleted_.erase(iter);
- return;
- }
- }
-
- // DestroyVDA() might already have been called.
- if (vda_)
- vda_->ReusePictureBuffer(picture_buffer_id);
-}
-
-bool RTCVideoDecoder::IsProfileSupported(media::VideoCodecProfile profile) {
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
- media::VideoDecodeAccelerator::Capabilities capabilities =
- factories_->GetVideoDecodeAcceleratorCapabilities();
-
- for (const auto& supported_profile : capabilities.supported_profiles) {
- if (profile == supported_profile.profile) {
- min_resolution_ = supported_profile.min_resolution;
- max_resolution_ = supported_profile.max_resolution;
- return true;
- }
- }
-
- return false;
-}
-
-void RTCVideoDecoder::CreateVDA(media::VideoCodecProfile profile,
- base::WaitableEvent* waiter) {
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
- if (!IsProfileSupported(profile)) {
- DVLOG(1) << "Unsupported profile " << GetProfileName(profile);
- } else {
- vda_ = factories_->CreateVideoDecodeAccelerator();
-
- media::VideoDecodeAccelerator::Config config(profile);
- if (vda_ && !vda_->Initialize(config, this))
- vda_.release()->Destroy();
- vda_codec_profile_ = profile;
- }
-
- if (waiter)
- waiter->Signal();
-}
-
-void RTCVideoDecoder::DestroyTextures() {
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
- while (!assigned_picture_buffers_.empty())
- DismissPictureBuffer(assigned_picture_buffers_.begin()->first);
-}
-
-void RTCVideoDecoder::DestroyVDA() {
- DVLOG(2) << "DestroyVDA";
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
- if (vda_)
- vda_.release()->Destroy();
- DestroyTextures();
-
- base::AutoLock auto_lock(lock_);
-
- // Put the buffers back in case we restart the decoder.
- for (auto& buffer : bitstream_buffers_in_decoder_)
- PutSHM_Locked(std::move(buffer.second));
- bitstream_buffers_in_decoder_.clear();
-
- state_ = UNINITIALIZED;
-}
-
-std::unique_ptr<base::SharedMemory> RTCVideoDecoder::GetSHM_Locked(
- size_t min_size) {
- // Reuse a SHM if possible.
- if (!available_shm_segments_.empty() &&
- available_shm_segments_.back()->mapped_size() >= min_size) {
- std::unique_ptr<base::SharedMemory> buffer =
- std::move(available_shm_segments_.back());
- available_shm_segments_.pop_back();
- return buffer;
- }
-
- if (available_shm_segments_.size() != num_shm_buffers_) {
- // Either available_shm_segments_ is empty (and we already have some SHM
- // buffers allocated), or the size of available segments is not large
- // enough. In the former case we need to wait for buffers to be returned,
- // in the latter we need to wait for all buffers to be returned to drop
- // them and reallocate with a new size.
- return nullptr;
- }
-
- if (num_shm_buffers_ != 0) {
- available_shm_segments_.clear();
- num_shm_buffers_ = 0;
- }
-
- // Create twice as large buffers as required, to avoid frequent reallocation.
- factories_->GetTaskRunner()->PostTask(
- FROM_HERE,
- base::BindOnce(&RTCVideoDecoder::CreateSHM, weak_factory_.GetWeakPtr(),
- kNumSharedMemorySegments, min_size * 2));
-
- // We'll be called again after the shared memory is created.
- return nullptr;
-}
-
-void RTCVideoDecoder::PutSHM_Locked(
- std::unique_ptr<base::SharedMemory> shm_buffer) {
- lock_.AssertAcquired();
- available_shm_segments_.push_back(std::move(shm_buffer));
-}
-
-void RTCVideoDecoder::CreateSHM(size_t count, size_t size) {
- DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
- DVLOG(2) << "CreateSHM. count=" << count << ", size=" << size;
-
- for (size_t i = 0; i < count; i++) {
- std::unique_ptr<base::SharedMemory> shm =
- factories_->CreateSharedMemory(size);
- if (!shm) {
- LOG(ERROR) << "Failed allocating shared memory of size=" << size;
- NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
- return;
- }
-
- base::AutoLock auto_lock(lock_);
- PutSHM_Locked(std::move(shm));
- ++num_shm_buffers_;
- }
-
- // Kick off the decoding.
- RequestBufferDecode();
-}
-
-void RTCVideoDecoder::RecordBufferData(const BufferData& buffer_data) {
- input_buffer_data_.push_front(buffer_data);
- // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but
- // that's too small for some pathological B-frame test videos. The cost of
- // using too-high a value is low (192 bits per extra slot).
- static const size_t kMaxInputBufferDataSize = 128;
- // Pop from the back of the list, because that's the oldest and least likely
- // to be useful in the future data.
- if (input_buffer_data_.size() > kMaxInputBufferDataSize)
- input_buffer_data_.pop_back();
-}
-
-void RTCVideoDecoder::GetBufferData(int32_t bitstream_buffer_id,
- uint32_t* timestamp,
- gfx::Rect* visible_rect) {
- for (const auto& buffer_data : input_buffer_data_) {
- if (buffer_data.bitstream_buffer_id != bitstream_buffer_id)
- continue;
- *timestamp = buffer_data.timestamp;
- *visible_rect = buffer_data.visible_rect;
- return;
- }
- NOTREACHED() << "Missing bitstream buffer id: " << bitstream_buffer_id;
-}
-
-int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) {
- // Logging boolean is enough to know if HW decoding has been used. Also,
- // InitDecode is less likely to return an error so enum is not used here.
- bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false;
- UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample);
- return status;
-}
-
-void RTCVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent()
- const {
- DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread());
-}
-
-void RTCVideoDecoder::ClearPendingBuffers() {
- // Delete WebRTC input buffers.
- for (const auto& pending_buffer : pending_buffers_)
- delete[] pending_buffer.first.data();
- pending_buffers_.clear();
-}
-
-bool RTCVideoDecoder::ShouldFallbackToSoftwareDecode() {
- // Check if SW H264 implementation is available before falling back, because
- // it might not available on the platform due to licensing issues.
- if (vda_error_counter_ > kNumVDAErrorsBeforeSWFallback &&
- (video_codec_type_ != webrtc::kVideoCodecH264 ||
- webrtc::H264Decoder::IsSupported())) {
- DLOG(ERROR) << vda_error_counter_
- << " errors reported by VDA, falling back to software decode";
- return true;
- }
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder.h b/chromium/content/renderer/media/webrtc/rtc_video_decoder.h
deleted file mode 100644
index 40b7e5c8e79..00000000000
--- a/chromium/content/renderer/media/webrtc/rtc_video_decoder.h
+++ /dev/null
@@ -1,321 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_RTC_VIDEO_DECODER_H_
-#define CONTENT_RENDERER_MEDIA_WEBRTC_RTC_VIDEO_DECODER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <list>
-#include <map>
-#include <memory>
-#include <set>
-#include <utility>
-
-#include "base/containers/circular_deque.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread.h"
-#include "content/common/content_export.h"
-#include "media/base/bitstream_buffer.h"
-#include "media/base/video_decoder.h"
-#include "media/video/picture.h"
-#include "media/video/video_decode_accelerator.h"
-#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
-#include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace base {
-class WaitableEvent;
-} // namespace base
-
-namespace media {
-class GpuVideoAcceleratorFactories;
-} // namespace media
-
-namespace gpu {
-struct SyncToken;
-} // namespace gpu
-
-namespace content {
-
-// This class uses hardware accelerated video decoder to decode video for
-// WebRTC. Lives on the media thread, where VDA::Client methods run on.
-// webrtc::VideoDecoder methods run on WebRTC DecodingThread or
-// Chrome_libJingle_WorkerThread, which are trampolined to the media thread.
-// Decode() is non-blocking and queues the buffers. Decoded frames are
-// delivered to WebRTC on the media task runner.
-class CONTENT_EXPORT RTCVideoDecoder
- : public webrtc::VideoDecoder,
- public media::VideoDecodeAccelerator::Client {
- public:
- ~RTCVideoDecoder() override;
-
- // Creates a RTCVideoDecoder on the message loop of |factories|. Returns NULL
- // if failed. The video decoder will run on the message loop of |factories|.
- static std::unique_ptr<RTCVideoDecoder> Create(
- const webrtc::SdpVideoFormat& format,
- media::GpuVideoAcceleratorFactories* factories);
- // Destroys |decoder| on the loop of |factories|
- static void Destroy(webrtc::VideoDecoder* decoder,
- media::GpuVideoAcceleratorFactories* factories);
-
- // webrtc::VideoDecoder implementation.
- // Called on WebRTC DecodingThread.
- int32_t InitDecode(const webrtc::VideoCodec* codecSettings,
- int32_t numberOfCores) override;
- // Called on WebRTC DecodingThread.
- int32_t Decode(const webrtc::EncodedImage& inputImage,
- bool missingFrames,
- int64_t renderTimeMs) override;
- // Called on WebRTC DecodingThread.
- int32_t RegisterDecodeCompleteCallback(
- webrtc::DecodedImageCallback* callback) override;
- // Called on Chrome_libJingle_WorkerThread. The child thread is blocked while
- // this runs.
- int32_t Release() override;
-
- // VideoDecodeAccelerator::Client implementation.
- void ProvidePictureBuffers(uint32_t count,
- media::VideoPixelFormat format,
- uint32_t textures_per_buffer,
- const gfx::Size& size,
- uint32_t texture_target) override;
- void DismissPictureBuffer(int32_t id) override;
- void PictureReady(const media::Picture& picture) override;
- void NotifyEndOfBitstreamBuffer(int32_t id) override;
- void NotifyFlushDone() override;
- void NotifyResetDone() override;
- void NotifyError(media::VideoDecodeAccelerator::Error error) override;
- const char* ImplementationName() const override;
-
- private:
- // Metadata of a bitstream buffer.
- struct BufferData {
- BufferData(int32_t bitstream_buffer_id,
- uint32_t timestamp,
- size_t size,
- const gfx::Rect& visible_rect);
- BufferData();
- ~BufferData();
- int32_t bitstream_buffer_id;
- uint32_t timestamp; // in 90KHz
- size_t size; // buffer size
- gfx::Rect visible_rect;
- };
-
- FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, IsBufferAfterReset);
- FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, IsFirstBufferAfterReset);
- FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest,
- GetVDAErrorCounterForNotifyError);
- FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest,
- GetVDAErrorCounterForRunningOutOfPendingBuffers);
- FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest,
- GetVDAErrorCounterForSendingFramesWithoutSize);
- FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, ParsesVP9CodecProfile);
-
- RTCVideoDecoder(webrtc::VideoCodecType type,
- media::GpuVideoAcceleratorFactories* factories);
-
- // Requests a buffer to be decoded by VDA.
- void RequestBufferDecode();
-
- bool CanMoreDecodeWorkBeDone();
-
- // Returns true if bitstream buffer id |id_buffer| comes after |id_reset|.
- // This handles the wraparound.
- bool IsBufferAfterReset(int32_t id_buffer, int32_t id_reset);
-
- // Returns true if bitstream buffer |id_buffer| is the first buffer after
- // |id_reset|.
- bool IsFirstBufferAfterReset(int32_t id_buffer, int32_t id_reset);
-
- int GetVDAErrorCounterForTesting() { return vda_error_counter_; }
-
- // Saves a WebRTC buffer in |decode_buffers_| for decode.
- void SaveToDecodeBuffers_Locked(
- const webrtc::EncodedImage& input_image,
- std::unique_ptr<base::SharedMemory> shm_buffer,
- const BufferData& buffer_data);
-
- // Saves a WebRTC buffer in |pending_buffers_| waiting for SHM available.
- // Returns true on success.
- bool SaveToPendingBuffers_Locked(const webrtc::EncodedImage& input_image,
- const BufferData& buffer_data);
-
- // Gets SHM and moves pending buffers to decode buffers.
- void MovePendingBuffersToDecodeBuffers();
-
- scoped_refptr<media::VideoFrame> CreateVideoFrame(
- const media::Picture& picture,
- const media::PictureBuffer& pb,
- uint32_t timestamp,
- const gfx::Rect& visible_rect,
- media::VideoPixelFormat pixel_format);
-
- // Resets VDA.
- void Reset_Locked();
- void ResetInternal();
-
- // Static method is to allow it to run even after RVD is deleted.
- static void ReleaseMailbox(
- base::WeakPtr<RTCVideoDecoder> decoder,
- media::GpuVideoAcceleratorFactories* factories,
- int64_t picture_buffer_id,
- const media::PictureBuffer::TextureIds& texture_ids,
- const gpu::SyncToken& release_sync_token);
- // Tells VDA that a picture buffer can be recycled.
- void ReusePictureBuffer(int64_t picture_buffer_id);
-
- // Creates |vda_| on the media thread.
- void CreateVDA(media::VideoCodecProfile profile, base::WaitableEvent* waiter);
-
- void DestroyTextures();
- void DestroyVDA();
-
- // Gets a shared-memory segment of at least |min_size| bytes from
- // |available_shm_segments_|. Returns NULL if there is no buffer or the
- // buffer is not big enough.
- std::unique_ptr<base::SharedMemory> GetSHM_Locked(size_t min_size);
-
- // Returns a shared-memory segment to the available pool.
- void PutSHM_Locked(std::unique_ptr<base::SharedMemory> shm_buffer);
-
- // Allocates |count| shared memory buffers of |size| bytes.
- void CreateSHM(size_t count, size_t size);
-
- // Stores the buffer metadata to |input_buffer_data_|.
- void RecordBufferData(const BufferData& buffer_data);
- // Gets the buffer metadata from |input_buffer_data_|.
- void GetBufferData(int32_t bitstream_buffer_id,
- uint32_t* timestamp,
- gfx::Rect* visible_rect);
-
- // Records the result of InitDecode to UMA and returns |status|.
- int32_t RecordInitDecodeUMA(int32_t status);
-
- // Asserts the contract that this class is operated on the right thread.
- void DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() const;
-
- // Queries factories_ whether |profile| is supported and return true is so,
- // false otherwise. If true, also set resolution limits for |profile|
- // in min/max_resolution_.
- bool IsProfileSupported(media::VideoCodecProfile profile);
-
- // Clears the pending_buffers_ queue, freeing memory.
- void ClearPendingBuffers();
-
- // Checks |vda_error_counter_| to see if we should ask for SW fallback.
- bool ShouldFallbackToSoftwareDecode();
-
- enum State {
- UNINITIALIZED, // The decoder has not initialized.
- INITIALIZED, // The decoder has initialized.
- RESETTING, // The decoder is being reset.
- DECODE_ERROR, // Decoding error happened.
- };
-
- static const int32_t ID_LAST; // maximum bitstream buffer id
- static const int32_t ID_HALF; // half of the maximum bitstream buffer id
- static const int32_t ID_INVALID; // indicates Reset or Release never occurred
-
- // The hardware video decoder.
- std::unique_ptr<media::VideoDecodeAccelerator> vda_;
-
- media::VideoCodecProfile vda_codec_profile_;
-
- // Number of times that |vda_| notified of an error.
- uint32_t vda_error_counter_;
-
- // The video codec type, as reported by WebRTC.
- const webrtc::VideoCodecType video_codec_type_;
-
- // The size of the incoming video frames.
- gfx::Size frame_size_;
-
- media::GpuVideoAcceleratorFactories* const factories_;
-
- // Metadata of the buffers that have been sent for decode.
- std::list<BufferData> input_buffer_data_;
-
- // A map from bitstream buffer IDs to bitstream buffers that are being
- // processed by VDA.
- std::map<int32_t, std::unique_ptr<base::SharedMemory>>
- bitstream_buffers_in_decoder_;
-
- // A map from picture buffer IDs to texture-backed picture buffers.
- std::map<int32_t, media::PictureBuffer> assigned_picture_buffers_;
- // The texture ids that should be destroyed but the buffer is still in
- // |picture_buffers_at_display_|. It will be destroyed when the buffer is
- // returned from display via ReusePictureBuffer().
- std::map<int32_t /* picture_buffer_id */,
- media::PictureBuffer::TextureIds /* texture_ids */>
- textures_to_be_deleted_;
- // PictureBuffers given to us by VDA via PictureReady, which we sent forward
- // as VideoFrames to be rendered via read_cb_, and which will be returned
- // to us via ReusePictureBuffer. Note that a picture buffer might be sent from
- // VDA multiple times. Therefore we use map to track the number of times we
- // passed the picture buffer for display.
- std::map<int32_t /* picture_buffer_id */,
- size_t /* num_times_sent_to_client */>
- picture_buffers_at_display_;
-
- // The id that will be given to the next picture buffer.
- int32_t next_picture_buffer_id_;
-
- // Protects |state_|, |decode_complete_callback_| , |num_shm_buffers_|,
- // |available_shm_segments_|, |pending_buffers_|, |decode_buffers_|,
- // |next_bitstream_buffer_id_|, |reset_bitstream_buffer_id_| and
- // |vda_error_counter_|.
- base::Lock lock_;
-
- // The state of RTCVideoDecoder. Guarded by |lock_|.
- State state_;
-
- // Guarded by |lock_|.
- webrtc::DecodedImageCallback* decode_complete_callback_;
-
- // Total number of allocated SHM buffers. Guarded by |lock_|.
- size_t num_shm_buffers_;
-
- // Shared-memory buffer pool. Since allocating SHM segments requires a
- // round-trip to the browser process, we keep allocation out of the
- // steady-state of the decoder. Guarded by |lock_|.
- std::vector<std::unique_ptr<base::SharedMemory>> available_shm_segments_;
-
- // A queue storing WebRTC encoding images (and their metadata) that are
- // waiting for the shared memory. Guarded by |lock_|.
- base::circular_deque<std::pair<webrtc::EncodedImage, BufferData>>
- pending_buffers_;
-
- // A queue storing buffers (and their metadata) that will be sent to VDA for
- // decode. Guarded by |lock_|.
- base::circular_deque<
- std::pair<std::unique_ptr<base::SharedMemory>, BufferData>>
- decode_buffers_;
-
- // The id that will be given to the next bitstream buffer. Guarded by |lock_|.
- int32_t next_bitstream_buffer_id_;
-
- // A buffer that has an id less than this should be dropped because Reset or
- // Release has been called. Guarded by |lock_|.
- int32_t reset_bitstream_buffer_id_;
-
- // Minimum and maximum supported resolutions for the current profile/VDA.
- gfx::Size min_resolution_;
- gfx::Size max_resolution_;
-
- // Must be destroyed, or invalidated, on the media thread.
- // NOTE: Weak pointers must be invalidated before all other member variables.
- base::WeakPtrFactory<RTCVideoDecoder> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoder);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_VIDEO_DECODER_H_
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
index 4b79c1afa62..1f6a9494243 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
@@ -144,7 +144,7 @@ std::unique_ptr<RTCVideoDecoderAdapter> RTCVideoDecoderAdapter::Create(
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWin7WebRtcHWH264Decoding) &&
video_codec_type == webrtc::kVideoCodecH264 &&
- base::win::GetVersion() == base::win::VERSION_WIN7) {
+ base::win::GetVersion() == base::win::Version::WIN7) {
DVLOG(1) << "H.264 HW decoding is not supported on Win7";
return nullptr;
}
@@ -159,7 +159,7 @@ std::unique_ptr<RTCVideoDecoderAdapter> RTCVideoDecoderAdapter::Create(
media::VideoDecoderConfig config(
ToVideoCodec(webrtc::PayloadStringToCodecType(format.name)),
GuessVideoCodecProfile(format), kDefaultPixelFormat,
- media::VideoColorSpace(), media::VIDEO_ROTATION_0, kDefaultSize,
+ media::VideoColorSpace(), media::kNoTransformation, kDefaultSize,
gfx::Rect(kDefaultSize), kDefaultSize, media::EmptyExtraData(),
media::Unencrypted());
if (!gpu_factories->IsDecoderConfigSupported(kImplementation, config))
@@ -208,12 +208,11 @@ bool RTCVideoDecoderAdapter::InitializeSync(
base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
media::VideoDecoder::InitCB init_cb =
- base::BindRepeating(&FinishWait, &waiter, &result);
+ base::BindOnce(&FinishWait, &waiter, &result);
if (media_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&RTCVideoDecoderAdapter::InitializeOnMediaThread,
- base::Unretained(this), std::cref(config),
- std::cref(init_cb)))) {
+ base::Unretained(this), config, std::move(init_cb)))) {
waiter.Wait();
}
return result;
@@ -337,7 +336,7 @@ const char* RTCVideoDecoderAdapter::ImplementationName() const {
void RTCVideoDecoderAdapter::InitializeOnMediaThread(
const media::VideoDecoderConfig& config,
- const media::VideoDecoder::InitCB& init_cb) {
+ media::VideoDecoder::InitCB init_cb) {
DVLOG(3) << __func__;
DCHECK(media_task_runner_->BelongsToCurrentThread());
@@ -353,7 +352,7 @@ void RTCVideoDecoderAdapter::InitializeOnMediaThread(
if (!video_decoder_) {
media_task_runner_->PostTask(FROM_HERE,
- base::BindRepeating(init_cb, false));
+ base::BindOnce(std::move(init_cb), false));
return;
}
}
@@ -367,8 +366,8 @@ void RTCVideoDecoderAdapter::InitializeOnMediaThread(
media::VideoDecoder::OutputCB output_cb =
base::BindRepeating(&RTCVideoDecoderAdapter::OnOutput, weak_this_);
- video_decoder_->Initialize(config, low_delay, cdm_context, init_cb, output_cb,
- base::DoNothing());
+ video_decoder_->Initialize(config, low_delay, cdm_context, std::move(init_cb),
+ output_cb, base::DoNothing());
}
void RTCVideoDecoderAdapter::DecodeOnMediaThread() {
@@ -423,19 +422,25 @@ void RTCVideoDecoderAdapter::OnDecodeDone(media::DecodeStatus status) {
DecodeOnMediaThread();
}
-void RTCVideoDecoderAdapter::OnOutput(
- const scoped_refptr<media::VideoFrame>& frame) {
+void RTCVideoDecoderAdapter::OnOutput(scoped_refptr<media::VideoFrame> frame) {
DVLOG(3) << __func__;
DCHECK(media_task_runner_->BelongsToCurrentThread());
- webrtc::VideoFrame rtc_frame(
- new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(frame),
- frame->timestamp().InMicroseconds(), 0, webrtc::kVideoRotation_0);
+ const base::TimeDelta timestamp = frame->timestamp();
+ webrtc::VideoFrame rtc_frame =
+ webrtc::VideoFrame::Builder()
+ .set_video_frame_buffer(
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
+ std::move(frame)))
+ .set_timestamp_rtp(timestamp.InMicroseconds())
+ .set_timestamp_us(0)
+ .set_rotation(webrtc::kVideoRotation_0)
+ .build();
base::AutoLock auto_lock(lock_);
- if (!base::ContainsValue(decode_timestamps_, frame->timestamp())) {
- DVLOG(2) << "Discarding frame with timestamp " << frame->timestamp();
+ if (!base::ContainsValue(decode_timestamps_, timestamp)) {
+ DVLOG(2) << "Discarding frame with timestamp " << timestamp;
return;
}
@@ -474,7 +479,7 @@ bool RTCVideoDecoderAdapter::ReinitializeSync(
base::BindRepeating(&FinishWait, &waiter, &result);
FlushDoneCB flush_success_cb =
base::BindOnce(&RTCVideoDecoderAdapter::InitializeOnMediaThread,
- weak_this_, std::cref(config), std::cref(init_cb));
+ weak_this_, config, std::move(init_cb));
FlushDoneCB flush_fail_cb =
base::BindOnce(&FinishWait, &waiter, &result, false);
if (media_task_runner_->PostTask(
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.h b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.h
index c56b3972806..e81e2447bc2 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.h
+++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.h
@@ -89,10 +89,10 @@ class CONTENT_EXPORT RTCVideoDecoderAdapter : public webrtc::VideoDecoder {
bool InitializeSync(const media::VideoDecoderConfig& config);
void InitializeOnMediaThread(const media::VideoDecoderConfig& config,
- const media::VideoDecoder::InitCB& init_cb);
+ media::VideoDecoder::InitCB init_cb);
void DecodeOnMediaThread();
void OnDecodeDone(media::DecodeStatus status);
- void OnOutput(const scoped_refptr<media::VideoFrame>& frame);
+ void OnOutput(scoped_refptr<media::VideoFrame> frame);
bool ShouldReinitializeForSettingHDRColorSpace(
const webrtc::EncodedImage& input_image) const;
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter_unittest.cc
index 5d2ee52ec30..799f340c8a5 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter_unittest.cc
@@ -50,17 +50,29 @@ namespace {
class MockVideoDecoder : public media::VideoDecoder {
public:
std::string GetDisplayName() const override { return "MockVideoDecoder"; }
- MOCK_METHOD6(Initialize,
+ void Initialize(const media::VideoDecoderConfig& config,
+ bool low_delay,
+ media::CdmContext* cdm_context,
+ InitCB init_cb,
+ const OutputCB& output_cb,
+ const media::WaitingCB& waiting_cb) override {
+ Initialize_(config, low_delay, cdm_context, init_cb, output_cb, waiting_cb);
+ }
+ MOCK_METHOD6(Initialize_,
void(const media::VideoDecoderConfig& config,
bool low_delay,
media::CdmContext* cdm_context,
- const InitCB& init_cb,
+ InitCB& init_cb,
const OutputCB& output_cb,
const media::WaitingCB& waiting_cb));
- MOCK_METHOD2(Decode,
- void(scoped_refptr<media::DecoderBuffer> buffer,
- const DecodeCB&));
- MOCK_METHOD1(Reset, void(const base::RepeatingClosure&));
+ void Decode(scoped_refptr<media::DecoderBuffer> buffer,
+ DecodeCB cb) override {
+ Decode_(std::move(buffer), cb);
+ }
+ MOCK_METHOD2(Decode_,
+ void(scoped_refptr<media::DecoderBuffer> buffer, DecodeCB&));
+ void Reset(base::OnceClosure cb) override { Reset_(cb); }
+ MOCK_METHOD1(Reset_, void(base::OnceClosure&));
bool NeedsBitstreamConversion() const override { return false; }
bool CanReadWithoutStalling() const override { return true; }
int GetMaxDecodeRequests() const override { return 1; }
@@ -148,9 +160,9 @@ class RTCVideoDecoderAdapterTest : public ::testing::Test {
}
bool CreateAndInitialize(bool init_cb_result = true) {
- EXPECT_CALL(*video_decoder_, Initialize(_, _, _, _, _, _))
+ EXPECT_CALL(*video_decoder_, Initialize_(_, _, _, _, _, _))
.WillOnce(DoAll(SaveArg<0>(&vda_config_), SaveArg<4>(&output_cb_),
- media::RunCallback<3>(init_cb_result)));
+ media::RunOnceCallback<3>(init_cb_result)));
rtc_video_decoder_adapter_ =
RTCVideoDecoderAdapter::Create(&gpu_factories_, sdp_format_);
return !!rtc_video_decoder_adapter_;
@@ -168,8 +180,10 @@ class RTCVideoDecoderAdapterTest : public ::testing::Test {
}
int32_t Decode(uint32_t timestamp) {
- uint8_t buf[] = {0};
- webrtc::EncodedImage input_image(&buf[0], 1, 1);
+ webrtc::EncodedImage input_image;
+ input_image.Allocate(1);
+ input_image.set_size(1);
+ input_image.data()[0] = 0;
input_image._frameType = webrtc::VideoFrameType::kVideoFrameKey;
input_image._completeFrame = true;
input_image.SetTimestamp(timestamp);
@@ -198,9 +212,11 @@ class RTCVideoDecoderAdapterTest : public ::testing::Test {
int32_t Release() { return rtc_video_decoder_adapter_->Release(); }
- webrtc::EncodedImage GetEncodedImageWithColorSpace(uint8_t* buf,
- uint32_t timestamp) {
- webrtc::EncodedImage input_image(buf, 1, 1);
+ webrtc::EncodedImage GetEncodedImageWithColorSpace(uint32_t timestamp) {
+ webrtc::EncodedImage input_image;
+ input_image.Allocate(1);
+ input_image.set_size(1);
+ input_image.data()[0] = 0;
input_image._completeFrame = true;
input_image._frameType = webrtc::VideoFrameType::kVideoFrameKey;
input_image.SetTimestamp(timestamp);
@@ -268,8 +284,8 @@ TEST_F(RTCVideoDecoderAdapterTest, InitializationFailure) {
TEST_F(RTCVideoDecoderAdapterTest, Decode) {
ASSERT_TRUE(BasicSetup());
- EXPECT_CALL(*video_decoder_, Decode(_, _))
- .WillOnce(media::RunCallback<1>(media::DecodeStatus::OK));
+ EXPECT_CALL(*video_decoder_, Decode_(_, _))
+ .WillOnce(media::RunOnceCallback<1>(media::DecodeStatus::OK));
ASSERT_EQ(Decode(0), WEBRTC_VIDEO_CODEC_OK);
@@ -281,8 +297,8 @@ TEST_F(RTCVideoDecoderAdapterTest, Decode) {
TEST_F(RTCVideoDecoderAdapterTest, Decode_Error) {
ASSERT_TRUE(BasicSetup());
- EXPECT_CALL(*video_decoder_, Decode(_, _))
- .WillOnce(media::RunCallback<1>(media::DecodeStatus::DECODE_ERROR));
+ EXPECT_CALL(*video_decoder_, Decode_(_, _))
+ .WillOnce(media::RunOnceCallback<1>(media::DecodeStatus::DECODE_ERROR));
ASSERT_EQ(Decode(0), WEBRTC_VIDEO_CODEC_OK);
media_thread_.FlushForTesting();
@@ -294,7 +310,7 @@ TEST_F(RTCVideoDecoderAdapterTest, Decode_Hang_Short) {
ASSERT_TRUE(BasicSetup());
// Ignore Decode() calls.
- EXPECT_CALL(*video_decoder_, Decode(_, _)).Times(AtLeast(1));
+ EXPECT_CALL(*video_decoder_, Decode_(_, _)).Times(AtLeast(1));
for (int counter = 0; counter < 10; counter++) {
int32_t result = Decode(counter);
@@ -312,7 +328,7 @@ TEST_F(RTCVideoDecoderAdapterTest, Decode_Hang_Long) {
ASSERT_TRUE(BasicSetup());
// Ignore Decode() calls.
- EXPECT_CALL(*video_decoder_, Decode(_, _)).Times(AtLeast(1));
+ EXPECT_CALL(*video_decoder_, Decode_(_, _)).Times(AtLeast(1));
for (int counter = 0; counter < 100; counter++) {
int32_t result = Decode(counter);
@@ -333,19 +349,18 @@ TEST_F(RTCVideoDecoderAdapterTest, ReinitializesForHDRColorSpaceInitially) {
ASSERT_TRUE(BasicSetup());
EXPECT_EQ(media::VP9PROFILE_PROFILE2, vda_config_.profile());
EXPECT_FALSE(vda_config_.color_space_info().IsSpecified());
- uint8_t buf[] = {0};
// Decode() is expected to be called for EOS flush as well.
- EXPECT_CALL(*video_decoder_, Decode(_, _))
+ EXPECT_CALL(*video_decoder_, Decode_(_, _))
.Times(3)
- .WillRepeatedly(media::RunCallback<1>(media::DecodeStatus::OK));
+ .WillRepeatedly(media::RunOnceCallback<1>(media::DecodeStatus::OK));
EXPECT_CALL(decoded_cb_, Run(_)).Times(2);
// First Decode() should cause a reinitialize as new color space is given.
- EXPECT_CALL(*video_decoder_, Initialize(_, _, _, _, _, _))
- .WillOnce(DoAll(SaveArg<0>(&vda_config_), media::RunCallback<3>(true)));
- webrtc::EncodedImage first_input_image =
- GetEncodedImageWithColorSpace(&buf[0], 0);
+ EXPECT_CALL(*video_decoder_, Initialize_(_, _, _, _, _, _))
+ .WillOnce(
+ DoAll(SaveArg<0>(&vda_config_), media::RunOnceCallback<3>(true)));
+ webrtc::EncodedImage first_input_image = GetEncodedImageWithColorSpace(0);
ASSERT_EQ(rtc_video_decoder_adapter_->Decode(first_input_image, false, 0),
WEBRTC_VIDEO_CODEC_OK);
media_thread_.FlushForTesting();
@@ -354,8 +369,7 @@ TEST_F(RTCVideoDecoderAdapterTest, ReinitializesForHDRColorSpaceInitially) {
media_thread_.FlushForTesting();
// Second Decode() with same params should happen normally.
- webrtc::EncodedImage second_input_image =
- GetEncodedImageWithColorSpace(&buf[0], 1);
+ webrtc::EncodedImage second_input_image = GetEncodedImageWithColorSpace(1);
ASSERT_EQ(rtc_video_decoder_adapter_->Decode(second_input_image, false, 0),
WEBRTC_VIDEO_CODEC_OK);
FinishDecode(1);
@@ -369,16 +383,15 @@ TEST_F(RTCVideoDecoderAdapterTest, HandlesReinitializeFailure) {
ASSERT_TRUE(BasicSetup());
EXPECT_EQ(media::VP9PROFILE_PROFILE2, vda_config_.profile());
EXPECT_FALSE(vda_config_.color_space_info().IsSpecified());
- uint8_t buf[] = {0};
- webrtc::EncodedImage input_image = GetEncodedImageWithColorSpace(&buf[0], 0);
+ webrtc::EncodedImage input_image = GetEncodedImageWithColorSpace(0);
// Decode() is expected to be called for EOS flush as well.
- EXPECT_CALL(*video_decoder_, Decode(_, _))
- .WillOnce(media::RunCallback<1>(media::DecodeStatus::OK));
+ EXPECT_CALL(*video_decoder_, Decode_(_, _))
+ .WillOnce(media::RunOnceCallback<1>(media::DecodeStatus::OK));
// Set Initialize() to fail.
- EXPECT_CALL(*video_decoder_, Initialize(_, _, _, _, _, _))
- .WillOnce(media::RunCallback<3>(false));
+ EXPECT_CALL(*video_decoder_, Initialize_(_, _, _, _, _, _))
+ .WillOnce(media::RunOnceCallback<3>(false));
ASSERT_EQ(rtc_video_decoder_adapter_->Decode(input_image, false, 0),
WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE);
}
@@ -390,12 +403,11 @@ TEST_F(RTCVideoDecoderAdapterTest, HandlesFlushFailure) {
ASSERT_TRUE(BasicSetup());
EXPECT_EQ(media::VP9PROFILE_PROFILE2, vda_config_.profile());
EXPECT_FALSE(vda_config_.color_space_info().IsSpecified());
- uint8_t buf[] = {0};
- webrtc::EncodedImage input_image = GetEncodedImageWithColorSpace(&buf[0], 0);
+ webrtc::EncodedImage input_image = GetEncodedImageWithColorSpace(0);
// Decode() is expected to be called for EOS flush, set to fail.
- EXPECT_CALL(*video_decoder_, Decode(_, _))
- .WillOnce(media::RunCallback<1>(media::DecodeStatus::ABORTED));
+ EXPECT_CALL(*video_decoder_, Decode_(_, _))
+ .WillOnce(media::RunOnceCallback<1>(media::DecodeStatus::ABORTED));
ASSERT_EQ(rtc_video_decoder_adapter_->Decode(input_image, false, 0),
WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE);
}
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder_factory.cc b/chromium/content/renderer/media/webrtc/rtc_video_decoder_factory.cc
index 0e5c48030e2..c139e0b2dc8 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_decoder_factory.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder_factory.cc
@@ -6,108 +6,15 @@
#include <memory>
-#include "base/feature_list.h"
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
-#include "content/renderer/media/webrtc/rtc_video_decoder.h"
#include "content/renderer/media/webrtc/rtc_video_decoder_adapter.h"
-#include "media/base/media_switches.h"
#include "media/video/gpu_video_accelerator_factories.h"
-#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
-#include "third_party/webrtc/common_video/h264/profile_level_id.h"
-#include "third_party/webrtc/media/base/codec.h"
-#include "third_party/webrtc/media/base/vp9_profile.h"
namespace content {
-
namespace {
-const int kDefaultFps = 30;
-
-// Translate from media::VideoDecodeAccelerator::SupportedProfile to
-// webrtc::SdpVideoFormat, or return nothing if the profile isn't supported.
-base::Optional<webrtc::SdpVideoFormat> VDAToWebRTCFormat(
- const media::VideoDecodeAccelerator::SupportedProfile& profile) {
- if (profile.profile >= media::VP8PROFILE_MIN &&
- profile.profile <= media::VP8PROFILE_MAX) {
- return webrtc::SdpVideoFormat("VP8");
- } else if (profile.profile >= media::VP9PROFILE_MIN &&
- profile.profile <= media::VP9PROFILE_MAX) {
- webrtc::VP9Profile vp9_profile;
- switch (profile.profile) {
- case media::VP9PROFILE_PROFILE0:
- vp9_profile = webrtc::VP9Profile::kProfile0;
- break;
- case media::VP9PROFILE_PROFILE2:
- vp9_profile = webrtc::VP9Profile::kProfile2;
- break;
- default:
- // Unsupported H264 profile in WebRTC.
- return base::nullopt;
- }
- return webrtc::SdpVideoFormat(
- "VP9",
- {{webrtc::kVP9FmtpProfileId, webrtc::VP9ProfileToString(vp9_profile)}});
- } else if (profile.profile >= media::H264PROFILE_MIN &&
- profile.profile <= media::H264PROFILE_MAX) {
- webrtc::H264::Profile h264_profile;
- switch (profile.profile) {
- case media::H264PROFILE_BASELINE:
- h264_profile = webrtc::H264::kProfileBaseline;
- break;
- case media::H264PROFILE_MAIN:
- h264_profile = webrtc::H264::kProfileMain;
- break;
- case media::H264PROFILE_HIGH:
- h264_profile = webrtc::H264::kProfileHigh;
- break;
- default:
- // Unsupported H264 profile in WebRTC.
- return base::nullopt;
- }
-
- const int width = profile.max_resolution.width();
- const int height = profile.max_resolution.height();
-
- const absl::optional<webrtc::H264::Level> h264_level =
- webrtc::H264::SupportedLevel(width * height, kDefaultFps);
- const webrtc::H264::ProfileLevelId profile_level_id(
- h264_profile, h264_level.value_or(webrtc::H264::kLevel1));
-
- webrtc::SdpVideoFormat format("H264");
- format.parameters = {
- {cricket::kH264FmtpProfileLevelId,
- *webrtc::H264::ProfileLevelIdToString(profile_level_id)},
- {cricket::kH264FmtpLevelAsymmetryAllowed, "1"},
- {cricket::kH264FmtpPacketizationMode, "1"}};
- return format;
- }
- return base::nullopt;
-}
-
-// Due to https://crbug.com/345569, HW decoders do not distinguish between
-// Constrained Baseline(CBP) and Baseline(BP) profiles. Since CBP is a subset of
-// BP, we can report support for both. It is safe to do so when SW fallback is
-// available.
-// TODO(emircan): Remove this when the bug referred above is fixed.
-void MapBaselineProfile(
- std::vector<webrtc::SdpVideoFormat>* supported_formats) {
- for (const auto& format : *supported_formats) {
- const absl::optional<webrtc::H264::ProfileLevelId> profile_level_id =
- webrtc::H264::ParseSdpProfileLevelId(format.parameters);
- if (profile_level_id &&
- profile_level_id->profile == webrtc::H264::kProfileBaseline) {
- webrtc::SdpVideoFormat cbp_format = format;
- webrtc::H264::ProfileLevelId cbp_profile = *profile_level_id;
- cbp_profile.profile = webrtc::H264::kProfileConstrainedBaseline;
- cbp_format.parameters[cricket::kH264FmtpProfileLevelId] =
- *webrtc::H264::ProfileLevelIdToString(cbp_profile);
- supported_formats->push_back(cbp_format);
- return;
- }
- }
-}
-
// This extra indirection is needed so that we can delete the decoder on the
// correct thread.
class ScopedVideoDecoder : public webrtc::VideoDecoder {
@@ -155,26 +62,12 @@ RTCVideoDecoderFactory::RTCVideoDecoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories)
: gpu_factories_(gpu_factories) {
DVLOG(2) << __func__;
-
- // RTCVideoDecoderAdapter does not use |supported_formats_|.
- if (base::FeatureList::IsEnabled(media::kRTCVideoDecoderAdapter))
- return;
-
- const media::VideoDecodeAccelerator::SupportedProfiles profiles =
- gpu_factories_->GetVideoDecodeAcceleratorCapabilities()
- .supported_profiles;
- for (const auto& profile : profiles) {
- base::Optional<webrtc::SdpVideoFormat> format = VDAToWebRTCFormat(profile);
- if (format)
- supported_formats_.push_back(std::move(*format));
- }
- MapBaselineProfile(&supported_formats_);
}
std::vector<webrtc::SdpVideoFormat>
RTCVideoDecoderFactory::GetSupportedFormats() const {
- DCHECK(!base::FeatureList::IsEnabled(media::kRTCVideoDecoderAdapter));
- return supported_formats_;
+ NOTREACHED();
+ return std::vector<webrtc::SdpVideoFormat>();
}
RTCVideoDecoderFactory::~RTCVideoDecoderFactory() {
@@ -185,12 +78,8 @@ std::unique_ptr<webrtc::VideoDecoder>
RTCVideoDecoderFactory::CreateVideoDecoder(
const webrtc::SdpVideoFormat& format) {
DVLOG(2) << __func__;
- std::unique_ptr<webrtc::VideoDecoder> decoder;
- if (base::FeatureList::IsEnabled(media::kRTCVideoDecoderAdapter)) {
- decoder = RTCVideoDecoderAdapter::Create(gpu_factories_, format);
- } else {
- decoder = RTCVideoDecoder::Create(format, gpu_factories_);
- }
+ std::unique_ptr<webrtc::VideoDecoder> decoder =
+ RTCVideoDecoderAdapter::Create(gpu_factories_, format);
// ScopedVideoDecoder uses the task runner to make sure the decoder is
// destructed on the correct thread.
return decoder ? std::make_unique<ScopedVideoDecoder>(
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder_factory.h b/chromium/content/renderer/media/webrtc/rtc_video_decoder_factory.h
index 8dc0ce8c89e..622dcb6c966 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_decoder_factory.h
+++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder_factory.h
@@ -38,7 +38,6 @@ class CONTENT_EXPORT RTCVideoDecoderFactory
private:
media::GpuVideoAcceleratorFactories* gpu_factories_;
- std::vector<webrtc::SdpVideoFormat> supported_formats_;
DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderFactory);
};
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc
deleted file mode 100644
index 0e47914ea10..00000000000
--- a/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc
+++ /dev/null
@@ -1,483 +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 <stdint.h>
-#include <string.h>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/renderer/media/webrtc/rtc_video_decoder.h"
-#include "media/base/gmock_callback_support.h"
-#include "media/video/mock_gpu_video_accelerator_factories.h"
-#include "media/video/mock_video_decode_accelerator.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/webrtc/media/base/vp9_profile.h"
-
-#if defined(OS_WIN)
-#include "base/command_line.h"
-#include "content/public/common/content_switches.h"
-#endif // defined(OS_WIN)
-
-using ::testing::_;
-using ::testing::AtLeast;
-using ::testing::Invoke;
-using ::testing::Return;
-using ::testing::SaveArg;
-using ::testing::Values;
-using ::testing::WithArgs;
-
-namespace content {
-
-namespace {
-
-static const int kMinResolutionWidth = 16;
-static const int kMinResolutionHeight = 16;
-static const int kMaxResolutionWidth = 1920;
-static const int kMaxResolutionHeight = 1088;
-
-} // namespace
-
-// TODO(wuchengli): add MockSharedMemory so more functions can be tested.
-class RTCVideoDecoderTest
- : public ::testing::TestWithParam<webrtc::VideoCodecType>,
- webrtc::DecodedImageCallback {
- public:
- RTCVideoDecoderTest()
- : mock_gpu_factories_(
- new media::MockGpuVideoAcceleratorFactories(nullptr)),
- vda_thread_("vda_thread"),
- idle_waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED) {
- memset(&codec_, 0, sizeof(codec_));
- }
-
- void SetUp() override {
- ASSERT_TRUE(vda_thread_.Start());
- vda_task_runner_ = vda_thread_.task_runner();
- mock_vda_ = new media::MockVideoDecodeAccelerator;
-
- media::VideoDecodeAccelerator::SupportedProfile supported_profile;
- supported_profile.min_resolution.SetSize(kMinResolutionWidth,
- kMinResolutionHeight);
- supported_profile.max_resolution.SetSize(kMaxResolutionWidth,
- kMaxResolutionHeight);
- supported_profile.profile = media::H264PROFILE_MAIN;
- capabilities_.supported_profiles.push_back(supported_profile);
- supported_profile.profile = media::VP8PROFILE_ANY;
- capabilities_.supported_profiles.push_back(supported_profile);
- supported_profile.profile = media::VP9PROFILE_PROFILE0;
- capabilities_.supported_profiles.push_back(supported_profile);
- supported_profile.profile = media::VP9PROFILE_PROFILE2;
- capabilities_.supported_profiles.push_back(supported_profile);
-
- EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner())
- .WillRepeatedly(Return(vda_task_runner_));
- EXPECT_CALL(*mock_gpu_factories_.get(),
- GetVideoDecodeAcceleratorCapabilities())
- .WillRepeatedly(Return(capabilities_));
- EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoDecodeAccelerator())
- .WillRepeatedly(Return(mock_vda_));
- EXPECT_CALL(*mock_vda_, Initialize(_, _))
- .Times(1)
- .WillRepeatedly(Return(true));
- EXPECT_CALL(*mock_vda_, Destroy()).Times(1);
-
-#if defined(OS_WIN)
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableWin7WebRtcHWH264Decoding);
-#endif // defined(OS_WIN)
- }
-
- void TearDown() override {
- DVLOG(2) << "TearDown";
- EXPECT_TRUE(vda_thread_.IsRunning());
- RunUntilIdle(); // Wait until all callbascks complete.
- vda_task_runner_->DeleteSoon(FROM_HERE, rtc_decoder_.release());
- // Make sure the decoder is released before stopping the thread.
- RunUntilIdle();
- vda_thread_.Stop();
- }
-
- int32_t Decoded(webrtc::VideoFrame& decoded_image) override {
- DVLOG(2) << "Decoded";
- EXPECT_EQ(vda_task_runner_,
- blink::scheduler::GetSingleThreadTaskRunnerForTesting());
- return WEBRTC_VIDEO_CODEC_OK;
- }
-
- void CreateDecoder(const webrtc::SdpVideoFormat& format) {
- DVLOG(2) << "CreateDecoder";
- codec_.codecType = webrtc::PayloadStringToCodecType(format.name);
- rtc_decoder_ = RTCVideoDecoder::Create(format, mock_gpu_factories_.get());
- }
-
- void CreateDecoder(webrtc::VideoCodecType codec_type) {
- CreateDecoder(
- webrtc::SdpVideoFormat(webrtc::CodecTypeToPayloadString(codec_type)));
- }
-
- void Initialize() {
- DVLOG(2) << "Initialize";
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
- rtc_decoder_->RegisterDecodeCompleteCallback(this));
- }
-
- void NotifyResetDone() {
- DVLOG(2) << "NotifyResetDone";
- vda_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&RTCVideoDecoder::NotifyResetDone,
- base::Unretained(rtc_decoder_.get())));
- }
-
- void NotifyError(media::VideoDecodeAccelerator::Error error) {
- DVLOG(2) << "NotifyError";
- vda_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&RTCVideoDecoder::NotifyError,
- base::Unretained(rtc_decoder_.get()), error));
- }
-
- void RunUntilIdle() {
- DVLOG(2) << "RunUntilIdle";
- vda_task_runner_->PostTask(FROM_HERE,
- base::BindOnce(&base::WaitableEvent::Signal,
- base::Unretained(&idle_waiter_)));
- idle_waiter_.Wait();
- }
-
- bool CreateMockTextures(int32_t count,
- const gfx::Size& size,
- std::vector<uint32_t>* texture_ids,
- std::vector<gpu::Mailbox>* texture_mailboxes,
- uint32_t texture_target) {
- texture_ids->resize(count, 0);
- texture_mailboxes->resize(count, gpu::Mailbox());
- return true;
- }
-
- void ProvidePictureBuffers(uint32_t buffer_count,
- media::VideoPixelFormat format,
- uint32_t textures_per_buffer,
- const gfx::Size& size,
- uint32_t texture_target) {
- vda_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&RTCVideoDecoder::ProvidePictureBuffers,
- base::Unretained(rtc_decoder_.get()), buffer_count,
- format, textures_per_buffer, size, texture_target));
- RunUntilIdle();
- }
-
- void SetUpResetVDA() {
- mock_vda_after_reset_ = new media::MockVideoDecodeAccelerator;
- EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoDecodeAccelerator())
- .WillRepeatedly(Return(mock_vda_after_reset_));
- EXPECT_CALL(*mock_vda_after_reset_, Initialize(_, _))
- .Times(1)
- .WillRepeatedly(Return(true));
- EXPECT_CALL(*mock_vda_after_reset_, Destroy()).Times(1);
- }
-
- protected:
- std::unique_ptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_;
- media::MockVideoDecodeAccelerator* mock_vda_;
- media::MockVideoDecodeAccelerator* mock_vda_after_reset_;
- std::unique_ptr<RTCVideoDecoder> rtc_decoder_;
- webrtc::VideoCodec codec_;
- base::Thread vda_thread_;
- media::VideoDecodeAccelerator::Capabilities capabilities_;
-
- private:
- scoped_refptr<base::SingleThreadTaskRunner> vda_task_runner_;
-
- base::Lock lock_;
- base::WaitableEvent idle_waiter_;
-};
-
-TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) {
- CreateDecoder(webrtc::kVideoCodecVP8);
- std::unique_ptr<RTCVideoDecoder> null_rtc_decoder(RTCVideoDecoder::Create(
- webrtc::SdpVideoFormat("I420"), mock_gpu_factories_.get()));
- EXPECT_EQ(nullptr, null_rtc_decoder.get());
-}
-
-TEST_P(RTCVideoDecoderTest, CreateAndInitSucceeds) {
- const webrtc::VideoCodecType codec_type = GetParam();
- CreateDecoder(codec_type);
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
-}
-
-TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) {
- CreateDecoder(webrtc::kVideoCodecVP8);
- webrtc::EncodedImage input_image;
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED,
- rtc_decoder_->Decode(input_image, false, 0));
-}
-
-TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
- CreateDecoder(webrtc::kVideoCodecVP8);
- Initialize();
- webrtc::EncodedImage input_image;
- input_image._completeFrame = false;
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
- rtc_decoder_->Decode(input_image, false, 0));
-}
-
-TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
- CreateDecoder(webrtc::kVideoCodecVP8);
- Initialize();
- webrtc::EncodedImage input_image;
- input_image._completeFrame = true;
- bool missingFrames = true;
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
- rtc_decoder_->Decode(input_image, missingFrames, 0));
-}
-
-TEST_F(RTCVideoDecoderTest, FallBackToSoftwareOnVp9Svc) {
- // HW VP9 decoders don't handle more than one spatial layer. See
- // https://crbug.com/webrtc/9304, https://crbug.com/webrtc/9518 for details.
- // The RTC video decoder triggers software fallback if it receives stream
- // with more than one spatial layer.
- CreateDecoder(webrtc::kVideoCodecVP9);
- Initialize();
-
- webrtc::EncodedImage input_image;
- input_image.SetSpatialIndex(1);
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE,
- rtc_decoder_->Decode(input_image, false, 0));
-}
-
-TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
- CreateDecoder(webrtc::kVideoCodecVP8);
- Initialize();
- EXPECT_CALL(*mock_vda_, Reset())
- .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
-}
-
-TEST_F(RTCVideoDecoderTest, InitDecodeAfterRelease) {
- CreateDecoder(webrtc::kVideoCodecVP8);
- EXPECT_CALL(*mock_vda_, Reset())
- .WillRepeatedly(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
- Initialize();
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
- Initialize();
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
-}
-
-TEST_F(RTCVideoDecoderTest, IsBufferAfterReset) {
- CreateDecoder(webrtc::kVideoCodecVP8);
- EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
- EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
- RTCVideoDecoder::ID_INVALID));
- EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF - 2,
- RTCVideoDecoder::ID_HALF + 2));
- EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF + 2,
- RTCVideoDecoder::ID_HALF - 2));
-
- EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(0, 0));
- EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
- EXPECT_FALSE(
- rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF - 2));
- EXPECT_TRUE(
- rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF + 2));
-
- EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, 0));
- EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
- RTCVideoDecoder::ID_HALF - 2));
- EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
- RTCVideoDecoder::ID_HALF + 2));
- EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
- RTCVideoDecoder::ID_LAST));
-}
-
-TEST_F(RTCVideoDecoderTest, IsFirstBufferAfterReset) {
- CreateDecoder(webrtc::kVideoCodecVP8);
- EXPECT_TRUE(
- rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
- EXPECT_FALSE(
- rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_INVALID));
- EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(0, 0));
- EXPECT_TRUE(rtc_decoder_->IsFirstBufferAfterReset(1, 0));
- EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(2, 0));
-
- EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_HALF,
- RTCVideoDecoder::ID_HALF));
- EXPECT_TRUE(rtc_decoder_->IsFirstBufferAfterReset(
- RTCVideoDecoder::ID_HALF + 1, RTCVideoDecoder::ID_HALF));
- EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(
- RTCVideoDecoder::ID_HALF + 2, RTCVideoDecoder::ID_HALF));
-
- EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_LAST,
- RTCVideoDecoder::ID_LAST));
- EXPECT_TRUE(
- rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
- EXPECT_FALSE(
- rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST));
-}
-
-TEST_F(RTCVideoDecoderTest, MultipleTexturesPerBuffer) {
- CreateDecoder(webrtc::kVideoCodecVP8);
- const uint32_t kBufferCount = 5;
- const uint32_t kTexturesPerBuffer = 3;
- const gfx::Size kSize(48, 48);
-
- EXPECT_CALL(*mock_gpu_factories_.get(), CreateTextures(_, _, _, _, _))
- .WillRepeatedly(Invoke(this, &RTCVideoDecoderTest::CreateMockTextures));
- EXPECT_CALL(*mock_gpu_factories_.get(), DeleteTexture(_))
- .Times(kBufferCount * kTexturesPerBuffer);
-
- std::vector<media::PictureBuffer> pbs;
- EXPECT_CALL(*mock_vda_, AssignPictureBuffers(_)).WillOnce(SaveArg<0>(&pbs));
- ProvidePictureBuffers(kBufferCount, media::PIXEL_FORMAT_UNKNOWN,
- kTexturesPerBuffer, kSize, 0);
- EXPECT_EQ(kBufferCount, pbs.size());
- for (const auto pb : pbs) {
- EXPECT_EQ(kSize, pb.size());
- EXPECT_EQ(kTexturesPerBuffer, pb.client_texture_ids().size());
- }
-}
-
-TEST_F(RTCVideoDecoderTest, ParsesVP9CodecProfile) {
- webrtc::SdpVideoFormat sdp_format(
- "VP9", {{webrtc::kVP9FmtpProfileId,
- webrtc::VP9ProfileToString(webrtc::VP9Profile::kProfile2)}});
- CreateDecoder(sdp_format);
- EXPECT_EQ(media::VP9PROFILE_PROFILE2, rtc_decoder_->vda_codec_profile_);
-}
-
-// Tests/Verifies that |rtc_encoder_| drops incoming frames and its error
-// counter is increased when decoder implementation calls NotifyError().
-TEST_P(RTCVideoDecoderTest, GetVDAErrorCounterForNotifyError) {
- const webrtc::VideoCodecType codec_type = GetParam();
- CreateDecoder(codec_type);
- Initialize();
-
- webrtc::EncodedImage input_image;
- uint8_t buffer[kMinResolutionWidth * kMaxResolutionHeight];
- input_image._completeFrame = true;
- input_image._encodedWidth = 0;
- input_image._encodedHeight = 0;
- input_image._frameType = webrtc::VideoFrameType::kVideoFrameDelta;
- input_image.set_buffer(buffer, sizeof(buffer));
- input_image.set_size(sizeof(buffer));
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
- rtc_decoder_->Decode(input_image, false, 0));
- RunUntilIdle();
-
- // Notify the decoder about a platform error.
- NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
- RunUntilIdle();
- EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
-
- // Expect decode call to reset decoder, and set up a new VDA to track it.
- SetUpResetVDA();
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
- rtc_decoder_->Decode(input_image, false, 0));
- EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
-
- // Decoder expects a frame with size after reset, so drops any other frames.
- // However, we should still increment the error counter.
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
- rtc_decoder_->Decode(input_image, false, 0));
- EXPECT_EQ(2, rtc_decoder_->GetVDAErrorCounterForTesting());
-}
-
-// Tests/Verifies that |rtc_decoder_| increases its error counter when it runs
-// out of pending buffers.
-TEST_P(RTCVideoDecoderTest, GetVDAErrorCounterForRunningOutOfPendingBuffers) {
- const webrtc::VideoCodecType codec_type = GetParam();
- CreateDecoder(codec_type);
- Initialize();
-
- webrtc::EncodedImage input_image;
- uint8_t buffer[1];
- input_image._completeFrame = true;
- input_image._encodedWidth = 640;
- input_image._encodedHeight = 480;
- input_image._frameType = webrtc::VideoFrameType::kVideoFrameKey;
- input_image.set_buffer(buffer, sizeof(buffer));
- input_image.set_size(sizeof(buffer));
-
- EXPECT_CALL(*mock_vda_, Decode(_)).Times(AtLeast(1));
-
- const uint32_t kMaxNumDecodeRequests = 100;
- uint32_t i = 0;
- while (i++ < kMaxNumDecodeRequests) {
- const int32_t result = rtc_decoder_->Decode(input_image, false, 0);
- RunUntilIdle();
- if (result == WEBRTC_VIDEO_CODEC_OK)
- EXPECT_EQ(0, rtc_decoder_->GetVDAErrorCounterForTesting());
- else if (result == WEBRTC_VIDEO_CODEC_ERROR) {
- // Expect to saturate all buffer resources and increase error counter.
- EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
- return;
- } else {
- ASSERT_TRUE(false);
- return;
- }
- }
- // We have run out of kMaxNumDecodeRequests without forcing an error.
- ASSERT_TRUE(false);
-}
-
-// Tests/Verifies that |rtc_decoder_| increases its error counter when it keeps
-// getting frames with no size set.
-TEST_P(RTCVideoDecoderTest, GetVDAErrorCounterForSendingFramesWithoutSize) {
- const webrtc::VideoCodecType codec_type = GetParam();
- CreateDecoder(codec_type);
- Initialize();
-
- webrtc::EncodedImage input_image;
- uint8_t buffer[1];
- input_image._completeFrame = true;
- input_image._encodedWidth = 0;
- input_image._encodedHeight = 0;
- input_image._frameType = webrtc::VideoFrameType::kVideoFrameKey;
- input_image.set_buffer(buffer, sizeof(buffer));
- input_image.set_size(sizeof(buffer));
- const int kNumDecodeRequests = 3;
- for (int i = 0; i < kNumDecodeRequests; i++) {
- const int32_t result = rtc_decoder_->Decode(input_image, false, 0);
- RunUntilIdle();
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, result);
- EXPECT_EQ(i + 1, rtc_decoder_->GetVDAErrorCounterForTesting());
- }
-}
-
-TEST_P(RTCVideoDecoderTest, Reinitialize) {
- const webrtc::VideoCodecType codec_type = GetParam();
- CreateDecoder(codec_type);
- Initialize();
-
- webrtc::EncodedImage input_image;
- uint8_t buffer[1];
- input_image._completeFrame = true;
- input_image._encodedWidth = 640;
- input_image._encodedHeight = 480;
- input_image._frameType = webrtc::VideoFrameType::kVideoFrameKey;
- input_image.set_buffer(buffer, sizeof(buffer));
- input_image.set_size(sizeof(buffer));
- EXPECT_CALL(*mock_vda_, Decode(_)).Times(1);
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Decode(input_image, false, 0));
- RunUntilIdle();
-
- // InitDecode and Decode after Release should succeed.
- EXPECT_CALL(*mock_vda_, Reset()).Times(1);
- rtc_decoder_->Release();
- Initialize();
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Decode(input_image, false, 0));
-}
-
-INSTANTIATE_TEST_SUITE_P(CodecProfiles,
- RTCVideoDecoderTest,
- Values(webrtc::kVideoCodecVP8,
- webrtc::kVideoCodecH264));
-
-} // content
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc b/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc
index e8162d20ca2..332725545c7 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc
@@ -87,8 +87,6 @@ bool GetRTPFragmentationHeaderH264(webrtc::RTPFragmentationHeader* header,
for (size_t i = 0; i < nalu_vector.size(); ++i) {
header->fragmentationOffset[i] = nalu_vector[i].data - data;
header->fragmentationLength[i] = nalu_vector[i].size;
- header->fragmentationPlType[i] = 0;
- header->fragmentationTimeDiff[i] = 0;
}
return true;
}
@@ -145,8 +143,8 @@ class RTCVideoEncoder::Impl
void UseOutputBitstreamBufferId(int32_t bitstream_buffer_id);
// Request encoding parameter change for the underlying encoder.
- void RequestEncodingParametersChange(webrtc::VideoBitrateAllocation bitrate,
- uint32_t framerate);
+ void RequestEncodingParametersChange(
+ const webrtc::VideoEncoder::RateControlParameters& parameters);
void RegisterEncodeCompleteCallback(base::WaitableEvent* async_waiter,
int32_t* async_retval,
@@ -205,7 +203,7 @@ class RTCVideoEncoder::Impl
// Checks if the frame size is different than hardware accelerator
// requirements.
- bool RequiresSizeChange(const scoped_refptr<media::VideoFrame>& frame) const;
+ bool RequiresSizeChange(const media::VideoFrame& frame) const;
// Return an encoded output buffer to WebRTC.
void ReturnEncodedImage(const webrtc::EncodedImage& image,
@@ -392,29 +390,29 @@ void RTCVideoEncoder::Impl::UseOutputBitstreamBufferId(
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (video_encoder_) {
video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
- bitstream_buffer_id,
- output_buffers_[bitstream_buffer_id]->handle(),
+ bitstream_buffer_id, output_buffers_[bitstream_buffer_id]->handle(),
+ false /* read_only */,
output_buffers_[bitstream_buffer_id]->mapped_size()));
output_buffers_free_count_++;
}
}
void RTCVideoEncoder::Impl::RequestEncodingParametersChange(
- webrtc::VideoBitrateAllocation bitrate,
- uint32_t framerate) {
- DVLOG(3) << __func__ << " bitrate=" << bitrate.ToString()
- << ", framerate=" << framerate;
+ const webrtc::VideoEncoder::RateControlParameters& parameters) {
+ DVLOG(3) << __func__ << " bitrate=" << parameters.bitrate.ToString()
+ << ", framerate=" << parameters.framerate_fps;
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// This is a workaround to zero being temporarily provided, as part of the
// initial setup, by WebRTC.
- if (bitrate.get_sum_bps() == 0) {
- bitrate.SetBitrate(0, 0, 1);
- }
- framerate = std::max(1u, framerate);
-
if (video_encoder_) {
media::VideoBitrateAllocation allocation;
+ if (parameters.bitrate.get_sum_bps() == 0) {
+ allocation.SetBitrate(0, 0, 1);
+ }
+ uint32_t framerate =
+ std::max(1u, static_cast<uint32_t>(parameters.framerate_fps + 0.5));
+
for (size_t spatial_id = 0;
spatial_id < media::VideoBitrateAllocation::kMaxSpatialLayers;
++spatial_id) {
@@ -422,17 +420,19 @@ void RTCVideoEncoder::Impl::RequestEncodingParametersChange(
temporal_id < media::VideoBitrateAllocation::kMaxTemporalLayers;
++temporal_id) {
// TODO(sprang): Clean this up if/when webrtc struct moves to int.
- uint32_t layer_bitrate = bitrate.GetBitrate(spatial_id, temporal_id);
+ uint32_t layer_bitrate =
+ parameters.bitrate.GetBitrate(spatial_id, temporal_id);
RTC_CHECK_LE(layer_bitrate,
static_cast<uint32_t>(std::numeric_limits<int>::max()));
if (!allocation.SetBitrate(spatial_id, temporal_id, layer_bitrate)) {
LOG(WARNING) << "Overflow in bitrate allocation: "
- << bitrate.ToString();
+ << parameters.bitrate.ToString();
break;
}
}
}
- DCHECK_EQ(allocation.GetSumBps(), static_cast<int>(bitrate.get_sum_bps()));
+ DCHECK_EQ(allocation.GetSumBps(),
+ static_cast<int>(parameters.bitrate.get_sum_bps()));
video_encoder_->RequestEncodingParametersChange(allocation, framerate);
}
}
@@ -504,7 +504,8 @@ void RTCVideoEncoder::Impl::RequireBitstreamBuffers(
// Immediately provide all output buffers to the VEA.
for (size_t i = 0; i < output_buffers_.size(); ++i) {
video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
- i, output_buffers_[i]->handle(), output_buffers_[i]->mapped_size()));
+ i, output_buffers_[i]->handle(), false /* read_only */,
+ output_buffers_[i]->mapped_size()));
output_buffers_free_count_++;
}
DCHECK_EQ(GetStatus(), WEBRTC_VIDEO_CODEC_UNINITIALIZED);
@@ -564,9 +565,10 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(
capture_timestamp_ms = current_time_ms;
}
- webrtc::EncodedImage image(static_cast<uint8_t*>(output_buffer->memory()),
- metadata.payload_size_bytes,
- output_buffer->mapped_size());
+ webrtc::EncodedImage image;
+ image.Allocate(metadata.payload_size_bytes);
+ image.set_size(metadata.payload_size_bytes);
+ memcpy(image.data(), output_buffer->memory(), metadata.payload_size_bytes);
image._encodedWidth = input_visible_size_.width();
image._encodedHeight = input_visible_size_.height();
image.SetTimestamp(rtp_timestamp.value());
@@ -649,7 +651,7 @@ void RTCVideoEncoder::Impl::EncodeOneFrame() {
frame = static_cast<WebRtcVideoFrameAdapter*>(
next_frame->video_frame_buffer().get())
->getMediaVideoFrame();
- requires_copy = RequiresSizeChange(frame) ||
+ requires_copy = RequiresSizeChange(*frame) ||
frame->storage_type() != media::VideoFrame::STORAGE_SHMEM;
} else {
requires_copy = true;
@@ -694,8 +696,8 @@ void RTCVideoEncoder::Impl::EncodeOneFrame() {
return;
}
}
- frame->AddDestructionObserver(media::BindToCurrentLoop(
- base::Bind(&RTCVideoEncoder::Impl::EncodeFrameFinished, this, index)));
+ frame->AddDestructionObserver(media::BindToCurrentLoop(base::BindOnce(
+ &RTCVideoEncoder::Impl::EncodeFrameFinished, this, index)));
if (!failed_timestamp_match_) {
DCHECK(std::find_if(pending_timestamps_.begin(), pending_timestamps_.end(),
[&frame](const RTCTimestamps& entry) {
@@ -746,9 +748,9 @@ bool RTCVideoEncoder::Impl::IsBitrateTooHigh(uint32_t bitrate) {
}
bool RTCVideoEncoder::Impl::RequiresSizeChange(
- const scoped_refptr<media::VideoFrame>& frame) const {
- return (frame->coded_size() != input_frame_coded_size_ ||
- frame->visible_rect() != gfx::Rect(input_visible_size_));
+ const media::VideoFrame& frame) const {
+ return (frame.coded_size() != input_frame_coded_size_ ||
+ frame.visible_rect() != gfx::Rect(input_visible_size_));
}
void RTCVideoEncoder::Impl::RegisterEncodeCompleteCallback(
@@ -782,8 +784,6 @@ void RTCVideoEncoder::Impl::ReturnEncodedImage(
header.VerifyAndAllocateFragmentationHeader(1);
header.fragmentationOffset[0] = 0;
header.fragmentationLength[0] = image.size();
- header.fragmentationPlType[0] = 0;
- header.fragmentationTimeDiff[0] = 0;
break;
case webrtc::kVideoCodecH264:
if (!GetRTPFragmentationHeaderH264(&header, image.data(), image.size())) {
@@ -976,27 +976,26 @@ int32_t RTCVideoEncoder::Release() {
return WEBRTC_VIDEO_CODEC_OK;
}
-int32_t RTCVideoEncoder::SetRateAllocation(
- const webrtc::VideoBitrateAllocation& allocation,
- uint32_t frame_rate) {
- DVLOG(3) << __func__ << " new_bit_rate=" << allocation.ToString()
- << ", frame_rate=" << frame_rate;
+void RTCVideoEncoder::SetRates(
+ const webrtc::VideoEncoder::RateControlParameters& parameters) {
+ DVLOG(3) << __func__ << " new_bit_rate=" << parameters.bitrate.ToString()
+ << ", frame_rate=" << parameters.framerate_fps;
if (!impl_.get()) {
DVLOG(3) << "Encoder is not initialized";
- return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
+ return;
}
const int32_t retval = impl_->GetStatus();
if (retval != WEBRTC_VIDEO_CODEC_OK) {
DVLOG(3) << __func__ << " returning " << retval;
- return retval;
+ return;
}
gpu_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&RTCVideoEncoder::Impl::RequestEncodingParametersChange,
- impl_, allocation, frame_rate));
- return WEBRTC_VIDEO_CODEC_OK;
+ impl_, parameters));
+ return;
}
webrtc::VideoEncoder::EncoderInfo RTCVideoEncoder::GetEncoderInfo() const {
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_encoder.h b/chromium/content/renderer/media/webrtc/rtc_video_encoder.h
index bf33b7c23c4..fe0553dbc6a 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_encoder.h
+++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder.h
@@ -56,8 +56,8 @@ class CONTENT_EXPORT RTCVideoEncoder : public webrtc::VideoEncoder {
int32_t RegisterEncodeCompleteCallback(
webrtc::EncodedImageCallback* callback) override;
int32_t Release() override;
- int32_t SetRateAllocation(const webrtc::VideoBitrateAllocation& allocation,
- uint32_t framerate) override;
+ void SetRates(
+ const webrtc::VideoEncoder::RateControlParameters& parameters) override;
EncoderInfo GetEncoderInfo() const override;
private:
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc
index 2128596532f..e45d197ba1b 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc
@@ -39,19 +39,20 @@ const unsigned short kStartBitrate = 100;
class EncodedImageCallbackWrapper : public webrtc::EncodedImageCallback {
public:
- using EncodedCallback =
- base::Callback<void(const webrtc::EncodedImage& encoded_image,
- const webrtc::CodecSpecificInfo* codec_specific_info,
- const webrtc::RTPFragmentationHeader* fragmentation)>;
+ using EncodedCallback = base::OnceCallback<void(
+ const webrtc::EncodedImage& encoded_image,
+ const webrtc::CodecSpecificInfo* codec_specific_info,
+ const webrtc::RTPFragmentationHeader* fragmentation)>;
- EncodedImageCallbackWrapper(const EncodedCallback& encoded_callback)
- : encoded_callback_(encoded_callback) {}
+ EncodedImageCallbackWrapper(EncodedCallback encoded_callback)
+ : encoded_callback_(std::move(encoded_callback)) {}
Result OnEncodedImage(
const webrtc::EncodedImage& encoded_image,
const webrtc::CodecSpecificInfo* codec_specific_info,
const webrtc::RTPFragmentationHeader* fragmentation) override {
- encoded_callback_.Run(encoded_image, codec_specific_info, fragmentation);
+ std::move(encoded_callback_)
+ .Run(encoded_image, codec_specific_info, fragmentation);
return Result(Result::OK);
}
@@ -140,8 +141,9 @@ class RTCVideoEncoderTest
}
void RegisterEncodeCompleteCallback(
- const EncodedImageCallbackWrapper::EncodedCallback& callback) {
- callback_wrapper_.reset(new EncodedImageCallbackWrapper(callback));
+ EncodedImageCallbackWrapper::EncodedCallback callback) {
+ callback_wrapper_ =
+ std::make_unique<EncodedImageCallbackWrapper>(std::move(callback));
rtc_encoder_->RegisterEncodeCompleteCallback(callback_wrapper_.get());
}
@@ -163,7 +165,7 @@ class RTCVideoEncoderTest
kInputFrameFillU, kInputFrameFillV) == 0);
}
- void VerifyEncodedFrame(const scoped_refptr<media::VideoFrame>& frame,
+ void VerifyEncodedFrame(scoped_refptr<media::VideoFrame> frame,
bool force_keyframe) {
DVLOG(3) << __func__;
EXPECT_EQ(kInputFrameWidth, frame->visible_rect().width());
@@ -176,7 +178,7 @@ class RTCVideoEncoderTest
frame->visible_data(media::VideoFrame::kVPlane)[0]);
}
- void ReturnFrameWithTimeStamp(const scoped_refptr<media::VideoFrame>& frame,
+ void ReturnFrameWithTimeStamp(scoped_refptr<media::VideoFrame> frame,
bool force_keyframe) {
client_->BitstreamBufferReady(
0,
@@ -239,7 +241,7 @@ TEST_F(RTCVideoEncoderTest, SoftwareFallbackAfterError) {
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_encoder_->InitEncode(&codec, 1, 12345));
EXPECT_CALL(*mock_vea_, Encode(_, _))
- .WillOnce(Invoke([this](const scoped_refptr<media::VideoFrame>&, bool) {
+ .WillOnce(Invoke([this](scoped_refptr<media::VideoFrame>, bool) {
encoder_thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(
@@ -253,16 +255,24 @@ TEST_F(RTCVideoEncoderTest, SoftwareFallbackAfterError) {
FillFrameBuffer(buffer);
std::vector<webrtc::VideoFrameType> frame_types;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
- rtc_encoder_->Encode(
- webrtc::VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0),
- &frame_types));
+ rtc_encoder_->Encode(webrtc::VideoFrame::Builder()
+ .set_video_frame_buffer(buffer)
+ .set_timestamp_rtp(0)
+ .set_timestamp_us(0)
+ .set_rotation(webrtc::kVideoRotation_0)
+ .build(),
+ &frame_types));
RunUntilIdle();
// Expect the next frame to return SW fallback.
EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE,
- rtc_encoder_->Encode(
- webrtc::VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0),
- &frame_types));
+ rtc_encoder_->Encode(webrtc::VideoFrame::Builder()
+ .set_video_frame_buffer(buffer)
+ .set_timestamp_rtp(0)
+ .set_timestamp_us(0)
+ .set_rotation(webrtc::kVideoRotation_0)
+ .build(),
+ &frame_types));
}
TEST_F(RTCVideoEncoderTest, EncodeScaledFrame) {
@@ -280,14 +290,23 @@ TEST_F(RTCVideoEncoderTest, EncodeScaledFrame) {
FillFrameBuffer(buffer);
std::vector<webrtc::VideoFrameType> frame_types;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
- rtc_encoder_->Encode(
- webrtc::VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0),
- &frame_types));
+ rtc_encoder_->Encode(webrtc::VideoFrame::Builder()
+ .set_video_frame_buffer(buffer)
+ .set_timestamp_rtp(0)
+ .set_timestamp_us(0)
+ .set_rotation(webrtc::kVideoRotation_0)
+ .build(),
+ &frame_types));
const rtc::scoped_refptr<webrtc::I420Buffer> upscaled_buffer =
webrtc::I420Buffer::Create(2 * kInputFrameWidth, 2 * kInputFrameHeight);
FillFrameBuffer(upscaled_buffer);
- webrtc::VideoFrame rtc_frame(upscaled_buffer, 0, 0, webrtc::kVideoRotation_0);
+ webrtc::VideoFrame rtc_frame = webrtc::VideoFrame::Builder()
+ .set_video_frame_buffer(upscaled_buffer)
+ .set_timestamp_rtp(0)
+ .set_timestamp_us(0)
+ .set_rotation(webrtc::kVideoRotation_0)
+ .build();
rtc_frame.set_ntp_time_ms(123456);
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
rtc_encoder_->Encode(rtc_frame, &frame_types));
@@ -302,8 +321,8 @@ TEST_F(RTCVideoEncoderTest, PreserveTimestamps) {
const uint32_t rtp_timestamp = 1234567;
const uint32_t capture_time_ms = 3456789;
RegisterEncodeCompleteCallback(
- base::Bind(&RTCVideoEncoderTest::VerifyTimestamp, base::Unretained(this),
- rtp_timestamp, capture_time_ms));
+ base::BindOnce(&RTCVideoEncoderTest::VerifyTimestamp,
+ base::Unretained(this), rtp_timestamp, capture_time_ms));
EXPECT_CALL(*mock_vea_, Encode(_, _))
.WillOnce(Invoke(this, &RTCVideoEncoderTest::ReturnFrameWithTimeStamp));
@@ -311,8 +330,12 @@ TEST_F(RTCVideoEncoderTest, PreserveTimestamps) {
webrtc::I420Buffer::Create(kInputFrameWidth, kInputFrameHeight);
FillFrameBuffer(buffer);
std::vector<webrtc::VideoFrameType> frame_types;
- webrtc::VideoFrame rtc_frame(buffer, rtp_timestamp, 0,
- webrtc::kVideoRotation_0);
+ webrtc::VideoFrame rtc_frame = webrtc::VideoFrame::Builder()
+ .set_video_frame_buffer(buffer)
+ .set_timestamp_rtp(rtp_timestamp)
+ .set_timestamp_us(0)
+ .set_rotation(webrtc::kVideoRotation_0)
+ .build();
rtc_frame.set_timestamp_us(capture_time_ms * rtc::kNumMicrosecsPerMillisec);
// We need to set ntp_time_ms because it will be used to derive
// media::VideoFrame timestamp.
diff --git a/chromium/content/renderer/media/webrtc/track_observer.h b/chromium/content/renderer/media/webrtc/track_observer.h
index 760fc98245f..53a5665d3b5 100644
--- a/chromium/content/renderer/media/webrtc/track_observer.h
+++ b/chromium/content/renderer/media/webrtc/track_observer.h
@@ -16,8 +16,8 @@ namespace content {
class CONTENT_EXPORT TrackObserver {
public:
- typedef base::Callback<void(webrtc::MediaStreamTrackInterface::TrackState)>
- OnChangedCallback;
+ using OnChangedCallback = base::RepeatingCallback<void(
+ webrtc::MediaStreamTrackInterface::TrackState)>;
TrackObserver(const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
const scoped_refptr<webrtc::MediaStreamTrackInterface>& track);
diff --git a/chromium/content/renderer/media/webrtc/transmission_encoding_info_handler_unittest.cc b/chromium/content/renderer/media/webrtc/transmission_encoding_info_handler_unittest.cc
index 2e30db06321..813130c1da8 100644
--- a/chromium/content/renderer/media/webrtc/transmission_encoding_info_handler_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/transmission_encoding_info_handler_unittest.cc
@@ -12,7 +12,6 @@
#include "media/video/video_encode_accelerator.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/media_capabilities/web_audio_configuration.h"
-#include "third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_callbacks.h"
#include "third_party/blink/public/platform/modules/media_capabilities/web_media_configuration.h"
#include "third_party/blink/public/platform/modules/media_capabilities/web_video_configuration.h"
#include "third_party/blink/public/platform/web_string.h"
diff --git a/chromium/content/renderer/media/webrtc/video_codec_factory.cc b/chromium/content/renderer/media/webrtc/video_codec_factory.cc
index c32848b5c77..ea4220736e7 100644
--- a/chromium/content/renderer/media/webrtc/video_codec_factory.cc
+++ b/chromium/content/renderer/media/webrtc/video_codec_factory.cc
@@ -6,7 +6,6 @@
#include "base/base_switches.h"
#include "base/command_line.h"
-#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "content/public/common/content_switches.h"
@@ -63,14 +62,7 @@ std::vector<webrtc::SdpVideoFormat> MergeFormats(
std::unique_ptr<webrtc::VideoDecoder> CreateDecoder(
webrtc::VideoDecoderFactory* factory,
const webrtc::SdpVideoFormat& format) {
- if (base::FeatureList::IsEnabled(media::kRTCVideoDecoderAdapter))
- return factory ? factory->CreateVideoDecoder(format) : nullptr;
-
- // TODO(sandersd): Remove calls to GetSupportedFormats() once the
- // RTCVideoDecoder path is gone.
- return IsFormatSupported(factory, format)
- ? factory->CreateVideoDecoder(format)
- : nullptr;
+ return factory ? factory->CreateVideoDecoder(format) : nullptr;
}
std::unique_ptr<webrtc::VideoDecoder> Wrap(
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc
index 736c1f0b55f..32a12557ee7 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc
@@ -51,8 +51,8 @@ class SharedAudioRenderer : public blink::WebMediaStreamAudioRenderer {
// Callback definition for a callback that is called when when Play(), Pause()
// or SetVolume are called (whenever the internal |playing_state_| changes).
using OnPlayStateChanged =
- base::Callback<void(const blink::WebMediaStream&,
- WebRtcAudioRenderer::PlayingState*)>;
+ base::RepeatingCallback<void(const blink::WebMediaStream&,
+ WebRtcAudioRenderer::PlayingState*)>;
// Signals that the PlayingState* is about to become invalid, see comment in
// OnPlayStateRemoved.
@@ -222,7 +222,7 @@ scoped_refptr<blink::WebMediaStreamAudioRenderer>
WebRtcAudioRenderer::CreateSharedAudioRendererProxy(
const blink::WebMediaStream& media_stream) {
SharedAudioRenderer::OnPlayStateChanged on_play_state_changed =
- base::Bind(&WebRtcAudioRenderer::OnPlayStateChanged, this);
+ base::BindRepeating(&WebRtcAudioRenderer::OnPlayStateChanged, this);
SharedAudioRenderer::OnPlayStateRemoved on_play_state_removed =
base::BindOnce(&WebRtcAudioRenderer::OnPlayStateRemoved, this);
return new SharedAudioRenderer(this, media_stream,
@@ -430,10 +430,10 @@ int WebRtcAudioRenderer::Render(base::TimeDelta delay,
if (prior_frames_skipped > 0) {
const int source_frames_per_buffer = sink_params_.sample_rate() / 100;
if (!audio_fifo_ && prior_frames_skipped != source_frames_per_buffer) {
- audio_fifo_.reset(new media::AudioPullFifo(
+ audio_fifo_ = std::make_unique<media::AudioPullFifo>(
kChannels, source_frames_per_buffer,
- base::Bind(&WebRtcAudioRenderer::SourceCallback,
- base::Unretained(this))));
+ base::BindRepeating(&WebRtcAudioRenderer::SourceCallback,
+ base::Unretained(this)));
}
std::unique_ptr<media::AudioBus> drop_bus =
@@ -683,10 +683,10 @@ void WebRtcAudioRenderer::PrepareSink() {
if ((!audio_fifo_ && different_source_sink_frames) ||
(audio_fifo_ &&
audio_fifo_->SizeInFrames() != source_frames_per_buffer)) {
- audio_fifo_.reset(new media::AudioPullFifo(
+ audio_fifo_ = std::make_unique<media::AudioPullFifo>(
kChannels, source_frames_per_buffer,
- base::Bind(&WebRtcAudioRenderer::SourceCallback,
- base::Unretained(this))));
+ base::BindRepeating(&WebRtcAudioRenderer::SourceCallback,
+ base::Unretained(this)));
}
sink_params_ = new_sink_params;
}
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
index c5675c5db39..7fcb52eabf6 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
@@ -258,8 +258,8 @@ TEST_F(WebRtcAudioRendererTest, SwitchOutputDevice) {
base::RunLoop loop;
renderer_proxy_->SwitchOutputDevice(
kOtherOutputDeviceId,
- base::Bind(&WebRtcAudioRendererTest::SwitchDeviceCallback,
- base::Unretained(this), &loop));
+ base::BindOnce(&WebRtcAudioRendererTest::SwitchDeviceCallback,
+ base::Unretained(this), &loop));
loop.Run();
EXPECT_EQ(kOtherOutputDeviceId,
mock_sink_->GetOutputDeviceInfo().device_id());
@@ -284,8 +284,8 @@ TEST_F(WebRtcAudioRendererTest, SwitchOutputDeviceInvalidDevice) {
base::RunLoop loop;
renderer_proxy_->SwitchOutputDevice(
kInvalidOutputDeviceId,
- base::Bind(&WebRtcAudioRendererTest::SwitchDeviceCallback,
- base::Unretained(this), &loop));
+ base::BindOnce(&WebRtcAudioRendererTest::SwitchDeviceCallback,
+ base::Unretained(this), &loop));
loop.Run();
EXPECT_EQ(kDefaultOutputDeviceId,
original_sink->GetOutputDeviceInfo().device_id());
@@ -325,8 +325,8 @@ TEST_F(WebRtcAudioRendererTest, SwitchOutputDeviceStoppedSource) {
renderer_proxy_->Stop();
renderer_proxy_->SwitchOutputDevice(
kInvalidOutputDeviceId,
- base::BindRepeating(&WebRtcAudioRendererTest::SwitchDeviceCallback,
- base::Unretained(this), &loop));
+ base::BindOnce(&WebRtcAudioRendererTest::SwitchDeviceCallback,
+ base::Unretained(this), &loop));
loop.Run();
}
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc
index 45bc0a620e6..8924c755ba0 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc
@@ -26,8 +26,8 @@ WebRtcAudioSink::WebRtcAudioSink(
std::move(track_source),
std::move(signaling_task_runner),
std::move(main_task_runner))),
- fifo_(base::Bind(&WebRtcAudioSink::DeliverRebufferedAudio,
- base::Unretained(this))) {
+ fifo_(base::BindRepeating(&WebRtcAudioSink::DeliverRebufferedAudio,
+ base::Unretained(this))) {
DVLOG(1) << "WebRtcAudioSink::WebRtcAudioSink()";
}
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc
index b8ab52f66b3..5c00cd164d4 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc
@@ -13,10 +13,9 @@ namespace {
template <typename Base>
class FrameAdapter : public Base {
public:
- explicit FrameAdapter(const scoped_refptr<media::VideoFrame>& frame)
+ explicit FrameAdapter(scoped_refptr<media::VideoFrame> frame)
: frame_(std::move(frame)) {}
- private:
int width() const override { return frame_->visible_rect().width(); }
int height() const override { return frame_->visible_rect().height(); }
@@ -44,41 +43,39 @@ class FrameAdapter : public Base {
return frame_->stride(media::VideoFrame::kVPlane);
}
+ protected:
scoped_refptr<media::VideoFrame> frame_;
};
template <typename BaseWithA>
class FrameAdapterWithA : public FrameAdapter<BaseWithA> {
public:
- FrameAdapterWithA(const scoped_refptr<media::VideoFrame>& frame)
- : FrameAdapter<BaseWithA>(std::move(frame)), frame_(std::move(frame)) {}
+ explicit FrameAdapterWithA(scoped_refptr<media::VideoFrame> frame)
+ : FrameAdapter<BaseWithA>(std::move(frame)) {}
- private:
const uint8_t* DataA() const override {
- return frame_->visible_data(media::VideoFrame::kAPlane);
+ return FrameAdapter<BaseWithA>::frame_->visible_data(
+ media::VideoFrame::kAPlane);
}
int StrideA() const override {
- return frame_->stride(media::VideoFrame::kAPlane);
+ return FrameAdapter<BaseWithA>::frame_->stride(media::VideoFrame::kAPlane);
}
-
- scoped_refptr<media::VideoFrame> frame_;
};
-void IsValidFrame(const scoped_refptr<media::VideoFrame>& frame) {
+void IsValidFrame(const media::VideoFrame& frame) {
// Paranoia checks.
- DCHECK(frame);
DCHECK(media::VideoFrame::IsValidConfig(
- frame->format(), frame->storage_type(), frame->coded_size(),
- frame->visible_rect(), frame->natural_size()));
- DCHECK(media::PIXEL_FORMAT_I420 == frame->format() ||
- media::PIXEL_FORMAT_I420A == frame->format());
- CHECK(reinterpret_cast<void*>(frame->data(media::VideoFrame::kYPlane)));
- CHECK(reinterpret_cast<void*>(frame->data(media::VideoFrame::kUPlane)));
- CHECK(reinterpret_cast<void*>(frame->data(media::VideoFrame::kVPlane)));
- CHECK(frame->stride(media::VideoFrame::kYPlane));
- CHECK(frame->stride(media::VideoFrame::kUPlane));
- CHECK(frame->stride(media::VideoFrame::kVPlane));
+ frame.format(), frame.storage_type(), frame.coded_size(),
+ frame.visible_rect(), frame.natural_size()));
+ DCHECK(media::PIXEL_FORMAT_I420 == frame.format() ||
+ media::PIXEL_FORMAT_I420A == frame.format());
+ CHECK(reinterpret_cast<const void*>(frame.data(media::VideoFrame::kYPlane)));
+ CHECK(reinterpret_cast<const void*>(frame.data(media::VideoFrame::kUPlane)));
+ CHECK(reinterpret_cast<const void*>(frame.data(media::VideoFrame::kVPlane)));
+ CHECK(frame.stride(media::VideoFrame::kYPlane));
+ CHECK(frame.stride(media::VideoFrame::kUPlane));
+ CHECK(frame.stride(media::VideoFrame::kVPlane));
}
} // anonymous namespace
@@ -86,8 +83,8 @@ void IsValidFrame(const scoped_refptr<media::VideoFrame>& frame) {
namespace content {
WebRtcVideoFrameAdapter::WebRtcVideoFrameAdapter(
- const scoped_refptr<media::VideoFrame>& frame)
- : frame_(frame) {}
+ scoped_refptr<media::VideoFrame> frame)
+ : frame_(std::move(frame)) {}
WebRtcVideoFrameAdapter::~WebRtcVideoFrameAdapter() {
}
@@ -105,7 +102,7 @@ int WebRtcVideoFrameAdapter::height() const {
}
rtc::scoped_refptr<webrtc::I420BufferInterface>
-WebRtcVideoFrameAdapter::ToI420() {
+WebRtcVideoFrameAdapter::CreateFrameAdapter() const {
// We cant convert texture synchronously due to threading issues, see
// https://crbug.com/663452. Instead, return a black frame (yuv = {0, 0x80,
// 0x80}).
@@ -116,7 +113,7 @@ WebRtcVideoFrameAdapter::ToI420() {
0x80, 0x80, frame_->timestamp()));
}
- IsValidFrame(frame_);
+ IsValidFrame(*frame_);
if (media::PIXEL_FORMAT_I420A == frame_->format()) {
return new rtc::RefCountedObject<
FrameAdapterWithA<webrtc::I420ABufferInterface>>(frame_);
@@ -125,4 +122,19 @@ WebRtcVideoFrameAdapter::ToI420() {
frame_);
}
+rtc::scoped_refptr<webrtc::I420BufferInterface>
+WebRtcVideoFrameAdapter::ToI420() {
+ if (!frame_adapter_) {
+ frame_adapter_ = CreateFrameAdapter();
+ }
+ return frame_adapter_;
+}
+
+const webrtc::I420BufferInterface* WebRtcVideoFrameAdapter::GetI420() const {
+ if (!frame_adapter_) {
+ frame_adapter_ = CreateFrameAdapter();
+ }
+ return frame_adapter_.get();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.h
index e20b215c965..24a3f0e51d4 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.h
@@ -17,7 +17,7 @@ namespace content {
// different threads, but that's safe since it's read-only.
class WebRtcVideoFrameAdapter : public webrtc::VideoFrameBuffer {
public:
- WebRtcVideoFrameAdapter(const scoped_refptr<media::VideoFrame>& frame);
+ explicit WebRtcVideoFrameAdapter(scoped_refptr<media::VideoFrame> frame);
scoped_refptr<media::VideoFrame> getMediaVideoFrame() const { return frame_; }
@@ -27,10 +27,17 @@ class WebRtcVideoFrameAdapter : public webrtc::VideoFrameBuffer {
int height() const override;
rtc::scoped_refptr<webrtc::I420BufferInterface> ToI420() override;
+ const webrtc::I420BufferInterface* GetI420() const override;
protected:
~WebRtcVideoFrameAdapter() override;
+ rtc::scoped_refptr<webrtc::I420BufferInterface> CreateFrameAdapter() const;
+
+ // Used to cache result of CreateFrameAdapter. Which is called from const
+ // GetI420().
+ mutable rtc::scoped_refptr<webrtc::I420BufferInterface> frame_adapter_;
+
scoped_refptr<media::VideoFrame> frame_;
};
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_track_source.cc b/chromium/content/renderer/media/webrtc/webrtc_video_track_source.cc
index 7db108c031b..b08a50625fb 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_track_source.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_track_source.cc
@@ -63,7 +63,7 @@ absl::optional<bool> WebRtcVideoTrackSource::needs_denoising() const {
}
void WebRtcVideoTrackSource::OnFrameCaptured(
- const scoped_refptr<media::VideoFrame>& frame) {
+ scoped_refptr<media::VideoFrame> frame) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
TRACE_EVENT0("media", "WebRtcVideoSource::OnFrameCaptured");
if (!(frame->IsMappable() &&
@@ -126,11 +126,11 @@ void WebRtcVideoTrackSource::OnFrameCaptured(
// Return |frame| directly if it is texture backed, because there is no
// cropping support for texture yet. See http://crbug/503653.
if (frame->HasTextures()) {
- DeliverFrame(frame,
- // The webrtc::VideoFrame::UpdateRect expected by WebRTC must
- // be relative to the |visible_rect()|. We need to translate.
- CropRectangle(accumulated_update_rect_, frame->visible_rect()),
- translated_camera_time_us);
+ // The webrtc::VideoFrame::UpdateRect expected by WebRTC must
+ // be relative to the |visible_rect()|. We need to translate.
+ const auto cropped_rect =
+ CropRectangle(accumulated_update_rect_, frame->visible_rect());
+ DeliverFrame(std::move(frame), cropped_rect, translated_camera_time_us);
return;
}
@@ -159,26 +159,27 @@ void WebRtcVideoTrackSource::OnFrameCaptured(
frame_adaptation_params.scale_to_height);
// Soft-apply the new (combined) cropping and scaling.
scoped_refptr<media::VideoFrame> video_frame =
- media::VideoFrame::WrapVideoFrame(frame, frame->format(),
+ media::VideoFrame::WrapVideoFrame(*frame, frame->format(),
cropped_visible_rect, adapted_size);
if (!video_frame)
return;
// Attach shared ownership of the wrapped |frame| to the wrapping
// |video_frame|.
- video_frame->AddDestructionObserver(base::BindOnce(
- base::DoNothing::Once<scoped_refptr<media::VideoFrame>>(), frame));
+ video_frame->AddDestructionObserver(
+ base::BindOnce(base::DoNothing::Once<scoped_refptr<media::VideoFrame>>(),
+ std::move(frame)));
// If no scaling is needed, return a wrapped version of |frame| directly.
// The soft-applied cropping will be taken into account by the remainder
// of the pipeline.
if (video_frame->natural_size() == video_frame->visible_rect().size()) {
- DeliverFrame(
- video_frame,
- // The webrtc::VideoFrame::UpdateRect expected by WebRTC must be
- // relative to the |visible_rect()|. We need to translate.
- CropRectangle(accumulated_update_rect_, video_frame->visible_rect()),
- translated_camera_time_us);
+ // The webrtc::VideoFrame::UpdateRect expected by WebRTC must be
+ // relative to the |visible_rect()|. We need to translate.
+ const auto cropped_rect =
+ CropRectangle(accumulated_update_rect_, video_frame->visible_rect());
+ DeliverFrame(std::move(video_frame), cropped_rect,
+ translated_camera_time_us);
return;
}
@@ -189,7 +190,7 @@ void WebRtcVideoTrackSource::OnFrameCaptured(
scaled_frame_pool_.CreateFrame(
has_alpha ? media::PIXEL_FORMAT_I420A : media::PIXEL_FORMAT_I420,
adapted_size, gfx::Rect(adapted_size), adapted_size,
- frame->timestamp());
+ video_frame->timestamp());
libyuv::I420Scale(
video_frame->visible_data(media::VideoFrame::kYPlane),
video_frame->stride(media::VideoFrame::kYPlane),
@@ -218,7 +219,7 @@ void WebRtcVideoTrackSource::OnFrameCaptured(
// When scaling is applied and any part of the frame has changed, we mark the
// whole frame as changed.
DeliverFrame(
- scaled_frame,
+ std::move(scaled_frame),
accumulated_update_rect_.IsEmpty()
? gfx::Rect()
: gfx::Rect(0, 0, adapted_size.width(), adapted_size.height()),
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_track_source.h b/chromium/content/renderer/media/webrtc/webrtc_video_track_source.h
index 3a869bea40a..f18cb033b6e 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_track_source.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_track_source.h
@@ -43,7 +43,7 @@ class CONTENT_EXPORT WebRtcVideoTrackSource
bool remote() const override;
bool is_screencast() const override;
absl::optional<bool> needs_denoising() const override;
- void OnFrameCaptured(const scoped_refptr<media::VideoFrame>& frame);
+ void OnFrameCaptured(scoped_refptr<media::VideoFrame> frame);
using webrtc::VideoTrackSourceInterface::AddOrUpdateSink;
using webrtc::VideoTrackSourceInterface::RemoveSink;
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_utils.h b/chromium/content/renderer/media/webrtc/webrtc_video_utils.h
index 1d91b2a4607..5bcfcf01e78 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_utils.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_utils.h
@@ -6,7 +6,7 @@
#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_UTILS_H_
#include "media/base/video_color_space.h"
-#include "media/base/video_rotation.h"
+#include "media/base/video_transformation.h"
#include "third_party/webrtc/api/video/color_space.h"
#include "third_party/webrtc/api/video/video_rotation.h"
diff --git a/chromium/content/renderer/media_capture_from_element/OWNERS b/chromium/content/renderer/media_capture_from_element/OWNERS
index d176cccc0c4..e2687aba018 100644
--- a/chromium/content/renderer/media_capture_from_element/OWNERS
+++ b/chromium/content/renderer/media_capture_from_element/OWNERS
@@ -1,6 +1,7 @@
-emircan@chromium.org
+guidou@chromium.org
# Original (legacy) owner.
+emircan@chromium.org
mcasas@chromium.org
# COMPONENT: Blink>MediaStream>CaptureFromElement
diff --git a/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc b/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc
deleted file mode 100644
index dd17ee95f5e..00000000000
--- a/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc
+++ /dev/null
@@ -1,507 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media_capture_from_element/canvas_capture_handler.h"
-
-#include <utility>
-
-#include "base/base64.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/macros.h"
-#include "base/rand_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "components/viz/common/gl_helper.h"
-#include "content/public/renderer/render_thread.h"
-#include "content/renderer/render_thread_impl.h"
-#include "media/base/limits.h"
-#include "third_party/blink/public/platform/modules/mediastream/webrtc_uma_histograms.h"
-#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
-#include "third_party/blink/public/platform/web_media_stream_source.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h"
-#include "third_party/blink/public/web/modules/mediastream/media_stream_video_capturer_source.h"
-#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
-#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
-#include "third_party/libyuv/include/libyuv.h"
-#include "third_party/skia/include/core/SkImage.h"
-#include "third_party/skia/include/gpu/GrBackendSurface.h"
-#include "ui/gfx/color_space.h"
-
-using media::VideoFrame;
-
-namespace content {
-
-namespace {
-
-// Return the gfx::ColorSpace that the pixels resulting from calling
-// ConvertToYUVFrame on |image| will be in.
-gfx::ColorSpace GetImageYUVColorSpace(sk_sp<SkImage> image) {
- // TODO: Determine the ColorSpace::MatrixID and ColorSpace::RangeID that the
- // calls to libyuv are assuming.
- return gfx::ColorSpace();
-}
-
-} // namespace
-
-// Implementation VideoCapturerSource that is owned by
-// MediaStreamVideoCapturerSource and delegates the Start/Stop calls to
-// CanvasCaptureHandler.
-// This class is single threaded and pinned to main render thread.
-class VideoCapturerSource : public media::VideoCapturerSource {
- public:
- VideoCapturerSource(base::WeakPtr<CanvasCaptureHandler> canvas_handler,
- const blink::WebSize& size,
- double frame_rate)
- : size_(size),
- frame_rate_(static_cast<float>(
- std::min(static_cast<double>(media::limits::kMaxFramesPerSecond),
- frame_rate))),
- canvas_handler_(canvas_handler) {
- DCHECK_LE(0, frame_rate_);
- }
-
- protected:
- media::VideoCaptureFormats GetPreferredFormats() override {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- media::VideoCaptureFormats formats;
- formats.push_back(media::VideoCaptureFormat(size_, frame_rate_,
- media::PIXEL_FORMAT_I420));
- formats.push_back(media::VideoCaptureFormat(size_, frame_rate_,
- media::PIXEL_FORMAT_I420A));
- return formats;
- }
- void StartCapture(const media::VideoCaptureParams& params,
- const blink::VideoCaptureDeliverFrameCB& frame_callback,
- const RunningCallback& running_callback) override {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- if (canvas_handler_.get()) {
- canvas_handler_->StartVideoCapture(params, frame_callback,
- running_callback);
- }
- }
- void RequestRefreshFrame() override {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- if (canvas_handler_.get())
- canvas_handler_->RequestRefreshFrame();
- }
- void StopCapture() override {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- if (canvas_handler_.get())
- canvas_handler_->StopVideoCapture();
- }
-
- private:
- const blink::WebSize size_;
- const float frame_rate_;
- // Bound to Main Render thread.
- base::ThreadChecker main_render_thread_checker_;
- // CanvasCaptureHandler is owned by CanvasDrawListener in blink. It is
- // guaranteed to be destroyed on Main Render thread and it would happen
- // independently of this class. Therefore, WeakPtr should always be checked
- // before use.
- base::WeakPtr<CanvasCaptureHandler> canvas_handler_;
-};
-
-class CanvasCaptureHandler::CanvasCaptureHandlerDelegate {
- public:
- explicit CanvasCaptureHandlerDelegate(
- media::VideoCapturerSource::VideoCaptureDeliverFrameCB new_frame_callback)
- : new_frame_callback_(new_frame_callback), weak_ptr_factory_(this) {
- io_thread_checker_.DetachFromThread();
- }
- ~CanvasCaptureHandlerDelegate() {
- DCHECK(io_thread_checker_.CalledOnValidThread());
- }
-
- void SendNewFrameOnIOThread(scoped_refptr<VideoFrame> video_frame,
- base::TimeTicks current_time) {
- DCHECK(io_thread_checker_.CalledOnValidThread());
- new_frame_callback_.Run(std::move(video_frame), current_time);
- }
-
- base::WeakPtr<CanvasCaptureHandlerDelegate> GetWeakPtrForIOThread() {
- return weak_ptr_factory_.GetWeakPtr();
- }
-
- private:
- const media::VideoCapturerSource::VideoCaptureDeliverFrameCB
- new_frame_callback_;
- // Bound to IO thread.
- base::ThreadChecker io_thread_checker_;
- base::WeakPtrFactory<CanvasCaptureHandlerDelegate> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(CanvasCaptureHandlerDelegate);
-};
-
-CanvasCaptureHandler::CanvasCaptureHandler(
- const blink::WebSize& size,
- double frame_rate,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- blink::WebMediaStreamTrack* track)
- : ask_for_new_frame_(false),
- io_task_runner_(std::move(io_task_runner)),
- weak_ptr_factory_(this) {
- std::unique_ptr<media::VideoCapturerSource> video_source(
- new VideoCapturerSource(weak_ptr_factory_.GetWeakPtr(), size,
- frame_rate));
- AddVideoCapturerSourceToVideoTrack(std::move(video_source), track);
-}
-
-CanvasCaptureHandler::~CanvasCaptureHandler() {
- DVLOG(3) << __func__;
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- io_task_runner_->DeleteSoon(FROM_HERE, delegate_.release());
-}
-
-// static
-std::unique_ptr<CanvasCaptureHandler>
-CanvasCaptureHandler::CreateCanvasCaptureHandler(
- const blink::WebSize& size,
- double frame_rate,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- blink::WebMediaStreamTrack* track) {
- // Save histogram data so we can see how much CanvasCapture is used.
- // The histogram counts the number of calls to the JS API.
- UpdateWebRTCMethodCount(blink::WebRTCAPIName::kCanvasCaptureStream);
-
- return std::unique_ptr<CanvasCaptureHandler>(new CanvasCaptureHandler(
- size, frame_rate, std::move(io_task_runner), track));
-}
-
-void CanvasCaptureHandler::SendNewFrame(
- sk_sp<SkImage> image,
- blink::WebGraphicsContext3DProvider* context_provider) {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- DCHECK(image);
- TRACE_EVENT0("webrtc", "CanvasCaptureHandler::SendNewFrame");
-
- // Initially try accessing pixels directly if they are in memory.
- SkPixmap pixmap;
- if (image->peekPixels(&pixmap) &&
- (pixmap.colorType() == kRGBA_8888_SkColorType ||
- pixmap.colorType() == kBGRA_8888_SkColorType) &&
- (pixmap.alphaType() == kUnpremul_SkAlphaType || image->isOpaque())) {
- const base::TimeTicks timestamp = base::TimeTicks::Now();
- SendFrame(ConvertToYUVFrame(image->isOpaque(), false,
- static_cast<const uint8_t*>(pixmap.addr(0, 0)),
- gfx::Size(pixmap.width(), pixmap.height()),
- pixmap.rowBytes(), pixmap.colorType()),
- timestamp, GetImageYUVColorSpace(image));
- return;
- }
-
- // Copy the pixels into memory synchronously. This call may block the main
- // render thread.
- if (!image->isTextureBacked()) {
- ReadARGBPixelsSync(image);
- return;
- }
-
- if (!context_provider) {
- DLOG(ERROR) << "Context lost, skipping frame";
- return;
- }
-
- // Try async reading SkImage if it is texture backed.
- if (image->isOpaque()) {
- ReadYUVPixelsAsync(image, context_provider);
- } else {
- ReadARGBPixelsAsync(image, context_provider);
- }
-}
-
-bool CanvasCaptureHandler::NeedsNewFrame() const {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- return ask_for_new_frame_;
-}
-
-void CanvasCaptureHandler::StartVideoCapture(
- const media::VideoCaptureParams& params,
- const media::VideoCapturerSource::VideoCaptureDeliverFrameCB&
- new_frame_callback,
- const media::VideoCapturerSource::RunningCallback& running_callback) {
- DVLOG(3) << __func__ << " requested "
- << media::VideoCaptureFormat::ToString(params.requested_format);
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- DCHECK(params.requested_format.IsValid());
- capture_format_ = params.requested_format;
- delegate_.reset(new CanvasCaptureHandlerDelegate(new_frame_callback));
- DCHECK(delegate_);
- ask_for_new_frame_ = true;
- running_callback.Run(true);
-}
-
-void CanvasCaptureHandler::RequestRefreshFrame() {
- DVLOG(3) << __func__;
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- if (last_frame_ && delegate_) {
- io_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&CanvasCaptureHandler::CanvasCaptureHandlerDelegate::
- SendNewFrameOnIOThread,
- delegate_->GetWeakPtrForIOThread(), last_frame_,
- base::TimeTicks::Now()));
- }
-}
-
-void CanvasCaptureHandler::StopVideoCapture() {
- DVLOG(3) << __func__;
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- ask_for_new_frame_ = false;
- io_task_runner_->DeleteSoon(FROM_HERE, delegate_.release());
-}
-
-void CanvasCaptureHandler::ReadARGBPixelsSync(sk_sp<SkImage> image) {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
-
- const base::TimeTicks timestamp = base::TimeTicks::Now();
- const gfx::Size image_size(image->width(), image->height());
- scoped_refptr<VideoFrame> temp_argb_frame = frame_pool_.CreateFrame(
- media::PIXEL_FORMAT_ARGB, image_size, gfx::Rect(image_size), image_size,
- base::TimeDelta());
- if (!temp_argb_frame) {
- DLOG(ERROR) << "Couldn't allocate video frame";
- return;
- }
- const bool is_opaque = image->isOpaque();
- SkImageInfo image_info = SkImageInfo::MakeN32(
- image_size.width(), image_size.height(),
- is_opaque ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
- if (!image->readPixels(image_info,
- temp_argb_frame->visible_data(VideoFrame::kARGBPlane),
- temp_argb_frame->stride(VideoFrame::kARGBPlane),
- 0 /*srcX*/, 0 /*srcY*/)) {
- DLOG(ERROR) << "Couldn't read SkImage using readPixels()";
- return;
- }
- SendFrame(
- ConvertToYUVFrame(
- is_opaque, false /* flip */,
- temp_argb_frame->visible_data(VideoFrame::kARGBPlane), image_size,
- temp_argb_frame->stride(VideoFrame::kARGBPlane), kN32_SkColorType),
- timestamp, GetImageYUVColorSpace(image));
-}
-
-void CanvasCaptureHandler::ReadARGBPixelsAsync(
- sk_sp<SkImage> image,
- blink::WebGraphicsContext3DProvider* context_provider) {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
-
- const base::TimeTicks timestamp = base::TimeTicks::Now();
- const gfx::Size image_size(image->width(), image->height());
- scoped_refptr<VideoFrame> temp_argb_frame = frame_pool_.CreateFrame(
- media::PIXEL_FORMAT_ARGB, image_size, gfx::Rect(image_size), image_size,
- base::TimeDelta());
- if (!temp_argb_frame) {
- DLOG(ERROR) << "Couldn't allocate video frame";
- return;
- }
- GrSurfaceOrigin surface_origin = kTopLeft_GrSurfaceOrigin;
- GrBackendTexture backend_texture =
- image->getBackendTexture(true, &surface_origin);
- DCHECK(backend_texture.isValid());
- GrGLTextureInfo texture_info;
- const bool result = backend_texture.getGLTextureInfo(&texture_info);
- DCHECK(result);
- DCHECK(context_provider->GetGLHelper());
- context_provider->GetGLHelper()->ReadbackTextureAsync(
- texture_info.fID, image_size,
- temp_argb_frame->visible_data(VideoFrame::kARGBPlane), kN32_SkColorType,
- base::BindOnce(&CanvasCaptureHandler::OnARGBPixelsReadAsync,
- weak_ptr_factory_.GetWeakPtr(), image, temp_argb_frame,
- timestamp, surface_origin != kTopLeft_GrSurfaceOrigin));
-}
-
-void CanvasCaptureHandler::ReadYUVPixelsAsync(
- sk_sp<SkImage> image,
- blink::WebGraphicsContext3DProvider* context_provider) {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
-
- const base::TimeTicks timestamp = base::TimeTicks::Now();
- const gfx::Size image_size(image->width(), image->height());
- scoped_refptr<VideoFrame> output_frame = frame_pool_.CreateFrame(
- media::PIXEL_FORMAT_I420, image_size, gfx::Rect(image_size), image_size,
- base::TimeDelta());
- if (!output_frame) {
- DLOG(ERROR) << "Couldn't allocate video frame";
- return;
- }
-
- GrSurfaceOrigin surface_origin = kTopLeft_GrSurfaceOrigin;
- GrBackendTexture backend_texture =
- image->getBackendTexture(true, &surface_origin);
- DCHECK(backend_texture.isValid());
- GrGLTextureInfo texture_info;
- const bool result = backend_texture.getGLTextureInfo(&texture_info);
- DCHECK(result);
- DCHECK(context_provider->GetGLHelper());
- viz::ReadbackYUVInterface* const yuv_reader =
- context_provider->GetGLHelper()->GetReadbackPipelineYUV(
- surface_origin != kTopLeft_GrSurfaceOrigin);
- yuv_reader->ReadbackYUV(
- texture_info.fID, image_size, gfx::Rect(image_size),
- output_frame->stride(media::VideoFrame::kYPlane),
- output_frame->visible_data(media::VideoFrame::kYPlane),
- output_frame->stride(media::VideoFrame::kUPlane),
- output_frame->visible_data(media::VideoFrame::kUPlane),
- output_frame->stride(media::VideoFrame::kVPlane),
- output_frame->visible_data(media::VideoFrame::kVPlane), gfx::Point(0, 0),
- base::BindOnce(&CanvasCaptureHandler::OnYUVPixelsReadAsync,
- weak_ptr_factory_.GetWeakPtr(), image, output_frame,
- timestamp));
-}
-
-void CanvasCaptureHandler::OnARGBPixelsReadAsync(
- sk_sp<SkImage> image,
- scoped_refptr<media::VideoFrame> temp_argb_frame,
- base::TimeTicks this_frame_ticks,
- bool flip,
- bool success) {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- if (!success) {
- DLOG(ERROR) << "Couldn't read SkImage using async callback";
- // Async reading is not supported on some platforms, see
- // http://crbug.com/788386.
- ReadARGBPixelsSync(image);
- return;
- }
- // Let |image| fall out of scope after we are done reading.
- const bool is_opaque = image->isOpaque();
- const auto color_space = GetImageYUVColorSpace(image);
- image = nullptr;
-
- SendFrame(
- ConvertToYUVFrame(is_opaque, flip,
- temp_argb_frame->visible_data(VideoFrame::kARGBPlane),
- temp_argb_frame->visible_rect().size(),
- temp_argb_frame->stride(VideoFrame::kARGBPlane),
- kN32_SkColorType),
- this_frame_ticks, color_space);
-}
-
-void CanvasCaptureHandler::OnYUVPixelsReadAsync(
- sk_sp<SkImage> image,
- scoped_refptr<media::VideoFrame> yuv_frame,
- base::TimeTicks this_frame_ticks,
- bool success) {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- if (!success) {
- DLOG(ERROR) << "Couldn't read SkImage using async callback";
- return;
- }
- SendFrame(yuv_frame, this_frame_ticks, GetImageYUVColorSpace(image));
-}
-
-scoped_refptr<media::VideoFrame> CanvasCaptureHandler::ConvertToYUVFrame(
- bool is_opaque,
- bool flip,
- const uint8_t* source_ptr,
- const gfx::Size& image_size,
- int stride,
- SkColorType source_color_type) {
- DVLOG(4) << __func__;
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- TRACE_EVENT0("webrtc", "CanvasCaptureHandler::ConvertToYUVFrame");
-
- scoped_refptr<VideoFrame> video_frame = frame_pool_.CreateFrame(
- is_opaque ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_I420A,
- image_size, gfx::Rect(image_size), image_size, base::TimeDelta());
- if (!video_frame) {
- DLOG(ERROR) << "Couldn't allocate video frame";
- return nullptr;
- }
-
- int (*ConvertToI420)(const uint8_t* src_argb, int src_stride_argb,
- uint8_t* dst_y, int dst_stride_y, uint8_t* dst_u,
- int dst_stride_u, uint8_t* dst_v, int dst_stride_v,
- int width, int height) = nullptr;
- switch (source_color_type) {
- case kRGBA_8888_SkColorType:
- ConvertToI420 = libyuv::ABGRToI420;
- break;
- case kBGRA_8888_SkColorType:
- ConvertToI420 = libyuv::ARGBToI420;
- break;
- default:
- NOTIMPLEMENTED() << "Unexpected SkColorType.";
- return nullptr;
- }
-
- if (ConvertToI420(source_ptr, stride,
- video_frame->visible_data(media::VideoFrame::kYPlane),
- video_frame->stride(media::VideoFrame::kYPlane),
- video_frame->visible_data(media::VideoFrame::kUPlane),
- video_frame->stride(media::VideoFrame::kUPlane),
- video_frame->visible_data(media::VideoFrame::kVPlane),
- video_frame->stride(media::VideoFrame::kVPlane),
- image_size.width(),
- (flip ? -1 : 1) * image_size.height()) != 0) {
- DLOG(ERROR) << "Couldn't convert to I420";
- return nullptr;
- }
- if (!is_opaque) {
- // It is ok to use ARGB function because alpha has the same alignment for
- // both ABGR and ARGB.
- libyuv::ARGBExtractAlpha(
- source_ptr, stride, video_frame->visible_data(VideoFrame::kAPlane),
- video_frame->stride(VideoFrame::kAPlane), image_size.width(),
- (flip ? -1 : 1) * image_size.height());
- }
-
- return video_frame;
-}
-
-void CanvasCaptureHandler::SendFrame(scoped_refptr<VideoFrame> video_frame,
- base::TimeTicks this_frame_ticks,
- const gfx::ColorSpace& color_space) {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
-
- // If this function is called asynchronously, |delegate_| might have been
- // released already in StopVideoCapture().
- if (!delegate_ || !video_frame)
- return;
-
- if (!first_frame_ticks_)
- first_frame_ticks_ = this_frame_ticks;
- video_frame->set_timestamp(this_frame_ticks - *first_frame_ticks_);
- if (color_space.IsValid())
- video_frame->set_color_space(color_space);
-
- last_frame_ = video_frame;
- io_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&CanvasCaptureHandler::CanvasCaptureHandlerDelegate::
- SendNewFrameOnIOThread,
- delegate_->GetWeakPtrForIOThread(), std::move(video_frame),
- this_frame_ticks));
-}
-
-void CanvasCaptureHandler::AddVideoCapturerSourceToVideoTrack(
- std::unique_ptr<media::VideoCapturerSource> source,
- blink::WebMediaStreamTrack* web_track) {
- std::string str_track_id;
- base::Base64Encode(base::RandBytesAsString(64), &str_track_id);
- const blink::WebString track_id = blink::WebString::FromASCII(str_track_id);
- media::VideoCaptureFormats preferred_formats = source->GetPreferredFormats();
- blink::MediaStreamVideoSource* media_stream_source =
- new blink::MediaStreamVideoCapturerSource(
- blink::WebPlatformMediaStreamSource::SourceStoppedCallback(),
- std::move(source));
- blink::WebMediaStreamSource webkit_source;
- webkit_source.Initialize(track_id, blink::WebMediaStreamSource::kTypeVideo,
- track_id, false);
- webkit_source.SetPlatformSource(base::WrapUnique(media_stream_source));
- webkit_source.SetCapabilities(ComputeCapabilitiesForVideoSource(
- track_id, preferred_formats,
- media::VideoFacingMode::MEDIA_VIDEO_FACING_NONE,
- false /* is_device_capture */));
-
- web_track->Initialize(webkit_source);
- web_track->SetPlatformTrack(std::make_unique<blink::MediaStreamVideoTrack>(
- media_stream_source, blink::MediaStreamVideoSource::ConstraintsCallback(),
- true));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.h b/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.h
deleted file mode 100644
index 38cec5398d9..00000000000
--- a/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.h
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_CANVAS_CAPTURE_HANDLER_H_
-#define CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_CANVAS_CAPTURE_HANDLER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_checker.h"
-#include "content/common/content_export.h"
-#include "media/base/video_frame_pool.h"
-#include "media/capture/video_capturer_source.h"
-#include "third_party/blink/public/platform/web_canvas_capture_handler.h"
-#include "third_party/blink/public/platform/web_media_stream_track.h"
-#include "third_party/blink/public/platform/web_size.h"
-#include "third_party/skia/include/core/SkImageInfo.h"
-
-class SkImage;
-
-namespace content {
-
-// CanvasCaptureHandler acts as the link between Blink side HTMLCanvasElement
-// and Chrome side VideoCapturerSource. It is responsible for handling
-// SkImage instances sent from the Blink side, convert them to
-// media::VideoFrame and plug them to the MediaStreamTrack.
-// CanvasCaptureHandler instance is owned by a blink::CanvasDrawListener which
-// is owned by a CanvasCaptureMediaStreamTrack.
-// All methods are called on the same thread as construction and destruction,
-// i.e. the Main Render thread. Note that a CanvasCaptureHandlerDelegate is
-// used to send back frames to |io_task_runner_|, i.e. IO thread.
-class CONTENT_EXPORT CanvasCaptureHandler final
- : public blink::WebCanvasCaptureHandler {
- public:
- ~CanvasCaptureHandler() override;
-
- // Creates a CanvasCaptureHandler instance and updates UMA histogram.
- static std::unique_ptr<CanvasCaptureHandler> CreateCanvasCaptureHandler(
- const blink::WebSize& size,
- double frame_rate,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- blink::WebMediaStreamTrack* track);
-
- // blink::WebCanvasCaptureHandler implementation.
- void SendNewFrame(
- sk_sp<SkImage> image,
- blink::WebGraphicsContext3DProvider* context_provider) override;
- bool NeedsNewFrame() const override;
-
- // Functions called by media::VideoCapturerSource implementation.
- void StartVideoCapture(
- const media::VideoCaptureParams& params,
- const media::VideoCapturerSource::VideoCaptureDeliverFrameCB&
- new_frame_callback,
- const media::VideoCapturerSource::RunningCallback& running_callback);
- void RequestRefreshFrame();
- void StopVideoCapture();
-
- private:
- // A VideoCapturerSource instance is created, which is responsible for handing
- // stop&start callbacks back to CanvasCaptureHandler. That VideoCapturerSource
- // is then plugged into a MediaStreamTrack passed as |track|, and it is owned
- // by the Blink side MediaStreamSource.
- CanvasCaptureHandler(
- const blink::WebSize& size,
- double frame_rate,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- blink::WebMediaStreamTrack* track);
-
- // Helper functions to read pixel content.
- void ReadARGBPixelsSync(sk_sp<SkImage> image);
- void ReadARGBPixelsAsync(
- sk_sp<SkImage> image,
- blink::WebGraphicsContext3DProvider* context_provider);
- void ReadYUVPixelsAsync(
- sk_sp<SkImage> image,
- blink::WebGraphicsContext3DProvider* context_provider);
- void OnARGBPixelsReadAsync(sk_sp<SkImage> image,
- scoped_refptr<media::VideoFrame> temp_argb_frame,
- base::TimeTicks this_frame_ticks,
- bool flip,
- bool success);
- void OnYUVPixelsReadAsync(sk_sp<SkImage> image,
- scoped_refptr<media::VideoFrame> yuv_frame,
- base::TimeTicks this_frame_ticks,
- bool success);
-
- scoped_refptr<media::VideoFrame> ConvertToYUVFrame(
- bool is_opaque,
- bool flip,
- const uint8_t* source_ptr,
- const gfx::Size& image_size,
- int stride,
- SkColorType source_color_type);
- void SendFrame(scoped_refptr<media::VideoFrame> video_frame,
- base::TimeTicks this_frame_ticks,
- const gfx::ColorSpace& color_space);
-
- void AddVideoCapturerSourceToVideoTrack(
- std::unique_ptr<media::VideoCapturerSource> source,
- blink::WebMediaStreamTrack* web_track);
-
- // Object that does all the work of running |new_frame_callback_|.
- // Destroyed on |frame_callback_task_runner_| after the class is destroyed.
- class CanvasCaptureHandlerDelegate;
-
- media::VideoCaptureFormat capture_format_;
- bool ask_for_new_frame_;
- media::VideoFramePool frame_pool_;
- base::Optional<base::TimeTicks> first_frame_ticks_;
- scoped_refptr<media::VideoFrame> last_frame_;
-
- const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
- std::unique_ptr<CanvasCaptureHandlerDelegate> delegate_;
-
- // Bound to Main Render thread.
- base::ThreadChecker main_render_thread_checker_;
- base::WeakPtrFactory<CanvasCaptureHandler> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(CanvasCaptureHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_CANVAS_CAPTURE_HANDLER_H_
diff --git a/chromium/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc b/chromium/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc
deleted file mode 100644
index 0952402b41c..00000000000
--- a/chromium/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media_capture_from_element/canvas_capture_handler.h"
-
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/child/child_process.h"
-#include "media/base/limits.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/web_media_stream_source.h"
-#include "third_party/blink/public/platform/web_media_stream_track.h"
-#include "third_party/blink/public/platform/web_size.h"
-#include "third_party/blink/public/web/modules/mediastream/media_stream_video_capturer_source.h"
-#include "third_party/blink/public/web/web_heap.h"
-#include "third_party/skia/include/core/SkImage.h"
-#include "third_party/skia/include/core/SkRefCnt.h"
-
-using ::testing::_;
-using ::testing::InSequence;
-using ::testing::Mock;
-using ::testing::SaveArg;
-using ::testing::Test;
-using ::testing::TestWithParam;
-
-namespace content {
-
-namespace {
-
-static const int kTestCanvasCaptureWidth = 320;
-static const int kTestCanvasCaptureHeight = 240;
-static const double kTestCanvasCaptureFramesPerSecond = 55.5;
-
-static const int kTestCanvasCaptureFrameEvenSize = 2;
-static const int kTestCanvasCaptureFrameOddSize = 3;
-static const int kTestCanvasCaptureFrameColorErrorTolerance = 2;
-static const int kTestAlphaValue = 175;
-
-ACTION_P(RunClosure, closure) {
- closure.Run();
-}
-
-} // namespace
-
-class CanvasCaptureHandlerTest
- : public TestWithParam<testing::tuple<bool, int, int>> {
- public:
- CanvasCaptureHandlerTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
-
- void SetUp() override {
- canvas_capture_handler_ = CanvasCaptureHandler::CreateCanvasCaptureHandler(
- blink::WebSize(kTestCanvasCaptureWidth, kTestCanvasCaptureHeight),
- kTestCanvasCaptureFramesPerSecond,
- blink::scheduler::GetSingleThreadTaskRunnerForTesting(), &track_);
- }
-
- void TearDown() override {
- track_.Reset();
- blink::WebHeap::CollectAllGarbageForTesting();
- canvas_capture_handler_.reset();
-
- // Let the message loop run to finish destroying the capturer.
- base::RunLoop().RunUntilIdle();
- }
-
- // Necessary callbacks and MOCK_METHODS for VideoCapturerSource.
- MOCK_METHOD2(DoOnDeliverFrame,
- void(const scoped_refptr<media::VideoFrame>&, base::TimeTicks));
- void OnDeliverFrame(const scoped_refptr<media::VideoFrame>& video_frame,
- base::TimeTicks estimated_capture_time) {
- DoOnDeliverFrame(video_frame, estimated_capture_time);
- }
-
- MOCK_METHOD1(DoOnRunning, void(bool));
- void OnRunning(bool state) { DoOnRunning(state); }
-
- // Verify returned frames.
- static sk_sp<SkImage> GenerateTestImage(bool opaque, int width, int height) {
- SkImageInfo info = SkImageInfo::MakeN32(
- width, height, opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType,
- SkColorSpace::MakeSRGB());
- SkBitmap testBitmap;
- testBitmap.allocPixels(info);
- testBitmap.eraseARGB(opaque ? 255 : kTestAlphaValue, 30, 60, 200);
- return SkImage::MakeFromBitmap(testBitmap);
- }
-
- void OnVerifyDeliveredFrame(
- bool opaque,
- int expected_width,
- int expected_height,
- const scoped_refptr<media::VideoFrame>& video_frame,
- base::TimeTicks estimated_capture_time) {
- if (opaque)
- EXPECT_EQ(media::PIXEL_FORMAT_I420, video_frame->format());
- else
- EXPECT_EQ(media::PIXEL_FORMAT_I420A, video_frame->format());
-
- const gfx::Size& size = video_frame->visible_rect().size();
- EXPECT_EQ(expected_width, size.width());
- EXPECT_EQ(expected_height, size.height());
- const uint8_t* y_plane =
- video_frame->visible_data(media::VideoFrame::kYPlane);
- EXPECT_NEAR(74, y_plane[0], kTestCanvasCaptureFrameColorErrorTolerance);
- const uint8_t* u_plane =
- video_frame->visible_data(media::VideoFrame::kUPlane);
- EXPECT_NEAR(193, u_plane[0], kTestCanvasCaptureFrameColorErrorTolerance);
- const uint8_t* v_plane =
- video_frame->visible_data(media::VideoFrame::kVPlane);
- EXPECT_NEAR(105, v_plane[0], kTestCanvasCaptureFrameColorErrorTolerance);
- if (!opaque) {
- const uint8_t* a_plane =
- video_frame->visible_data(media::VideoFrame::kAPlane);
- EXPECT_EQ(kTestAlphaValue, a_plane[0]);
- }
- }
-
- blink::WebMediaStreamTrack track_;
- // The Class under test. Needs to be scoped_ptr to force its destruction.
- std::unique_ptr<CanvasCaptureHandler> canvas_capture_handler_;
-
- protected:
- media::VideoCapturerSource* GetVideoCapturerSource(
- blink::MediaStreamVideoCapturerSource* ms_source) {
- return ms_source->GetSourceForTesting();
- }
-
- // A ChildProcess is needed to fool the Tracks and Sources believing they are
- // on the right threads. A ScopedTaskEnvironment must be instantiated before
- // ChildProcess to prevent it from leaking a ThreadPool.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- ChildProcess child_process_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CanvasCaptureHandlerTest);
-};
-
-// Checks that the initialization-destruction sequence works fine.
-TEST_F(CanvasCaptureHandlerTest, ConstructAndDestruct) {
- EXPECT_TRUE(canvas_capture_handler_->NeedsNewFrame());
- base::RunLoop().RunUntilIdle();
-}
-
-// Checks that the destruction sequence works fine.
-TEST_F(CanvasCaptureHandlerTest, DestructTrack) {
- EXPECT_TRUE(canvas_capture_handler_->NeedsNewFrame());
- track_.Reset();
- base::RunLoop().RunUntilIdle();
-}
-
-// Checks that the destruction sequence works fine.
-TEST_F(CanvasCaptureHandlerTest, DestructHandler) {
- EXPECT_TRUE(canvas_capture_handler_->NeedsNewFrame());
- canvas_capture_handler_.reset();
- base::RunLoop().RunUntilIdle();
-}
-
-// Checks that VideoCapturerSource call sequence works fine.
-TEST_P(CanvasCaptureHandlerTest, GetFormatsStartAndStop) {
- InSequence s;
- const blink::WebMediaStreamSource& web_media_stream_source = track_.Source();
- EXPECT_FALSE(web_media_stream_source.IsNull());
- blink::MediaStreamVideoCapturerSource* const ms_source =
- static_cast<blink::MediaStreamVideoCapturerSource*>(
- web_media_stream_source.GetPlatformSource());
- EXPECT_TRUE(ms_source != nullptr);
- media::VideoCapturerSource* source = GetVideoCapturerSource(ms_source);
- EXPECT_TRUE(source != nullptr);
-
- media::VideoCaptureFormats formats = source->GetPreferredFormats();
- ASSERT_EQ(2u, formats.size());
- EXPECT_EQ(kTestCanvasCaptureWidth, formats[0].frame_size.width());
- EXPECT_EQ(kTestCanvasCaptureHeight, formats[0].frame_size.height());
- media::VideoCaptureParams params;
- params.requested_format = formats[0];
-
- base::RunLoop run_loop;
- base::Closure quit_closure = run_loop.QuitClosure();
- EXPECT_CALL(*this, DoOnRunning(true)).Times(1);
- EXPECT_CALL(*this, DoOnDeliverFrame(_, _))
- .Times(1)
- .WillOnce(RunClosure(std::move(quit_closure)));
- source->StartCapture(
- params, base::Bind(&CanvasCaptureHandlerTest::OnDeliverFrame,
- base::Unretained(this)),
- base::Bind(&CanvasCaptureHandlerTest::OnRunning, base::Unretained(this)));
- canvas_capture_handler_->SendNewFrame(
- GenerateTestImage(testing::get<0>(GetParam()),
- testing::get<1>(GetParam()),
- testing::get<2>(GetParam())),
- nullptr);
- run_loop.Run();
-
- source->StopCapture();
-}
-
-// Verifies that SkImage is processed and produces VideoFrame as expected.
-TEST_P(CanvasCaptureHandlerTest, VerifyFrame) {
- const bool opaque_frame = testing::get<0>(GetParam());
- const bool width = testing::get<1>(GetParam());
- const bool height = testing::get<1>(GetParam());
- InSequence s;
- media::VideoCapturerSource* const source = GetVideoCapturerSource(
- static_cast<blink::MediaStreamVideoCapturerSource*>(
- track_.Source().GetPlatformSource()));
- EXPECT_TRUE(source != nullptr);
-
- base::RunLoop run_loop;
- EXPECT_CALL(*this, DoOnRunning(true)).Times(1);
- media::VideoCaptureParams params;
- source->StartCapture(
- params,
- base::Bind(&CanvasCaptureHandlerTest::OnVerifyDeliveredFrame,
- base::Unretained(this), opaque_frame, width, height),
- base::Bind(&CanvasCaptureHandlerTest::OnRunning, base::Unretained(this)));
- canvas_capture_handler_->SendNewFrame(
- GenerateTestImage(opaque_frame, width, height), nullptr);
- run_loop.RunUntilIdle();
-}
-
-// Checks that needsNewFrame() works as expected.
-TEST_F(CanvasCaptureHandlerTest, CheckNeedsNewFrame) {
- InSequence s;
- media::VideoCapturerSource* source = GetVideoCapturerSource(
- static_cast<blink::MediaStreamVideoCapturerSource*>(
- track_.Source().GetPlatformSource()));
- EXPECT_TRUE(source != nullptr);
- EXPECT_TRUE(canvas_capture_handler_->NeedsNewFrame());
- source->StopCapture();
- EXPECT_FALSE(canvas_capture_handler_->NeedsNewFrame());
-}
-
-INSTANTIATE_TEST_SUITE_P(
- ,
- CanvasCaptureHandlerTest,
- ::testing::Combine(::testing::Bool(),
- ::testing::Values(kTestCanvasCaptureFrameEvenSize,
- kTestCanvasCaptureFrameOddSize),
- ::testing::Values(kTestCanvasCaptureFrameEvenSize,
- kTestCanvasCaptureFrameOddSize)));
-
-} // namespace content
diff --git a/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc b/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc
index 8d42c937ed2..1e0686d3ee7 100644
--- a/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc
+++ b/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc
@@ -11,7 +11,6 @@
#include "media/base/audio_parameters.h"
#include "media/base/audio_renderer_sink.h"
#include "media/blink/webaudiosourceprovider_impl.h"
-#include "media/blink/webmediaplayer_impl.h"
#include "third_party/blink/public/platform/web_media_player.h"
namespace content {
@@ -64,7 +63,7 @@ void HtmlAudioElementCapturerSource::SetAudioCallback() {
if (audio_source_ && is_started_) {
// base:Unretained() is safe here since EnsureSourceIsStopped() guarantees
// no more calls to OnAudioBus().
- audio_source_->SetCopyAudioCallback(base::Bind(
+ audio_source_->SetCopyAudioCallback(base::BindRepeating(
&HtmlAudioElementCapturerSource::OnAudioBus, base::Unretained(this)));
}
}
diff --git a/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc b/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc
index 1d0658028f1..7061aa56911 100644
--- a/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc
+++ b/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc
@@ -36,11 +36,6 @@ static const int kAudioTrackSamplesPerBuffer =
kAudioTrackSampleRate * kBufferDurationMs /
base::Time::kMillisecondsPerSecond;
-ACTION_P(RunClosure, closure) {
- closure.Run();
-}
-
-//
class MockMediaStreamAudioSink final : public blink::WebMediaStreamAudioSink {
public:
MockMediaStreamAudioSink() : blink::WebMediaStreamAudioSink() {}
@@ -141,7 +136,7 @@ TEST_F(HTMLAudioElementCapturerSourceTest, CaptureAudio) {
InSequence s;
base::RunLoop run_loop;
- base::Closure quit_closure = run_loop.QuitClosure();
+ base::OnceClosure quit_closure = run_loop.QuitClosure();
MockMediaStreamAudioSink sink;
track()->AddSink(&sink);
@@ -153,7 +148,7 @@ TEST_F(HTMLAudioElementCapturerSourceTest, CaptureAudio) {
kAudioTrackSamplesPerBuffer)),
_))
.Times(1)
- .WillOnce(RunClosure(std::move(quit_closure)));
+ .WillOnce([&](const auto&, auto) { std::move(quit_closure).Run(); });
std::unique_ptr<media::AudioBus> bus = media::AudioBus::Create(
kNumChannelsForTest, kAudioTrackSamplesPerBuffer);
diff --git a/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc b/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
deleted file mode 100644
index 269400018b1..00000000000
--- a/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media_capture_from_element/html_video_element_capturer_source.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/memory/ptr_util.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
-#include "cc/paint/skia_paint_canvas.h"
-#include "content/public/renderer/render_thread.h"
-#include "media/base/limits.h"
-#include "media/blink/webmediaplayer_impl.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/blink/public/platform/modules/mediastream/webrtc_uma_histograms.h"
-#include "third_party/blink/public/platform/web_media_player.h"
-#include "third_party/blink/public/platform/web_rect.h"
-#include "third_party/blink/public/platform/web_size.h"
-#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
-#include "third_party/libyuv/include/libyuv.h"
-
-namespace {
-const float kMinFramesPerSecond = 1.0;
-} // anonymous namespace
-
-namespace content {
-
-//static
-std::unique_ptr<HtmlVideoElementCapturerSource>
-HtmlVideoElementCapturerSource::CreateFromWebMediaPlayerImpl(
- blink::WebMediaPlayer* player,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- // Save histogram data so we can see how much HTML Video capture is used.
- // The histogram counts the number of calls to the JS API.
- UpdateWebRTCMethodCount(blink::WebRTCAPIName::kVideoCaptureStream);
-
- return base::WrapUnique(new HtmlVideoElementCapturerSource(
- static_cast<media::WebMediaPlayerImpl*>(player)->AsWeakPtr(),
- io_task_runner, task_runner));
-}
-
-HtmlVideoElementCapturerSource::HtmlVideoElementCapturerSource(
- const base::WeakPtr<blink::WebMediaPlayer>& player,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : web_media_player_(player),
- io_task_runner_(io_task_runner),
- task_runner_(task_runner),
- is_opaque_(player->IsOpaque()),
- capture_frame_rate_(0.0),
- weak_factory_(this) {
- DCHECK(web_media_player_);
-}
-
-HtmlVideoElementCapturerSource::~HtmlVideoElementCapturerSource() {
- DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-media::VideoCaptureFormats
-HtmlVideoElementCapturerSource::GetPreferredFormats() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // WebMediaPlayer has a setRate() but can't be read back.
- // TODO(mcasas): Add getRate() to WMPlayer and/or fix the spec to allow users
- // to specify it.
- const media::VideoCaptureFormat format(
- web_media_player_->NaturalSize(),
- blink::MediaStreamVideoSource::kDefaultFrameRate,
- media::PIXEL_FORMAT_I420);
- media::VideoCaptureFormats formats;
- formats.push_back(format);
- return formats;
-}
-
-void HtmlVideoElementCapturerSource::StartCapture(
- const media::VideoCaptureParams& params,
- const VideoCaptureDeliverFrameCB& new_frame_callback,
- const RunningCallback& running_callback) {
- DVLOG(2) << __func__ << " requested "
- << media::VideoCaptureFormat::ToString(params.requested_format);
- DCHECK(params.requested_format.IsValid());
- DCHECK(thread_checker_.CalledOnValidThread());
-
- running_callback_ = running_callback;
- if (!web_media_player_ || !web_media_player_->HasVideo()) {
- running_callback_.Run(false);
- return;
- }
-
- new_frame_callback_ = new_frame_callback;
- // Force |capture_frame_rate_| to be in between k{Min,Max}FramesPerSecond.
- capture_frame_rate_ =
- std::max(kMinFramesPerSecond,
- std::min(static_cast<float>(media::limits::kMaxFramesPerSecond),
- params.requested_format.frame_rate));
-
- running_callback_.Run(true);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&HtmlVideoElementCapturerSource::sendNewFrame,
- weak_factory_.GetWeakPtr()));
-}
-
-void HtmlVideoElementCapturerSource::StopCapture() {
- DVLOG(2) << __func__;
- DCHECK(thread_checker_.CalledOnValidThread());
- running_callback_.Reset();
- new_frame_callback_.Reset();
- next_capture_time_ = base::TimeTicks();
-}
-
-void HtmlVideoElementCapturerSource::sendNewFrame() {
- DVLOG(3) << __func__;
- TRACE_EVENT0("media", "HtmlVideoElementCapturerSource::sendNewFrame");
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (!web_media_player_ || new_frame_callback_.is_null())
- return;
-
- const base::TimeTicks current_time = base::TimeTicks::Now();
- if (start_capture_time_.is_null())
- start_capture_time_ = current_time;
- const blink::WebSize resolution = web_media_player_->NaturalSize();
-
- if (!canvas_ || is_opaque_ != web_media_player_->IsOpaque()) {
- LOG(ERROR) << " Change in opacity !!!";
- is_opaque_ = web_media_player_->IsOpaque();
- if (!bitmap_.tryAllocPixels(SkImageInfo::MakeN32(
- resolution.width, resolution.height,
- is_opaque_ ? kOpaque_SkAlphaType : kPremul_SkAlphaType))) {
- running_callback_.Run(false);
- return;
- }
- canvas_ = std::make_unique<cc::SkiaPaintCanvas>(bitmap_);
- }
-
- cc::PaintFlags flags;
- flags.setBlendMode(SkBlendMode::kSrc);
- flags.setFilterQuality(kLow_SkFilterQuality);
- web_media_player_->Paint(
- canvas_.get(), blink::WebRect(0, 0, resolution.width, resolution.height),
- flags);
- DCHECK_NE(kUnknown_SkColorType, canvas_->imageInfo().colorType());
- DCHECK_EQ(canvas_->imageInfo().width(), resolution.width);
- DCHECK_EQ(canvas_->imageInfo().height(), resolution.height);
-
- DCHECK_NE(kUnknown_SkColorType, bitmap_.colorType());
- DCHECK(!bitmap_.drawsNothing());
- DCHECK(bitmap_.getPixels());
- if (bitmap_.colorType() != kN32_SkColorType) {
- DLOG(ERROR) << "Only supported color type is kN32_SkColorType (ARGB/ABGR)";
- return;
- }
-
- scoped_refptr<media::VideoFrame> frame = frame_pool_.CreateFrame(
- is_opaque_ ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_I420A,
- resolution, gfx::Rect(resolution), resolution,
- current_time - start_capture_time_);
-
- const uint32_t source_pixel_format =
- (kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR
- : libyuv::FOURCC_ARGB;
-
- if (frame &&
- libyuv::ConvertToI420(
- static_cast<uint8_t*>(bitmap_.getPixels()), bitmap_.computeByteSize(),
- frame->visible_data(media::VideoFrame::kYPlane),
- frame->stride(media::VideoFrame::kYPlane),
- frame->visible_data(media::VideoFrame::kUPlane),
- frame->stride(media::VideoFrame::kUPlane),
- frame->visible_data(media::VideoFrame::kVPlane),
- frame->stride(media::VideoFrame::kVPlane), 0 /* crop_x */,
- 0 /* crop_y */, frame->visible_rect().size().width(),
- frame->visible_rect().size().height(), bitmap_.info().width(),
- bitmap_.info().height(), libyuv::kRotate0,
- source_pixel_format) == 0) {
- if (!is_opaque_) {
- // OK to use ARGB...() because alpha has the same alignment for both ABGR
- // and ARGB.
- libyuv::ARGBExtractAlpha(static_cast<uint8_t*>(bitmap_.getPixels()),
- bitmap_.rowBytes() /* stride */,
- frame->visible_data(media::VideoFrame::kAPlane),
- frame->stride(media::VideoFrame::kAPlane),
- bitmap_.info().width(), bitmap_.info().height());
- } // Success!
- io_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(new_frame_callback_, frame, current_time));
- }
-
- // Calculate the time in the future where the next frame should be created.
- const base::TimeDelta frame_interval =
- base::TimeDelta::FromMicroseconds(1E6 / capture_frame_rate_);
- if (next_capture_time_.is_null()) {
- next_capture_time_ = current_time + frame_interval;
- } else {
- next_capture_time_ += frame_interval;
- // Don't accumulate any debt if we are lagging behind - just post next frame
- // immediately and continue as normal.
- if (next_capture_time_ < current_time)
- next_capture_time_ = current_time;
- }
- // Schedule next capture.
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&HtmlVideoElementCapturerSource::sendNewFrame,
- weak_factory_.GetWeakPtr()),
- next_capture_time_ - current_time);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source.h b/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source.h
deleted file mode 100644
index 69c0cfd4e93..00000000000
--- a/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source.h
+++ /dev/null
@@ -1,98 +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_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_HTML_VIDEO_ELEMENT_CAPTURER_SOURCE_H_
-#define CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_HTML_VIDEO_ELEMENT_CAPTURER_SOURCE_H_
-
-#include "base/callback.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "base/time/time.h"
-#include "content/common/content_export.h"
-#include "media/base/video_frame_pool.h"
-#include "media/base/video_types.h"
-#include "media/capture/video_capturer_source.h"
-#include "third_party/blink/public/platform/web_size.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkRefCnt.h"
-
-namespace base{
-class SingleThreadTaskRunner;
-}
-
-namespace blink {
-class WebMediaPlayer;
-} // namespace blink
-
-namespace cc {
-class PaintCanvas;
-} // namespace cc
-
-namespace content {
-
-// This class is a VideoCapturerSource taking video snapshots of the ctor-passed
-// blink::WebMediaPlayer on Render Main thread. The captured data is converted
-// and sent back to |io_task_runner_| via the registered |new_frame_callback_|.
-class CONTENT_EXPORT HtmlVideoElementCapturerSource final
- : public media::VideoCapturerSource {
- public:
- static std::unique_ptr<HtmlVideoElementCapturerSource>
- CreateFromWebMediaPlayerImpl(
- blink::WebMediaPlayer* player,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
-
- HtmlVideoElementCapturerSource(
- const base::WeakPtr<blink::WebMediaPlayer>& player,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- ~HtmlVideoElementCapturerSource() override;
-
- // media::VideoCapturerSource Implementation.
- media::VideoCaptureFormats GetPreferredFormats() override;
- void StartCapture(const media::VideoCaptureParams& params,
- const VideoCaptureDeliverFrameCB& new_frame_callback,
- const RunningCallback& running_callback) override;
- void StopCapture() override;
-
- private:
- friend class HTMLVideoElementCapturerSourceTest;
-
- // This method includes collecting data from the WebMediaPlayer and converting
- // it into a format suitable for MediaStreams.
- void sendNewFrame();
-
- media::VideoFramePool frame_pool_;
- SkBitmap bitmap_;
- std::unique_ptr<cc::PaintCanvas> canvas_;
-
- const base::WeakPtr<blink::WebMediaPlayer> web_media_player_;
- const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
- const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- bool is_opaque_;
-
- // These three configuration items are passed on StartCapture();
- RunningCallback running_callback_;
- VideoCaptureDeliverFrameCB new_frame_callback_;
- double capture_frame_rate_;
-
- // TimeTicks on which the first captured VideoFrame is produced.
- base::TimeTicks start_capture_time_;
-
- // Target time for the next frame.
- base::TimeTicks next_capture_time_;
-
- // Bound to the main render thread.
- base::ThreadChecker thread_checker_;
-
- // Used on main render thread to schedule future capture events.
- base::WeakPtrFactory<HtmlVideoElementCapturerSource> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(HtmlVideoElementCapturerSource);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_HTML_VIDEO_ELEMENT_CAPTURER_SOURCE_H_
diff --git a/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc b/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
deleted file mode 100644
index 69e3a4a6073..00000000000
--- a/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
+++ /dev/null
@@ -1,288 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media_capture_from_element/html_video_element_capturer_source.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/memory/weak_ptr.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "cc/paint/paint_canvas.h"
-#include "cc/paint/paint_flags.h"
-#include "media/base/limits.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/web_media_player.h"
-#include "third_party/blink/public/platform/web_rect.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-using ::testing::_;
-using ::testing::InSequence;
-using ::testing::Mock;
-using ::testing::SaveArg;
-
-namespace content {
-
-ACTION_P(RunClosure, closure) {
- closure.Run();
-}
-
-// An almost empty WebMediaPlayer to override paint() method.
-class MockWebMediaPlayer : public blink::WebMediaPlayer,
- public base::SupportsWeakPtr<MockWebMediaPlayer> {
- public:
- MockWebMediaPlayer() = default;
- ~MockWebMediaPlayer() override = default;
-
- LoadTiming Load(LoadType,
- const blink::WebMediaPlayerSource&,
- CorsMode) override {
- return LoadTiming::kImmediate;
- }
- void Play() override {}
- void Pause() override {}
- void Seek(double seconds) override {}
- void SetRate(double) override {}
- void SetVolume(double) override {}
- void OnRequestPictureInPicture() override {}
- blink::WebTimeRanges Buffered() const override {
- return blink::WebTimeRanges();
- }
- blink::WebTimeRanges Seekable() const override {
- return blink::WebTimeRanges();
- }
- void SetSinkId(const blink::WebString& sinkId,
- blink::WebSetSinkIdCompleteCallback) override {}
- bool HasVideo() const override { return true; }
- bool HasAudio() const override { return false; }
- blink::WebSize NaturalSize() const override { return blink::WebSize(16, 10); }
- blink::WebSize VisibleRect() const override { return blink::WebSize(16, 10); }
- bool Paused() const override { return false; }
- bool Seeking() const override { return false; }
- double Duration() const override { return 0.0; }
- double CurrentTime() const override { return 0.0; }
- NetworkState GetNetworkState() const override { return kNetworkStateEmpty; }
- ReadyState GetReadyState() const override { return kReadyStateHaveNothing; }
- SurfaceLayerMode GetVideoSurfaceLayerMode() const override {
- return SurfaceLayerMode::kNever;
- }
- blink::WebString GetErrorMessage() const override {
- return blink::WebString();
- }
-
- bool DidLoadingProgress() override { return true; }
- bool WouldTaintOrigin() const override { return false; }
- double MediaTimeForTimeValue(double timeValue) const override { return 0.0; }
- unsigned DecodedFrameCount() const override { return 0; }
- unsigned DroppedFrameCount() const override { return 0; }
- unsigned CorruptedFrameCount() const override { return 0; }
- uint64_t AudioDecodedByteCount() const override { return 0; }
- uint64_t VideoDecodedByteCount() const override { return 0; }
-
- void Paint(cc::PaintCanvas* canvas,
- const blink::WebRect& rect,
- cc::PaintFlags&,
- int already_uploaded_id,
- VideoFrameUploadMetadata* out_metadata) override {
- // We could fill in |canvas| with a meaningful pattern in ARGB and verify
- // that is correctly captured (as I420) by HTMLVideoElementCapturerSource
- // but I don't think that'll be easy/useful/robust, so just let go here.
- return;
- }
- bool IsOpaque() const override { return is_video_opaque_; }
-
- bool is_video_opaque_ = true;
-};
-
-class HTMLVideoElementCapturerSourceTest : public testing::TestWithParam<bool> {
- public:
- HTMLVideoElementCapturerSourceTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI),
- web_media_player_(new MockWebMediaPlayer()),
- html_video_capturer_(new HtmlVideoElementCapturerSource(
- web_media_player_->AsWeakPtr(),
- blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
- blink::scheduler::GetSingleThreadTaskRunnerForTesting())) {}
-
- // Necessary callbacks and MOCK_METHODS for them.
- MOCK_METHOD2(DoOnDeliverFrame,
- void(const scoped_refptr<media::VideoFrame>&, base::TimeTicks));
- void OnDeliverFrame(const scoped_refptr<media::VideoFrame>& video_frame,
- base::TimeTicks estimated_capture_time) {
- DoOnDeliverFrame(video_frame, estimated_capture_time);
- }
-
- MOCK_METHOD1(DoOnRunning, void(bool));
- void OnRunning(bool state) { DoOnRunning(state); }
-
- void SetVideoPlayerOpacity(bool opacity) {
- web_media_player_->is_video_opaque_ = opacity;
- }
-
- protected:
- // We need some kind of message loop to allow |html_video_capturer_| to
- // schedule capture events.
- const base::test::ScopedTaskEnvironment scoped_task_environment_;
-
- std::unique_ptr<MockWebMediaPlayer> web_media_player_;
- std::unique_ptr<HtmlVideoElementCapturerSource> html_video_capturer_;
-};
-
-// Constructs and destructs all objects, in particular |html_video_capturer_|
-// and its inner object(s). This is a non trivial sequence.
-TEST_F(HTMLVideoElementCapturerSourceTest, ConstructAndDestruct) {}
-
-// Checks that the usual sequence of GetPreferredFormats() ->
-// StartCapture() -> StopCapture() works as expected and let it capture two
-// frames, that are tested for format vs the expected source opacity.
-TEST_P(HTMLVideoElementCapturerSourceTest, GetFormatsAndStartAndStop) {
- InSequence s;
- media::VideoCaptureFormats formats =
- html_video_capturer_->GetPreferredFormats();
- ASSERT_EQ(1u, formats.size());
- EXPECT_EQ(web_media_player_->NaturalSize().width,
- formats[0].frame_size.width());
- EXPECT_EQ(web_media_player_->NaturalSize().height,
- formats[0].frame_size.height());
-
- media::VideoCaptureParams params;
- params.requested_format = formats[0];
-
- EXPECT_CALL(*this, DoOnRunning(true)).Times(1);
-
- const bool is_video_opaque = GetParam();
- SetVideoPlayerOpacity(is_video_opaque);
-
- base::RunLoop run_loop;
- base::Closure quit_closure = run_loop.QuitClosure();
- scoped_refptr<media::VideoFrame> first_frame;
- scoped_refptr<media::VideoFrame> second_frame;
- EXPECT_CALL(*this, DoOnDeliverFrame(_, _)).WillOnce(SaveArg<0>(&first_frame));
- EXPECT_CALL(*this, DoOnDeliverFrame(_, _))
- .Times(1)
- .WillOnce(DoAll(SaveArg<0>(&second_frame),
- RunClosure(std::move(quit_closure))));
-
- html_video_capturer_->StartCapture(
- params, base::Bind(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
- base::Unretained(this)),
- base::Bind(&HTMLVideoElementCapturerSourceTest::OnRunning,
- base::Unretained(this)));
-
- run_loop.Run();
-
- EXPECT_EQ(0u, first_frame->timestamp().InMilliseconds());
- EXPECT_GT(second_frame->timestamp().InMilliseconds(), 30u);
- if (is_video_opaque)
- EXPECT_EQ(media::PIXEL_FORMAT_I420, first_frame->format());
- else
- EXPECT_EQ(media::PIXEL_FORMAT_I420A, first_frame->format());
-
- html_video_capturer_->StopCapture();
- Mock::VerifyAndClearExpectations(this);
-}
-
-INSTANTIATE_TEST_SUITE_P(,
- HTMLVideoElementCapturerSourceTest,
- ::testing::Bool());
-
-// When a new source is created and started, it is stopped in the same task
-// when cross-origin data is detected. This test checks that no data is
-// delivered in this case.
-TEST_F(HTMLVideoElementCapturerSourceTest,
- StartAndStopInSameTaskCaptureZeroFrames) {
- InSequence s;
- media::VideoCaptureFormats formats =
- html_video_capturer_->GetPreferredFormats();
- ASSERT_EQ(1u, formats.size());
- EXPECT_EQ(web_media_player_->NaturalSize().width,
- formats[0].frame_size.width());
- EXPECT_EQ(web_media_player_->NaturalSize().height,
- formats[0].frame_size.height());
-
- media::VideoCaptureParams params;
- params.requested_format = formats[0];
-
- EXPECT_CALL(*this, DoOnRunning(true));
- EXPECT_CALL(*this, DoOnDeliverFrame(_, _)).Times(0);
-
- html_video_capturer_->StartCapture(
- params,
- base::Bind(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
- base::Unretained(this)),
- base::Bind(&HTMLVideoElementCapturerSourceTest::OnRunning,
- base::Unretained(this)));
- html_video_capturer_->StopCapture();
- base::RunLoop().RunUntilIdle();
-
- Mock::VerifyAndClearExpectations(this);
-}
-
-// Verify that changes in the opacicty of the source WebMediaPlayer are followed
-// by corresponding changes in the format of the captured VideoFrame.
-TEST_F(HTMLVideoElementCapturerSourceTest, AlphaAndNot) {
- InSequence s;
- media::VideoCaptureFormats formats =
- html_video_capturer_->GetPreferredFormats();
- media::VideoCaptureParams params;
- params.requested_format = formats[0];
-
- {
- SetVideoPlayerOpacity(false);
-
- base::RunLoop run_loop;
- base::Closure quit_closure = run_loop.QuitClosure();
- scoped_refptr<media::VideoFrame> frame;
- EXPECT_CALL(*this, DoOnRunning(true)).Times(1);
- EXPECT_CALL(*this, DoOnDeliverFrame(_, _))
- .WillOnce(
- DoAll(SaveArg<0>(&frame), RunClosure(std::move(quit_closure))));
- html_video_capturer_->StartCapture(
- params,
- base::Bind(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
- base::Unretained(this)),
- base::Bind(&HTMLVideoElementCapturerSourceTest::OnRunning,
- base::Unretained(this)));
- run_loop.Run();
-
- EXPECT_EQ(media::PIXEL_FORMAT_I420A, frame->format());
- }
- {
- SetVideoPlayerOpacity(true);
-
- base::RunLoop run_loop;
- base::Closure quit_closure = run_loop.QuitClosure();
- scoped_refptr<media::VideoFrame> frame;
- EXPECT_CALL(*this, DoOnDeliverFrame(_, _))
- .WillOnce(
- DoAll(SaveArg<0>(&frame), RunClosure(std::move(quit_closure))));
- run_loop.Run();
-
- EXPECT_EQ(media::PIXEL_FORMAT_I420, frame->format());
- }
- {
- SetVideoPlayerOpacity(false);
-
- base::RunLoop run_loop;
- base::Closure quit_closure = run_loop.QuitClosure();
- scoped_refptr<media::VideoFrame> frame;
- EXPECT_CALL(*this, DoOnDeliverFrame(_, _))
- .WillOnce(
- DoAll(SaveArg<0>(&frame), RunClosure(std::move(quit_closure))));
- run_loop.Run();
-
- EXPECT_EQ(media::PIXEL_FORMAT_I420A, frame->format());
- }
-
- html_video_capturer_->StopCapture();
- Mock::VerifyAndClearExpectations(this);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media_recorder/OWNERS b/chromium/content/renderer/media_recorder/OWNERS
index 75beff3151d..9c893fc1ecb 100644
--- a/chromium/content/renderer/media_recorder/OWNERS
+++ b/chromium/content/renderer/media_recorder/OWNERS
@@ -1,6 +1,7 @@
-emircan@chromium.org
+guidou@chromium.org
# Original (legacy) owner.
+emircan@chromium.org
mcasas@chromium.org
# COMPONENT: Blink>MediaRecording
diff --git a/chromium/content/renderer/media_recorder/media_recorder_handler.cc b/chromium/content/renderer/media_recorder/media_recorder_handler.cc
index 3aecc41199f..31d9b8ab5f4 100644
--- a/chromium/content/renderer/media_recorder/media_recorder_handler.cc
+++ b/chromium/content/renderer/media_recorder/media_recorder_handler.cc
@@ -562,7 +562,7 @@ bool MediaRecorderHandler::UpdateTracksAndCheckIfChanged() {
}
void MediaRecorderHandler::OnVideoFrameForTesting(
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
const TimeTicks& timestamp) {
for (const auto& recorder : video_recorders_)
recorder->OnVideoFrameForTesting(frame, timestamp);
diff --git a/chromium/content/renderer/media_recorder/media_recorder_handler.h b/chromium/content/renderer/media_recorder/media_recorder_handler.h
index f34a4c8504a..c820c0f0539 100644
--- a/chromium/content/renderer/media_recorder/media_recorder_handler.h
+++ b/chromium/content/renderer/media_recorder/media_recorder_handler.h
@@ -87,7 +87,7 @@ class CONTENT_EXPORT MediaRecorderHandler final
// Updates |video_tracks_|,|audio_tracks_| and returns true if any changed.
bool UpdateTracksAndCheckIfChanged();
- void OnVideoFrameForTesting(const scoped_refptr<media::VideoFrame>& frame,
+ void OnVideoFrameForTesting(scoped_refptr<media::VideoFrame> frame,
const base::TimeTicks& timestamp);
void OnAudioBusForTesting(const media::AudioBus& audio_bus,
const base::TimeTicks& timestamp);
diff --git a/chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc b/chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc
index 2caec230535..c5e244b473f 100644
--- a/chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc
+++ b/chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc
@@ -104,8 +104,8 @@ class MediaRecorderHandlerTest : public TestWithParam<MediaRecorderTestParams>,
return !media_recorder_handler_->audio_recorders_.empty();
}
- void OnVideoFrameForTesting(const scoped_refptr<media::VideoFrame>& frame) {
- media_recorder_handler_->OnVideoFrameForTesting(frame,
+ void OnVideoFrameForTesting(scoped_refptr<media::VideoFrame> frame) {
+ media_recorder_handler_->OnVideoFrameForTesting(std::move(frame),
base::TimeTicks::Now());
}
void OnAudioBusForTesting(const media::AudioBus& audio_bus) {
diff --git a/chromium/content/renderer/media_recorder/vea_encoder.cc b/chromium/content/renderer/media_recorder/vea_encoder.cc
index da6e18ea715..18514ca8f9d 100644
--- a/chromium/content/renderer/media_recorder/vea_encoder.cc
+++ b/chromium/content/renderer/media_recorder/vea_encoder.cc
@@ -162,6 +162,7 @@ void VEAEncoder::UseOutputBitstreamBufferId(int32_t bitstream_buffer_id) {
video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
bitstream_buffer_id, output_buffers_[bitstream_buffer_id]->handle(),
+ false /* read_only */,
output_buffers_[bitstream_buffer_id]->mapped_size()));
}
diff --git a/chromium/content/renderer/media_recorder/video_track_recorder.cc b/chromium/content/renderer/media_recorder/video_track_recorder.cc
index 992fb463048..2894e7735ca 100644
--- a/chromium/content/renderer/media_recorder/video_track_recorder.cc
+++ b/chromium/content/renderer/media_recorder/video_track_recorder.cc
@@ -23,7 +23,6 @@
#include "media/base/bind_to_current_loop.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
-#include "media/filters/context_3d.h"
#include "media/renderers/paint_canvas_video_renderer.h"
#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "skia/ext/platform_canvas.h"
@@ -209,7 +208,7 @@ VideoTrackRecorder::Encoder::~Encoder() {
}
void VideoTrackRecorder::Encoder::StartFrameEncode(
- const scoped_refptr<VideoFrame>& video_frame,
+ scoped_refptr<VideoFrame> video_frame,
base::TimeTicks capture_timestamp) {
// Cache the thread sending frames on first frame arrival.
if (!origin_task_runner_.get())
@@ -234,7 +233,7 @@ void VideoTrackRecorder::Encoder::StartFrameEncode(
if (video_frame->HasTextures()) {
main_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&Encoder::RetrieveFrameOnMainThread, this,
- video_frame, capture_timestamp));
+ std::move(video_frame), capture_timestamp));
return;
}
@@ -245,15 +244,14 @@ void VideoTrackRecorder::Encoder::StartFrameEncode(
wrapped_frame = media::WrapAsI420VideoFrame(video_frame);
} else {
wrapped_frame = media::VideoFrame::WrapVideoFrame(
- video_frame, video_frame->format(), video_frame->visible_rect(),
+ *video_frame, video_frame->format(), video_frame->visible_rect(),
video_frame->natural_size());
}
wrapped_frame->AddDestructionObserver(media::BindToCurrentLoop(
base::BindOnce(&VideoTrackRecorder::Counter::DecreaseCount,
num_frames_in_encode_->GetWeakPtr())));
- wrapped_frame->AddDestructionObserver(
- base::BindOnce([](const scoped_refptr<VideoFrame>& video_frame) {},
- std::move(video_frame)));
+ wrapped_frame->AddDestructionObserver(base::BindOnce(
+ [](scoped_refptr<VideoFrame> video_frame) {}, std::move(video_frame)));
num_frames_in_encode_->IncreaseCount();
encoding_task_runner_->PostTask(
@@ -262,7 +260,7 @@ void VideoTrackRecorder::Encoder::StartFrameEncode(
}
void VideoTrackRecorder::Encoder::RetrieveFrameOnMainThread(
- const scoped_refptr<VideoFrame>& video_frame,
+ scoped_refptr<VideoFrame> video_frame,
base::TimeTicks capture_timestamp) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
@@ -311,11 +309,7 @@ void VideoTrackRecorder::Encoder::RetrieveFrameOnMainThread(
if (!video_renderer_)
video_renderer_.reset(new media::PaintCanvasVideoRenderer);
- DCHECK(context_provider->ContextGL());
- video_renderer_->Copy(video_frame.get(), canvas_.get(),
- media::Context3D(context_provider->ContextGL(),
- context_provider->GrContext()),
- context_provider->ContextSupport());
+ video_renderer_->Copy(video_frame.get(), canvas_.get(), context_provider);
SkPixmap pixmap;
if (!bitmap_.peekPixels(&pixmap)) {
@@ -461,7 +455,7 @@ void VideoTrackRecorder::Resume() {
}
void VideoTrackRecorder::OnVideoFrameForTesting(
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
base::TimeTicks timestamp) {
DVLOG(3) << __func__;
@@ -471,7 +465,7 @@ void VideoTrackRecorder::OnVideoFrameForTesting(
timestamp);
}
- encoder_->StartFrameEncode(frame, timestamp);
+ encoder_->StartFrameEncode(std::move(frame), timestamp);
}
void VideoTrackRecorder::InitializeEncoder(
@@ -479,7 +473,7 @@ void VideoTrackRecorder::InitializeEncoder(
const OnEncodedVideoCB& on_encoded_video_callback,
int32_t bits_per_second,
bool allow_vea_encoder,
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
base::TimeTicks capture_time) {
DVLOG(3) << __func__ << frame->visible_rect().size().ToString();
DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
diff --git a/chromium/content/renderer/media_recorder/video_track_recorder.h b/chromium/content/renderer/media_recorder/video_track_recorder.h
index e2ef6e265e1..6e10eb16d9a 100644
--- a/chromium/content/renderer/media_recorder/video_track_recorder.h
+++ b/chromium/content/renderer/media_recorder/video_track_recorder.h
@@ -116,11 +116,10 @@ class CONTENT_EXPORT VideoTrackRecorder : public blink::MediaStreamVideoSink {
// encode the frame. If the |frame|'s data is not directly available (e.g.
// it's a texture) then RetrieveFrameOnMainThread() is called, and if even
// that fails, black frames are sent instead.
- void StartFrameEncode(const scoped_refptr<media::VideoFrame>& frame,
+ void StartFrameEncode(scoped_refptr<media::VideoFrame> frame,
base::TimeTicks capture_timestamp);
- void RetrieveFrameOnMainThread(
- const scoped_refptr<media::VideoFrame>& video_frame,
- base::TimeTicks capture_timestamp);
+ void RetrieveFrameOnMainThread(scoped_refptr<media::VideoFrame> video_frame,
+ base::TimeTicks capture_timestamp);
static void OnFrameEncodeCompleted(
const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_cb,
@@ -151,7 +150,7 @@ class CONTENT_EXPORT VideoTrackRecorder : public blink::MediaStreamVideoSink {
base::TimeTicks capture_timestamp) = 0;
// Called when the frame reference is released after encode.
- void FrameReleased(const scoped_refptr<media::VideoFrame>& frame);
+ void FrameReleased(scoped_refptr<media::VideoFrame> frame);
// Used to shutdown properly on the same thread we were created.
const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
@@ -241,15 +240,16 @@ class CONTENT_EXPORT VideoTrackRecorder : public blink::MediaStreamVideoSink {
void Pause();
void Resume();
- void OnVideoFrameForTesting(const scoped_refptr<media::VideoFrame>& frame,
+ void OnVideoFrameForTesting(scoped_refptr<media::VideoFrame> frame,
base::TimeTicks capture_time);
+
private:
friend class VideoTrackRecorderTest;
void InitializeEncoder(CodecId codec,
const OnEncodedVideoCB& on_encoded_video_callback,
int32_t bits_per_second,
bool allow_vea_encoder,
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
base::TimeTicks capture_time);
void OnError();
@@ -263,7 +263,7 @@ class CONTENT_EXPORT VideoTrackRecorder : public blink::MediaStreamVideoSink {
scoped_refptr<Encoder> encoder_;
base::Callback<void(bool allow_vea_encoder,
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
base::TimeTicks capture_time)>
initialize_encoder_callback_;
diff --git a/chromium/content/renderer/media_recorder/video_track_recorder_unittest.cc b/chromium/content/renderer/media_recorder/video_track_recorder_unittest.cc
index ac3320cb80e..72c83fcf57a 100644
--- a/chromium/content/renderer/media_recorder/video_track_recorder_unittest.cc
+++ b/chromium/content/renderer/media_recorder/video_track_recorder_unittest.cc
@@ -125,11 +125,11 @@ class VideoTrackRecorderTest
is_key_frame);
}
- void Encode(const scoped_refptr<VideoFrame>& frame,
- base::TimeTicks capture_time) {
+ void Encode(scoped_refptr<VideoFrame> frame, base::TimeTicks capture_time) {
EXPECT_TRUE(blink::scheduler::GetSingleThreadTaskRunnerForTesting()
->BelongsToCurrentThread());
- video_track_recorder_->OnVideoFrameForTesting(frame, capture_time);
+ video_track_recorder_->OnVideoFrameForTesting(std::move(frame),
+ capture_time);
}
void OnError() { video_track_recorder_->OnError(); }
@@ -148,7 +148,7 @@ class VideoTrackRecorderTest
// A ChildProcess is needed to fool the Tracks and Sources into believing they
// are on the right threads. A ScopedTaskEnvironment must be instantiated
- // before ChildProcess to prevent it from leaking a ThreadPool.
+ // before ChildProcess to prevent it from leaking a ThreadPoolInstance.
base::test::ScopedTaskEnvironment scoped_task_environment_;
const ChildProcess child_process_;
diff --git a/chromium/content/renderer/media_recorder/vpx_encoder.cc b/chromium/content/renderer/media_recorder/vpx_encoder.cc
index b9be9071642..052d29772b7 100644
--- a/chromium/content/renderer/media_recorder/vpx_encoder.cc
+++ b/chromium/content/renderer/media_recorder/vpx_encoder.cc
@@ -73,7 +73,7 @@ void VpxEncoder::EncodeOnEncodingTaskRunner(scoped_refptr<VideoFrame> frame,
DCHECK(encoding_task_runner_->BelongsToCurrentThread());
const gfx::Size frame_size = frame->visible_rect().size();
- base::TimeDelta duration = EstimateFrameDuration(frame);
+ base::TimeDelta duration = EstimateFrameDuration(*frame);
const media::WebmMuxer::VideoParameters video_params(frame);
if (!IsInitialized(codec_config_) ||
@@ -285,14 +285,13 @@ bool VpxEncoder::IsInitialized(const vpx_codec_enc_cfg_t& codec_config) const {
return codec_config.g_timebase.den != 0;
}
-base::TimeDelta VpxEncoder::EstimateFrameDuration(
- const scoped_refptr<VideoFrame>& frame) {
+base::TimeDelta VpxEncoder::EstimateFrameDuration(const VideoFrame& frame) {
DCHECK(encoding_task_runner_->BelongsToCurrentThread());
using base::TimeDelta;
TimeDelta predicted_frame_duration;
- if (!frame->metadata()->GetTimeDelta(VideoFrameMetadata::FRAME_DURATION,
- &predicted_frame_duration) ||
+ if (!frame.metadata()->GetTimeDelta(VideoFrameMetadata::FRAME_DURATION,
+ &predicted_frame_duration) ||
predicted_frame_duration <= TimeDelta()) {
// The source of the video frame did not provide the frame duration. Use
// the actual amount of time between the current and previous frame as a
@@ -300,9 +299,9 @@ base::TimeDelta VpxEncoder::EstimateFrameDuration(
// TODO(mcasas): This duration estimation could lead to artifacts if the
// cadence of the received stream is compromised (e.g. camera freeze, pause,
// remote packet loss). Investigate using GetFrameRate() in this case.
- predicted_frame_duration = frame->timestamp() - last_frame_timestamp_;
+ predicted_frame_duration = frame.timestamp() - last_frame_timestamp_;
}
- last_frame_timestamp_ = frame->timestamp();
+ last_frame_timestamp_ = frame.timestamp();
// Make sure |predicted_frame_duration| is in a safe range of values.
const TimeDelta kMaxFrameDuration = TimeDelta::FromSecondsD(1.0 / 8);
const TimeDelta kMinFrameDuration = TimeDelta::FromMilliseconds(1);
diff --git a/chromium/content/renderer/media_recorder/vpx_encoder.h b/chromium/content/renderer/media_recorder/vpx_encoder.h
index 888f34b3d5c..8b3445c59ed 100644
--- a/chromium/content/renderer/media_recorder/vpx_encoder.h
+++ b/chromium/content/renderer/media_recorder/vpx_encoder.h
@@ -62,8 +62,7 @@ class VpxEncoder final : public VideoTrackRecorder::Encoder {
bool IsInitialized(const vpx_codec_enc_cfg_t& codec_config) const;
// Estimate the frame duration from |frame| and |last_frame_timestamp_|.
- base::TimeDelta EstimateFrameDuration(
- const scoped_refptr<media::VideoFrame>& frame);
+ base::TimeDelta EstimateFrameDuration(const media::VideoFrame& frame);
// Force usage of VP9 for encoding, instead of VP8 which is the default.
const bool use_vp9_;
diff --git a/chromium/content/renderer/media_stream_utils.cc b/chromium/content/renderer/media_stream_utils.cc
deleted file mode 100644
index 10a94b5ba0e..00000000000
--- a/chromium/content/renderer/media_stream_utils.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/public/renderer/media_stream_utils.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/callback.h"
-#include "base/guid.h"
-#include "media/capture/video_capturer_source.h"
-#include "third_party/blink/public/platform/web_media_stream.h"
-#include "third_party/blink/public/platform/web_media_stream_source.h"
-#include "third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h"
-#include "third_party/blink/public/web/modules/mediastream/media_stream_video_capturer_source.h"
-#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
-#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
-
-namespace content {
-
-bool AddVideoTrackToMediaStream(
- std::unique_ptr<media::VideoCapturerSource> video_source,
- bool is_remote,
- blink::WebMediaStream* web_media_stream) {
- DCHECK(video_source.get());
- if (!web_media_stream || web_media_stream->IsNull()) {
- DLOG(ERROR) << "WebMediaStream is null";
- return false;
- }
-
- media::VideoCaptureFormats preferred_formats =
- video_source->GetPreferredFormats();
- blink::MediaStreamVideoSource* const media_stream_source =
- new blink::MediaStreamVideoCapturerSource(
- blink::WebPlatformMediaStreamSource::SourceStoppedCallback(),
- std::move(video_source));
- const blink::WebString track_id =
- blink::WebString::FromUTF8(base::GenerateGUID());
- blink::WebMediaStreamSource web_media_stream_source;
- web_media_stream_source.Initialize(
- track_id, blink::WebMediaStreamSource::kTypeVideo, track_id, is_remote);
- // Takes ownership of |media_stream_source|.
- web_media_stream_source.SetPlatformSource(
- base::WrapUnique(media_stream_source));
- web_media_stream_source.SetCapabilities(ComputeCapabilitiesForVideoSource(
- track_id, preferred_formats,
- media::VideoFacingMode::MEDIA_VIDEO_FACING_NONE,
- false /* is_device_capture */));
- web_media_stream->AddTrack(blink::MediaStreamVideoTrack::CreateVideoTrack(
- media_stream_source, blink::MediaStreamVideoSource::ConstraintsCallback(),
- true));
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/mus/BUILD.gn b/chromium/content/renderer/mus/BUILD.gn
deleted file mode 100644
index 391e93c5422..00000000000
--- a/chromium/content/renderer/mus/BUILD.gn
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-static_library("mus") {
- # Depend on this only via //content/renderer.
- visibility = [ "//content/renderer/*" ]
-
- sources = [
- "mus_embedded_frame.cc",
- "mus_embedded_frame.h",
- "mus_embedded_frame_delegate.h",
- "render_widget_window_tree_client_factory.cc",
- "render_widget_window_tree_client_factory.h",
- "renderer_window_tree_client.cc",
- "renderer_window_tree_client.h",
- ]
-
- configs += [ "//content:content_implementation" ]
-
- public_deps = [
- "//content/public/common:common_sources",
- ]
-
- deps = [
- "//base",
- "//cc",
- "//cc/mojo_embedder",
- "//components/viz/client",
- "//content/common",
- "//content/public/child:child_sources",
- "//media/mojo/interfaces:remoting",
- "//services/service_manager/public/cpp",
- "//services/ws/public/cpp",
- "//services/ws/public/mojom",
- "//third_party/blink/public:blink",
- "//ui/events:events",
- "//ui/events:events_base",
- "//ui/events/blink",
- "//ui/gfx/geometry/mojo",
- ]
-}
diff --git a/chromium/content/renderer/mus/OWNERS b/chromium/content/renderer/mus/OWNERS
deleted file mode 100644
index fa103a4a859..00000000000
--- a/chromium/content/renderer/mus/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-ben@chromium.org
-sadrul@chromium.org
-fsamuel@chromium.org
-rjkroege@chromium.org
-
-# COMPONENT: Internals>Services>WindowService
diff --git a/chromium/content/renderer/mus/mus_embedded_frame.cc b/chromium/content/renderer/mus/mus_embedded_frame.cc
deleted file mode 100644
index cebc33c41a5..00000000000
--- a/chromium/content/renderer/mus/mus_embedded_frame.cc
+++ /dev/null
@@ -1,123 +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/renderer/mus/mus_embedded_frame.h"
-
-#include <map>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/lazy_instance.h"
-#include "cc/base/switches.h"
-#include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
-#include "components/viz/client/hit_test_data_provider.h"
-#include "components/viz/client/local_surface_id_provider.h"
-#include "content/renderer/mus/renderer_window_tree_client.h"
-#include "services/ws/public/cpp/property_type_converters.h"
-#include "services/ws/public/mojom/window_manager.mojom.h"
-
-namespace content {
-namespace {
-
-// Callback from embedding a child frame.
-void OnEmbedAck(bool success) {
- DCHECK(success);
-}
-
-} // namespace
-
-MusEmbeddedFrame::~MusEmbeddedFrame() {
- renderer_window_tree_client_->OnEmbeddedFrameDestroyed(this);
-
- // If the tree changed the old tree the window was created in was dropped and
- // the server implictly cleaned up. As such, no need to do cleanup here (and
- // we don't have a handle to the right WindowTree at this point).
- if (tree_changed_)
- return;
-
- // If there is |pending_state_| it means we didn't actually create the window
- // yet and there is nothing to do.
- if (pending_state_)
- return;
-
- window_tree()->DeleteWindow(GetAndAdvanceNextChangeId(), window_id_);
-}
-
-void MusEmbeddedFrame::SetWindowBounds(
- const viz::LocalSurfaceIdAllocation& local_surface_id_allocation,
- const gfx::Rect& bounds) {
- if (tree_changed_)
- return;
-
- if (!window_tree()) {
- DCHECK(pending_state_);
- pending_state_->bounds = bounds;
- pending_state_->local_surface_id_allocation = local_surface_id_allocation;
- pending_state_->was_set_window_bounds_called = true;
- return;
- }
-
- window_tree()->SetWindowBounds(GetAndAdvanceNextChangeId(), window_id_,
- bounds, local_surface_id_allocation);
-}
-
-MusEmbeddedFrame::MusEmbeddedFrame(
- RendererWindowTreeClient* renderer_window_tree_client,
- MusEmbeddedFrameDelegate* delegate,
- ws::ClientSpecificId window_id,
- const base::UnguessableToken& token)
- : renderer_window_tree_client_(renderer_window_tree_client),
- delegate_(delegate),
- window_id_(window_id) {
- if (!window_tree()) {
- pending_state_ = std::make_unique<PendingState>();
- pending_state_->token = token;
- return;
- }
- CreateChildWindowAndEmbed(token);
-}
-
-void MusEmbeddedFrame::CreateChildWindowAndEmbed(
- const base::UnguessableToken& token) {
- // Set a name for debugging.
- base::flat_map<std::string, std::vector<uint8_t>> properties;
- properties[ws::mojom::WindowManager::kName_Property] =
- mojo::ConvertTo<std::vector<uint8_t>>(std::string("RendererFrame"));
- window_tree()->NewWindow(GetAndAdvanceNextChangeId(), window_id_, properties);
- window_tree()->AddWindow(GetAndAdvanceNextChangeId(),
- renderer_window_tree_client_->root_window_id_,
- window_id_);
- window_tree()->EmbedUsingToken(window_id_, token, 0,
- base::BindOnce(&OnEmbedAck));
-}
-
-void MusEmbeddedFrame::OnTreeAvailable() {
- // See header for description, always called before OnTreeWillChange().
- DCHECK(!tree_changed_);
- std::unique_ptr<PendingState> pending_state = std::move(pending_state_);
- CreateChildWindowAndEmbed(pending_state->token);
- if (pending_state->was_set_window_bounds_called)
- SetWindowBounds(pending_state->local_surface_id_allocation,
- pending_state->bounds);
-}
-
-void MusEmbeddedFrame::OnTreeWillChange() {
- tree_changed_ = true;
-}
-
-uint32_t MusEmbeddedFrame::GetAndAdvanceNextChangeId() {
- return renderer_window_tree_client_->GetAndAdvanceNextChangeId();
-}
-
-ws::mojom::WindowTree* MusEmbeddedFrame::window_tree() {
- // Once |tree_changed_| is true the WindowTree this instance used has changed
- // and it no longer makes sense to use it (the original window was deleted).
- return tree_changed_ ? nullptr : renderer_window_tree_client_->tree_.get();
-}
-
-MusEmbeddedFrame::PendingState::PendingState() = default;
-
-MusEmbeddedFrame::PendingState::~PendingState() = default;
-
-} // namespace content
diff --git a/chromium/content/renderer/mus/mus_embedded_frame.h b/chromium/content/renderer/mus/mus_embedded_frame.h
deleted file mode 100644
index 83634709f4b..00000000000
--- a/chromium/content/renderer/mus/mus_embedded_frame.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_RENDERER_MUS_MUS_EMBEDDED_FRAME_H_
-#define CONTENT_RENDERER_MUS_MUS_EMBEDDED_FRAME_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/unguessable_token.h"
-#include "components/viz/common/surfaces/local_surface_id_allocation.h"
-#include "services/ws/common/types.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace ws {
-namespace mojom {
-class WindowTree;
-}
-} // namespace ui
-
-namespace content {
-
-class MusEmbeddedFrameDelegate;
-class RendererWindowTreeClient;
-
-// MusEmbeddedFrame represents an embedding of an OOPIF frame. Internally this
-// creates a window in the window server and calls Embed().
-class MusEmbeddedFrame {
- public:
- ~MusEmbeddedFrame();
-
- // Sets the bounds (in pixels) of the embedded frame.
- void SetWindowBounds(
- const viz::LocalSurfaceIdAllocation& local_surface_id_allocation,
- const gfx::Rect& bounds);
-
- private:
- friend class RendererWindowTreeClient;
-
- // Stores state that needs to pushed to the server once the connection has
- // been established (OnEmbed() is called).
- struct PendingState {
- PendingState();
- ~PendingState();
-
- base::UnguessableToken token;
- viz::LocalSurfaceIdAllocation local_surface_id_allocation;
- gfx::Rect bounds;
- // True if SetWindowBounds() was called.
- bool was_set_window_bounds_called = false;
- };
-
- MusEmbeddedFrame(RendererWindowTreeClient* renderer_window_tree_client,
- MusEmbeddedFrameDelegate* delegate,
- ws::ClientSpecificId window_id,
- const base::UnguessableToken& token);
-
- // Called once the WindowTree has been obtained. This is only called if
- // the MusEmbeddedFrame is created before the WindowTree has been obtained.
- void OnTreeAvailable();
-
- // Called when the WindowTree held by |renderer_window_tree_client_| is about
- // to change. This means the renderer was reembeded.
- void OnTreeWillChange();
-
- // Does the actual embedding.
- void CreateChildWindowAndEmbed(const base::UnguessableToken& token);
-
- uint32_t GetAndAdvanceNextChangeId();
-
- ws::mojom::WindowTree* window_tree();
-
- RendererWindowTreeClient* renderer_window_tree_client_;
- MusEmbeddedFrameDelegate* delegate_;
- const ws::ClientSpecificId window_id_;
-
- std::unique_ptr<PendingState> pending_state_;
-
- // If set, the WindowTree that state was created on has changed.
- bool tree_changed_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(MusEmbeddedFrame);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MUS_MUS_EMBEDDED_FRAME_H_
diff --git a/chromium/content/renderer/mus/mus_embedded_frame_delegate.h b/chromium/content/renderer/mus/mus_embedded_frame_delegate.h
deleted file mode 100644
index cd61b383ce9..00000000000
--- a/chromium/content/renderer/mus/mus_embedded_frame_delegate.h
+++ /dev/null
@@ -1,26 +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_RENDERER_MUS_MUS_EMBEDDED_FRAME_DELEGATE_H_
-#define CONTENT_RENDERER_MUS_MUS_EMBEDDED_FRAME_DELEGATE_H_
-
-namespace viz {
-class FrameSinkId;
-} // namespace viz
-
-namespace content {
-
-class MusEmbeddedFrameDelegate {
- public:
- // Called when mus determines the FrameSinkId.
- virtual void OnMusEmbeddedFrameSinkIdAllocated(
- const viz::FrameSinkId& frame_sink_id) = 0;
-
- protected:
- virtual ~MusEmbeddedFrameDelegate() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MUS_MUS_EMBEDDED_FRAME_DELEGATE_H_
diff --git a/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc b/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc
deleted file mode 100644
index e06cadbc040..00000000000
--- a/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/mus/render_widget_window_tree_client_factory.h"
-
-#include <stdint.h>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/common/render_widget_window_tree_client_factory.mojom.h"
-#include "content/public/common/connection_filter.h"
-#include "content/public/common/service_manager_connection.h"
-#include "content/renderer/mus/renderer_window_tree_client.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/ws/public/mojom/window_tree.mojom.h"
-#include "url/gurl.h"
-
-namespace content {
-
-namespace {
-
-void BindMusConnectionOnMainThread(
- uint32_t routing_id,
- ws::mojom::WindowTreeClientRequest request,
- mojom::RenderWidgetWindowTreeClientRequest
- render_widget_window_tree_client_request) {
- RendererWindowTreeClient::CreateIfNecessary(routing_id);
- RendererWindowTreeClient::Get(routing_id)
- ->Bind(std::move(request),
- std::move(render_widget_window_tree_client_request));
-}
-
-// This object's lifetime is managed by ServiceManagerConnection because it's a
-// registered with it.
-class RenderWidgetWindowTreeClientFactoryImpl
- : public ConnectionFilter,
- public mojom::RenderWidgetWindowTreeClientFactory {
- public:
- RenderWidgetWindowTreeClientFactoryImpl() {
- main_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
- }
-
- ~RenderWidgetWindowTreeClientFactoryImpl() override {}
-
- private:
- // ConnectionFilter implementation:
- void OnBindInterface(const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle* interface_pipe,
- service_manager::Connector* connector) override {
- if (interface_name == mojom::RenderWidgetWindowTreeClientFactory::Name_) {
- bindings_.AddBinding(this,
- mojom::RenderWidgetWindowTreeClientFactoryRequest(
- std::move(*interface_pipe)));
- }
- }
-
- // mojom::RenderWidgetWindowTreeClientFactory implementation.
- void CreateWindowTreeClientForRenderWidget(
- uint32_t routing_id,
- ws::mojom::WindowTreeClientRequest request,
- mojom::RenderWidgetWindowTreeClientRequest
- render_widget_window_tree_client_request) override {
- main_thread_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&BindMusConnectionOnMainThread, routing_id,
- std::move(request),
- std::move(render_widget_window_tree_client_request)));
- }
-
- scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_;
- mojo::BindingSet<mojom::RenderWidgetWindowTreeClientFactory> bindings_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderWidgetWindowTreeClientFactoryImpl);
-};
-
-} // namespace
-
-void CreateRenderWidgetWindowTreeClientFactory(
- ServiceManagerConnection* connection) {
- connection->AddConnectionFilter(
- std::make_unique<RenderWidgetWindowTreeClientFactoryImpl>());
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/mus/render_widget_window_tree_client_factory.h b/chromium/content/renderer/mus/render_widget_window_tree_client_factory.h
deleted file mode 100644
index 40f20b38754..00000000000
--- a/chromium/content/renderer/mus/render_widget_window_tree_client_factory.h
+++ /dev/null
@@ -1,17 +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_RENDERER_MUS_RENDER_WIDGET_WINDOW_TREE_CLIENT_FACTORY_H_
-#define CONTENT_RENDERER_MUS_RENDER_WIDGET_WINDOW_TREE_CLIENT_FACTORY_H_
-
-namespace content {
-
-class ServiceManagerConnection;
-
-void CreateRenderWidgetWindowTreeClientFactory(
- ServiceManagerConnection* connection);
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MUS_RENDER_WIDGET_WINDOW_TREE_CLIENT_FACTORY_H_
diff --git a/chromium/content/renderer/mus/renderer_window_tree_client.cc b/chromium/content/renderer/mus/renderer_window_tree_client.cc
deleted file mode 100644
index 384141abf0e..00000000000
--- a/chromium/content/renderer/mus/renderer_window_tree_client.cc
+++ /dev/null
@@ -1,392 +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/renderer/mus/renderer_window_tree_client.h"
-
-#include <map>
-
-#include "base/bind_helpers.h"
-#include "base/command_line.h"
-#include "base/lazy_instance.h"
-#include "cc/base/switches.h"
-#include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
-#include "components/viz/client/hit_test_data_provider.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/features.h"
-#include "content/renderer/mus/mus_embedded_frame.h"
-#include "content/renderer/mus/mus_embedded_frame_delegate.h"
-#include "content/renderer/render_frame_proxy.h"
-#include "services/ws/public/mojom/window_tree_constants.mojom.h"
-#include "ui/base/ui_base_features.h"
-
-namespace content {
-
-namespace {
-
-using ConnectionMap = std::map<int, RendererWindowTreeClient*>;
-base::LazyInstance<ConnectionMap>::Leaky g_connections =
- LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-// static
-void RendererWindowTreeClient::CreateIfNecessary(int routing_id) {
- if (!features::IsMultiProcessMash() || Get(routing_id))
- return;
- RendererWindowTreeClient* connection =
- new RendererWindowTreeClient(routing_id);
- g_connections.Get().insert(std::make_pair(routing_id, connection));
-}
-
-// static
-void RendererWindowTreeClient::Destroy(int routing_id) {
- delete Get(routing_id);
-}
-
-// static
-RendererWindowTreeClient* RendererWindowTreeClient::Get(int routing_id) {
- auto it = g_connections.Get().find(routing_id);
- if (it != g_connections.Get().end())
- return it->second;
- return nullptr;
-}
-
-void RendererWindowTreeClient::Bind(
- ws::mojom::WindowTreeClientRequest request,
- mojom::RenderWidgetWindowTreeClientRequest
- render_widget_window_tree_client_request) {
- // Bind() may be called multiple times.
- binding_.Close();
- render_widget_window_tree_client_binding_.Close();
-
- binding_.Bind(std::move(request));
- render_widget_window_tree_client_binding_.Bind(
- std::move(render_widget_window_tree_client_request));
-}
-
-std::unique_ptr<MusEmbeddedFrame>
-RendererWindowTreeClient::OnRenderFrameProxyCreated(
- RenderFrameProxy* render_frame_proxy) {
- auto iter = pending_frames_.find(render_frame_proxy->routing_id());
- if (iter == pending_frames_.end())
- return nullptr;
-
- const base::UnguessableToken token = iter->second;
- pending_frames_.erase(iter);
- return CreateMusEmbeddedFrame(render_frame_proxy, token);
-}
-
-void RendererWindowTreeClient::SetVisible(bool visible) {
- if (visible_ == visible)
- return;
-
- visible_ = visible;
- if (tree_) {
- tree_->SetWindowVisibility(GetAndAdvanceNextChangeId(), root_window_id_,
- visible);
- }
-}
-
-void RendererWindowTreeClient::RequestLayerTreeFrameSink(
- scoped_refptr<viz::ContextProvider> context_provider,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- LayerTreeFrameSinkCallback callback) {
- DCHECK(pending_layer_tree_frame_sink_callback_.is_null());
- if (tree_) {
- RequestLayerTreeFrameSinkInternal(std::move(context_provider),
- gpu_memory_buffer_manager,
- std::move(callback));
- return;
- }
-
- pending_context_provider_ = std::move(context_provider);
- pending_gpu_memory_buffer_manager_ = gpu_memory_buffer_manager;
- pending_layer_tree_frame_sink_callback_ = std::move(callback);
-}
-
-std::unique_ptr<MusEmbeddedFrame>
-RendererWindowTreeClient::CreateMusEmbeddedFrame(
- MusEmbeddedFrameDelegate* delegate,
- const base::UnguessableToken& token) {
- std::unique_ptr<MusEmbeddedFrame> frame = base::WrapUnique<MusEmbeddedFrame>(
- new MusEmbeddedFrame(this, delegate, ++next_window_id_, token));
- embedded_frames_.insert(frame.get());
- return frame;
-}
-
-RendererWindowTreeClient::RendererWindowTreeClient(int routing_id)
- : routing_id_(routing_id),
- binding_(this),
- render_widget_window_tree_client_binding_(this) {}
-
-RendererWindowTreeClient::~RendererWindowTreeClient() {
- g_connections.Get().erase(routing_id_);
- DCHECK(embedded_frames_.empty());
-}
-
-void RendererWindowTreeClient::RequestLayerTreeFrameSinkInternal(
- scoped_refptr<viz::ContextProvider> context_provider,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- LayerTreeFrameSinkCallback callback) {
- viz::mojom::CompositorFrameSinkPtrInfo sink_info;
- viz::mojom::CompositorFrameSinkRequest sink_request =
- mojo::MakeRequest(&sink_info);
- viz::mojom::CompositorFrameSinkClientPtr client;
- viz::mojom::CompositorFrameSinkClientRequest client_request =
- mojo::MakeRequest(&client);
- cc::mojo_embedder::AsyncLayerTreeFrameSink::InitParams params;
- params.gpu_memory_buffer_manager = gpu_memory_buffer_manager;
- params.pipes.compositor_frame_sink_info = std::move(sink_info);
- params.pipes.client_request = std::move(client_request);
- params.enable_surface_synchronization = true;
- if (features::IsVizHitTestingDrawQuadEnabled()) {
- params.hit_test_data_provider =
- std::make_unique<viz::HitTestDataProviderDrawQuad>(
- true /* should_ask_for_child_region */,
- true /* root_accepts_events */);
- }
- auto frame_sink =
- std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>(
- std::move(context_provider), nullptr /* worker_context_provider */,
- &params);
- tree_->AttachCompositorFrameSink(root_window_id_, std::move(sink_request),
- std::move(client));
- std::move(callback).Run(std::move(frame_sink));
-}
-
-void RendererWindowTreeClient::OnEmbeddedFrameDestroyed(
- MusEmbeddedFrame* frame) {
- embedded_frames_.erase(embedded_frames_.find(frame));
-}
-
-void RendererWindowTreeClient::Embed(uint32_t frame_routing_id,
- const base::UnguessableToken& token) {
- RenderFrameProxy* render_frame_proxy =
- RenderFrameProxy::FromRoutingID(frame_routing_id);
- if (!render_frame_proxy) {
- pending_frames_[frame_routing_id] = token;
- return;
- }
- render_frame_proxy->SetMusEmbeddedFrame(
- CreateMusEmbeddedFrame(render_frame_proxy, token));
-}
-
-void RendererWindowTreeClient::OnEmbedFromToken(
- const base::UnguessableToken& token,
- ws::mojom::WindowDataPtr root,
- int64_t display_id,
- const base::Optional<viz::LocalSurfaceIdAllocation>&
- local_surface_id_allocation) {
- // Renderers don't use ScheduleEmbedForExistingClient(), so this path should
- // never be hit.
- NOTREACHED();
-}
-
-void RendererWindowTreeClient::DestroyFrame(uint32_t frame_routing_id) {
- pending_frames_.erase(frame_routing_id);
-}
-
-void RendererWindowTreeClient::OnClientId(uint32_t client_id) {}
-
-void RendererWindowTreeClient::OnEmbed(
- ws::mojom::WindowDataPtr root,
- ws::mojom::WindowTreePtr tree,
- int64_t display_id,
- ws::Id focused_window_id,
- bool drawn,
- const base::Optional<viz::LocalSurfaceIdAllocation>&
- local_surface_id_allocation) {
- const bool is_reembed = tree_.is_bound();
- if (is_reembed) {
- for (MusEmbeddedFrame* frame : embedded_frames_)
- frame->OnTreeWillChange();
- }
- root_window_id_ = root->window_id;
-
- tree_ = std::move(tree);
- tree_->SetWindowVisibility(GetAndAdvanceNextChangeId(), root_window_id_,
- visible_);
- if (!is_reembed) {
- for (MusEmbeddedFrame* frame : embedded_frames_)
- frame->OnTreeAvailable();
- }
-
- if (!pending_layer_tree_frame_sink_callback_.is_null()) {
- RequestLayerTreeFrameSinkInternal(
- std::move(pending_context_provider_),
- pending_gpu_memory_buffer_manager_,
- std::move(pending_layer_tree_frame_sink_callback_));
- pending_context_provider_ = nullptr;
- pending_gpu_memory_buffer_manager_ = nullptr;
- pending_layer_tree_frame_sink_callback_.Reset();
- }
-}
-
-void RendererWindowTreeClient::OnEmbeddedAppDisconnected(ws::Id window_id) {
- // TODO(sad): Embedded mus-client (oopif) is gone. Figure out what to do.
-}
-
-void RendererWindowTreeClient::OnUnembed(ws::Id window_id) {
- // At this point all operations will fail. We don't delete this as it would
- // mean all consumers have to null check (as would MusEmbeddedFrames).
-}
-
-void RendererWindowTreeClient::OnCaptureChanged(ws::Id new_capture_window_id,
- ws::Id old_capture_window_id) {}
-
-void RendererWindowTreeClient::OnFrameSinkIdAllocated(
- ws::Id window_id,
- const viz::FrameSinkId& frame_sink_id) {
- // When mus is not hosting viz FrameSinkIds come from the browser, so we
- // ignore them here.
- if (!features::IsMultiProcessMash())
- return;
-
- for (MusEmbeddedFrame* embedded_frame : embedded_frames_) {
- if (embedded_frame->window_id_ == window_id) {
- embedded_frame->delegate_->OnMusEmbeddedFrameSinkIdAllocated(
- frame_sink_id);
- return;
- }
- }
-}
-
-void RendererWindowTreeClient::OnTopLevelCreated(
- uint32_t change_id,
- ws::mojom::WindowDataPtr data,
- int64_t display_id,
- bool drawn,
- const viz::LocalSurfaceIdAllocation& local_surface_id_allocation) {
- NOTREACHED();
-}
-
-void RendererWindowTreeClient::OnWindowBoundsChanged(
- ws::Id window_id,
- const gfx::Rect& new_bounds,
- ui::WindowShowState state,
- const base::Optional<viz::LocalSurfaceIdAllocation>&
- local_surface_id_allocation) {}
-
-void RendererWindowTreeClient::OnWindowTransformChanged(
- ws::Id window_id,
- const gfx::Transform& new_transform) {}
-
-void RendererWindowTreeClient::OnTransientWindowAdded(
- ws::Id window_id,
- ws::Id transient_window_id) {}
-
-void RendererWindowTreeClient::OnTransientWindowRemoved(
- ws::Id window_id,
- ws::Id transient_window_id) {}
-
-void RendererWindowTreeClient::OnWindowHierarchyChanged(
- ws::Id window_id,
- ws::Id old_parent_id,
- ws::Id new_parent_id,
- std::vector<ws::mojom::WindowDataPtr> windows) {}
-
-void RendererWindowTreeClient::OnWindowReordered(
- ws::Id window_id,
- ws::Id relative_window_id,
- ws::mojom::OrderDirection direction) {}
-
-void RendererWindowTreeClient::OnWindowDeleted(ws::Id window_id) {
- // See comments on OnUnembed() for why we do nothing here.
-}
-
-void RendererWindowTreeClient::OnWindowVisibilityChanged(ws::Id window_id,
- bool visible) {}
-
-void RendererWindowTreeClient::OnWindowDisplayChanged(ws::Id window_id,
- int64_t display_id) {}
-
-void RendererWindowTreeClient::OnWindowParentDrawnStateChanged(ws::Id window_id,
- bool drawn) {}
-
-void RendererWindowTreeClient::OnWindowSharedPropertyChanged(
- ws::Id window_id,
- const std::string& name,
- const base::Optional<std::vector<uint8_t>>& new_data) {}
-
-void RendererWindowTreeClient::OnWindowInputEvent(
- uint32_t event_id,
- ws::Id window_id,
- int64_t display_id,
- std::unique_ptr<ui::Event> event,
- bool matches_event_observer) {
- NOTREACHED();
-}
-
-void RendererWindowTreeClient::OnObservedInputEvent(
- std::unique_ptr<ui::Event> event) {
- NOTREACHED();
-}
-
-void RendererWindowTreeClient::OnWindowFocused(ws::Id focused_window_id) {}
-
-void RendererWindowTreeClient::OnWindowCursorChanged(ws::Id window_id,
- ui::Cursor cursor) {}
-
-void RendererWindowTreeClient::OnDragDropStart(
- const base::flat_map<std::string, std::vector<uint8_t>>& mime_data) {}
-
-void RendererWindowTreeClient::OnDragEnter(ws::Id window_id,
- uint32_t event_flags,
- const gfx::PointF& location_in_root,
- const gfx::PointF& location,
- uint32_t effect_bitmask,
- OnDragEnterCallback callback) {}
-
-void RendererWindowTreeClient::OnDragOver(ws::Id window_id,
- uint32_t event_flags,
- const gfx::PointF& location_in_root,
- const gfx::PointF& location,
- uint32_t effect_bitmask,
- OnDragOverCallback callback) {}
-
-void RendererWindowTreeClient::OnDragLeave(ws::Id window_id) {}
-
-void RendererWindowTreeClient::OnCompleteDrop(
- ws::Id window_id,
- uint32_t event_flags,
- const gfx::PointF& location_in_root,
- const gfx::PointF& location,
- uint32_t effect_bitmask,
- OnCompleteDropCallback callback) {}
-
-void RendererWindowTreeClient::OnPerformDragDropCompleted(
- uint32_t change_id,
- bool success,
- uint32_t action_taken) {}
-
-void RendererWindowTreeClient::OnDragDropDone() {}
-
-void RendererWindowTreeClient::OnTopmostWindowChanged(
- const std::vector<ws::Id>& topmost_ids) {}
-
-void RendererWindowTreeClient::OnChangeCompleted(uint32_t change_id,
- bool success) {
- // Don't DCHECK success, as it's possible we'll try to do some operations
- // after unembedded, which means all operations will fail. Additionally
- // setting the window visibility may fail for the root frame (the browser
- // controls the visibility of the root frame).
-}
-
-void RendererWindowTreeClient::RequestClose(ws::Id window_id) {}
-
-void RendererWindowTreeClient::GetScreenProviderObserver(
- ws::mojom::ScreenProviderObserverAssociatedRequest observer) {}
-
-void RendererWindowTreeClient::OnOcclusionStatesChanged(
- const base::flat_map<ws::Id, ws::mojom::OcclusionState>&
- occlusion_changes) {}
-
-void RendererWindowTreeClient::CleanupGestureState(ws::Id window_id) {}
-
-void RendererWindowTreeClient::OnWindowResizeLoopStarted(ws::Id window_id) {}
-
-void RendererWindowTreeClient::OnWindowResizeLoopEnded(ws::Id window_id) {}
-
-} // namespace content
diff --git a/chromium/content/renderer/mus/renderer_window_tree_client.h b/chromium/content/renderer/mus/renderer_window_tree_client.h
deleted file mode 100644
index 723e7fecfe7..00000000000
--- a/chromium/content/renderer/mus/renderer_window_tree_client.h
+++ /dev/null
@@ -1,239 +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_RENDERER_MUS_RENDERER_WINDOW_TREE_CLIENT_H_
-#define CONTENT_RENDERER_MUS_RENDERER_WINDOW_TREE_CLIENT_H_
-
-#include <map>
-#include <memory>
-
-#include "base/containers/flat_set.h"
-#include "base/macros.h"
-#include "base/unguessable_token.h"
-#include "components/viz/common/surfaces/local_surface_id.h"
-#include "content/common/render_widget_window_tree_client_factory.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/ws/common/types.h"
-#include "services/ws/public/mojom/window_tree.mojom.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace base {
-class UnguessableToken;
-}
-
-namespace cc {
-class LayerTreeFrameSink;
-}
-
-namespace gpu {
-class GpuMemoryBufferManager;
-}
-
-namespace viz {
-class ContextProvider;
-}
-
-namespace content {
-
-class MusEmbeddedFrame;
-class MusEmbeddedFrameDelegate;
-class RenderFrameProxy;
-
-// ws::mojom::WindowTreeClient implementation for RenderWidget. This lives and
-// operates on the renderer's main thread.
-class RendererWindowTreeClient : public ws::mojom::WindowTreeClient,
- public mojom::RenderWidgetWindowTreeClient {
- public:
- // Creates a RendererWindowTreeClient instance for the RenderWidget instance
- // associated with |routing_id| (if one doesn't already exist). The instance
- // self-destructs when the connection to mus is lost, or when the window is
- // closed.
- static void CreateIfNecessary(int routing_id);
-
- // Destroys the client instance, if one exists. Otherwise, does nothing.
- static void Destroy(int routing_id);
-
- // Returns the RendererWindowTreeClient associated with |routing_id|. Returns
- // nullptr if none exists.
- // TODO(sky): make RenderWidget own RendererWindowTreeClient.
- static RendererWindowTreeClient* Get(int routing_id);
-
- void Bind(ws::mojom::WindowTreeClientRequest request,
- mojom::RenderWidgetWindowTreeClientRequest
- render_widget_window_tree_client_request);
-
- // Called when a new RenderFrameProxy has been created. If there is a pending
- // embedding ready, it's returned.
- std::unique_ptr<MusEmbeddedFrame> OnRenderFrameProxyCreated(
- RenderFrameProxy* render_frame_proxy);
-
- // Sets the visibility of the client.
- void SetVisible(bool visible);
-
- using LayerTreeFrameSinkCallback =
- base::OnceCallback<void(std::unique_ptr<cc::LayerTreeFrameSink>)>;
- void RequestLayerTreeFrameSink(
- scoped_refptr<viz::ContextProvider> context_provider,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- LayerTreeFrameSinkCallback callback);
-
- // Creates a new MusEmbeddedFrame. |token| is an UnguessableToken that was
- // registered for an embedding with mus (specifically ws::mojom::WindowTree).
- std::unique_ptr<MusEmbeddedFrame> CreateMusEmbeddedFrame(
- MusEmbeddedFrameDelegate* mus_embedded_frame_delegate,
- const base::UnguessableToken& token);
-
- private:
- friend class MusEmbeddedFrame;
-
- explicit RendererWindowTreeClient(int routing_id);
- ~RendererWindowTreeClient() override;
-
- void RequestLayerTreeFrameSinkInternal(
- scoped_refptr<viz::ContextProvider> context_provider,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- LayerTreeFrameSinkCallback callback);
-
- // Called from ~MusEmbeddedFrame to cleanup up internall mapping.
- void OnEmbeddedFrameDestroyed(MusEmbeddedFrame* frame);
-
- uint32_t GetAndAdvanceNextChangeId() { return ++next_change_id_; }
-
- // mojom::RenderWidgetWindowTreeClient:
- void Embed(uint32_t frame_routing_id,
- const base::UnguessableToken& token) override;
- void DestroyFrame(uint32_t frame_routing_id) override;
-
- // ws::mojom::WindowTreeClient:
- // Note: A number of the following are currently not-implemented. Some of
- // these will remain unimplemented in the long-term. Some of the
- // implementations would require some amount of refactoring out of
- // RenderWidget and related classes (e.g. resize, input, ime etc.).
- void OnClientId(uint32_t client_id) override;
- void OnEmbed(ws::mojom::WindowDataPtr root,
- ws::mojom::WindowTreePtr tree,
- int64_t display_id,
- ws::Id focused_window_id,
- bool drawn,
- const base::Optional<viz::LocalSurfaceIdAllocation>&
- local_surface_id_allocation) override;
- void OnEmbedFromToken(const base::UnguessableToken& token,
- ws::mojom::WindowDataPtr root,
- int64_t display_id,
- const base::Optional<viz::LocalSurfaceIdAllocation>&
- local_surface_id_allocation) override;
- void OnEmbeddedAppDisconnected(ws::Id window_id) override;
- void OnUnembed(ws::Id window_id) override;
- void OnCaptureChanged(ws::Id new_capture_window_id,
- ws::Id old_capture_window_id) override;
- void OnFrameSinkIdAllocated(ws::Id window_id,
- const viz::FrameSinkId& frame_sink_id) override;
- void OnTopLevelCreated(uint32_t change_id,
- ws::mojom::WindowDataPtr data,
- int64_t display_id,
- bool drawn,
- const viz::LocalSurfaceIdAllocation&
- local_surface_id_allocation) override;
- void OnWindowBoundsChanged(
- ws::Id window_id,
- const gfx::Rect& new_bounds,
- ui::WindowShowState state,
- const base::Optional<viz::LocalSurfaceIdAllocation>&
- local_surface_id_allocation) override;
- void OnWindowTransformChanged(ws::Id window_id,
- const gfx::Transform& new_transform) override;
- void OnTransientWindowAdded(ws::Id window_id,
- ws::Id transient_window_id) override;
- void OnTransientWindowRemoved(ws::Id window_id,
- ws::Id transient_window_id) override;
- void OnWindowHierarchyChanged(
- ws::Id window_id,
- ws::Id old_parent_id,
- ws::Id new_parent_id,
- std::vector<ws::mojom::WindowDataPtr> windows) override;
- void OnWindowReordered(ws::Id window_id,
- ws::Id relative_window_id,
- ws::mojom::OrderDirection direction) override;
- void OnWindowDeleted(ws::Id window_id) override;
- void OnWindowVisibilityChanged(ws::Id window_id, bool visible) override;
- void OnWindowDisplayChanged(ws::Id window_id, int64_t display_id) override;
- void OnWindowParentDrawnStateChanged(ws::Id window_id, bool drawn) override;
- void OnWindowSharedPropertyChanged(
- ws::Id window_id,
- const std::string& name,
- const base::Optional<std::vector<uint8_t>>& new_data) override;
- void OnWindowInputEvent(uint32_t event_id,
- ws::Id window_id,
- int64_t display_id,
- std::unique_ptr<ui::Event> event,
- bool matches_event_observer) override;
- void OnObservedInputEvent(std::unique_ptr<ui::Event> event) override;
- void OnWindowFocused(ws::Id focused_window_id) override;
- void OnWindowCursorChanged(ws::Id window_id, ui::Cursor cursor) override;
- void OnDragDropStart(const base::flat_map<std::string, std::vector<uint8_t>>&
- mime_data) override;
- void OnDragEnter(ws::Id window_id,
- uint32_t event_flags,
- const gfx::PointF& location_in_root,
- const gfx::PointF& location,
- uint32_t effect_bitmask,
- OnDragEnterCallback callback) override;
- void OnDragOver(ws::Id window_id,
- uint32_t event_flags,
- const gfx::PointF& location_in_root,
- const gfx::PointF& location,
- uint32_t effect_bitmask,
- OnDragOverCallback callback) override;
- void OnDragLeave(ws::Id window_id) override;
- void OnCompleteDrop(ws::Id window_id,
- uint32_t event_flags,
- const gfx::PointF& location_in_root,
- const gfx::PointF& location,
- uint32_t effect_bitmask,
- OnCompleteDropCallback callback) override;
- void OnPerformDragDropCompleted(uint32_t change_id,
- bool success,
- uint32_t action_taken) override;
- void OnDragDropDone() override;
- void OnTopmostWindowChanged(const std::vector<ws::Id>& topmost_ids) override;
- void OnChangeCompleted(uint32_t change_id, bool success) override;
- void RequestClose(ws::Id window_id) override;
- void GetScreenProviderObserver(
- ws::mojom::ScreenProviderObserverAssociatedRequest observer) override;
- void OnOcclusionStatesChanged(
- const base::flat_map<ws::Id, ws::mojom::OcclusionState>&
- occlusion_changes) override;
- void CleanupGestureState(ws::Id window_id) override;
- void OnWindowResizeLoopStarted(ws::Id window_id) override;
- void OnWindowResizeLoopEnded(ws::Id window_id) override;
-
- const int routing_id_;
- ws::Id root_window_id_ = 0u;
- bool visible_ = false;
- scoped_refptr<viz::ContextProvider> pending_context_provider_;
- gpu::GpuMemoryBufferManager* pending_gpu_memory_buffer_manager_ = nullptr;
- LayerTreeFrameSinkCallback pending_layer_tree_frame_sink_callback_;
- ws::mojom::WindowTreePtr tree_;
- mojo::Binding<ws::mojom::WindowTreeClient> binding_;
- mojo::Binding<mojom::RenderWidgetWindowTreeClient>
- render_widget_window_tree_client_binding_;
- ws::ClientSpecificId next_window_id_ = 0;
- uint32_t next_change_id_ = 0;
-
- // Set of MusEmbeddedFrames. They are owned by the corresponding
- // RenderFrameProxy.
- base::flat_set<MusEmbeddedFrame*> embedded_frames_;
-
- // Because RenderFrameProxy is created from an IPC message on a different
- // pipe it's entirely possible Embed() may be called before the
- // RenderFrameProxy is created. If Embed() is called before the
- // RenderFrameProxy is created the WindowTreeClient is added here.
- std::map<uint32_t, base::UnguessableToken> pending_frames_;
-
- DISALLOW_COPY_AND_ASSIGN(RendererWindowTreeClient);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MUS_RENDERER_WINDOW_TREE_CLIENT_H_
diff --git a/chromium/content/renderer/navigation_client.cc b/chromium/content/renderer/navigation_client.cc
index 36593d80663..97805224847 100644
--- a/chromium/content/renderer/navigation_client.cc
+++ b/chromium/content/renderer/navigation_client.cc
@@ -58,8 +58,8 @@ void NavigationClient::CommitFailedNavigation(
void NavigationClient::Bind(mojom::NavigationClientAssociatedRequest request) {
navigation_client_binding_.Bind(
- std::move(request),
- render_frame_->GetTaskRunner(blink::TaskType::kInternalNavigation));
+ std::move(request), render_frame_->GetTaskRunner(
+ blink::TaskType::kInternalNavigationAssociated));
SetDisconnectionHandler();
}
diff --git a/chromium/content/renderer/p2p/filtering_network_manager.cc b/chromium/content/renderer/p2p/filtering_network_manager.cc
index 73b9985489e..0596ce9e554 100644
--- a/chromium/content/renderer/p2p/filtering_network_manager.cc
+++ b/chromium/content/renderer/p2p/filtering_network_manager.cc
@@ -113,10 +113,12 @@ void FilteringNetworkManager::CheckPermission() {
// Request for media permission asynchronously.
media_permission_->HasPermission(
media::MediaPermission::AUDIO_CAPTURE,
- base::Bind(&FilteringNetworkManager::OnPermissionStatus, GetWeakPtr()));
+ base::BindOnce(&FilteringNetworkManager::OnPermissionStatus,
+ GetWeakPtr()));
media_permission_->HasPermission(
media::MediaPermission::VIDEO_CAPTURE,
- base::Bind(&FilteringNetworkManager::OnPermissionStatus, GetWeakPtr()));
+ base::BindOnce(&FilteringNetworkManager::OnPermissionStatus,
+ GetWeakPtr()));
}
void FilteringNetworkManager::OnPermissionStatus(bool granted) {
diff --git a/chromium/content/renderer/p2p/filtering_network_manager_unittest.cc b/chromium/content/renderer/p2p/filtering_network_manager_unittest.cc
index 7821bcbb997..9888bd529d6 100644
--- a/chromium/content/renderer/p2p/filtering_network_manager_unittest.cc
+++ b/chromium/content/renderer/p2p/filtering_network_manager_unittest.cc
@@ -107,40 +107,37 @@ class MockMediaPermission : public media::MediaPermission {
MockMediaPermission() {}
~MockMediaPermission() override {}
- void RequestPermission(
- Type type,
- const PermissionStatusCB& permission_status_cb) override {
+ void RequestPermission(Type type,
+ PermissionStatusCB permission_status_cb) override {
NOTIMPLEMENTED();
}
void HasPermission(Type type,
- const PermissionStatusCB& permission_status_cb) override {
+ PermissionStatusCB permission_status_cb) override {
if (type == MediaPermission::AUDIO_CAPTURE) {
DCHECK(mic_callback_.is_null());
- mic_callback_ = permission_status_cb;
+ mic_callback_ = std::move(permission_status_cb);
} else {
DCHECK(type == MediaPermission::VIDEO_CAPTURE);
DCHECK(camera_callback_.is_null());
- camera_callback_ = permission_status_cb;
+ camera_callback_ = std::move(permission_status_cb);
}
}
bool IsEncryptedMediaEnabled() override { return true; }
void SetMicPermission(bool granted) {
- if (mic_callback_.is_null())
+ if (!mic_callback_)
return;
- mic_callback_.Run(granted);
- mic_callback_ = PermissionStatusCB();
+ std::move(mic_callback_).Run(granted);
}
void SetCameraPermission(bool granted) {
- if (camera_callback_.is_null())
+ if (!camera_callback_)
return;
- camera_callback_.Run(granted);
- camera_callback_ = PermissionStatusCB();
+ std::move(camera_callback_).Run(granted);
}
private:
diff --git a/chromium/content/renderer/p2p/host_address_request.cc b/chromium/content/renderer/p2p/host_address_request.cc
index 9cd1a06dcbc..1424c153c13 100644
--- a/chromium/content/renderer/p2p/host_address_request.cc
+++ b/chromium/content/renderer/p2p/host_address_request.cc
@@ -4,8 +4,9 @@
#include "content/renderer/p2p/host_address_request.h"
+#include <utility>
+
#include "base/bind.h"
-#include "base/callback_helpers.h"
#include "base/feature_list.h"
#include "base/location.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -26,12 +27,12 @@ P2PAsyncAddressResolver::~P2PAsyncAddressResolver() {
}
void P2PAsyncAddressResolver::Start(const rtc::SocketAddress& host_name,
- const DoneCallback& done_callback) {
+ DoneCallback done_callback) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(STATE_CREATED, state_);
state_ = STATE_SENT;
- done_callback_ = done_callback;
+ done_callback_ = std::move(done_callback);
bool enable_mdns =
base::FeatureList::IsEnabled(features::kWebRtcHideLocalIpsWithMdns);
dispatcher_->GetP2PSocketManager()->get()->GetHostAddress(
@@ -53,7 +54,7 @@ void P2PAsyncAddressResolver::OnResponse(const net::IPAddressList& addresses) {
DCHECK(thread_checker_.CalledOnValidThread());
if (state_ == STATE_SENT) {
state_ = STATE_FINISHED;
- base::ResetAndReturn(&done_callback_).Run(addresses);
+ std::move(done_callback_).Run(addresses);
}
}
diff --git a/chromium/content/renderer/p2p/host_address_request.h b/chromium/content/renderer/p2p/host_address_request.h
index dcca873a222..cbfc93c26f2 100644
--- a/chromium/content/renderer/p2p/host_address_request.h
+++ b/chromium/content/renderer/p2p/host_address_request.h
@@ -26,12 +26,11 @@ class P2PSocketDispatcher;
class P2PAsyncAddressResolver
: public base::RefCountedThreadSafe<P2PAsyncAddressResolver> {
public:
- typedef base::Callback<void(const net::IPAddressList&)> DoneCallback;
+ using DoneCallback = base::OnceCallback<void(const net::IPAddressList&)>;
P2PAsyncAddressResolver(P2PSocketDispatcher* dispatcher);
// Start address resolve process.
- void Start(const rtc::SocketAddress& addr,
- const DoneCallback& done_callback);
+ void Start(const rtc::SocketAddress& addr, DoneCallback done_callback);
// Clients must unregister before exiting for cleanup.
void Cancel();
diff --git a/chromium/content/renderer/p2p/ipc_socket_factory.cc b/chromium/content/renderer/p2p/ipc_socket_factory.cc
index 78816b1a3c9..2a4b8693624 100644
--- a/chromium/content/renderer/p2p/ipc_socket_factory.cc
+++ b/chromium/content/renderer/p2p/ipc_socket_factory.cc
@@ -663,9 +663,9 @@ void AsyncAddressResolverImpl::Start(const rtc::SocketAddress& addr) {
// GetResolvedAddress.
addr_ = addr;
- resolver_->Start(addr, base::Bind(
- &AsyncAddressResolverImpl::OnAddressResolved,
- base::Unretained(this)));
+ resolver_->Start(addr,
+ base::BindOnce(&AsyncAddressResolverImpl::OnAddressResolved,
+ base::Unretained(this)));
}
bool AsyncAddressResolverImpl::GetResolvedAddress(
diff --git a/chromium/content/renderer/pepper/host_array_buffer_var.cc b/chromium/content/renderer/pepper/host_array_buffer_var.cc
index 84cb02ae4aa..0bdafb83fa3 100644
--- a/chromium/content/renderer/pepper/host_array_buffer_var.cc
+++ b/chromium/content/renderer/pepper/host_array_buffer_var.cc
@@ -10,13 +10,14 @@
#include <memory>
#include "base/logging.h"
-#include "base/memory/shared_memory.h"
+#include "base/memory/shared_memory_mapping.h"
#include "base/process/process_handle.h"
#include "content/common/pepper_file_util.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/plugin_module.h"
#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
#include "content/renderer/render_thread_impl.h"
+#include "mojo/public/cpp/base/shared_memory_utils.h"
#include "ppapi/c/pp_instance.h"
using ppapi::ArrayBufferVar;
@@ -31,14 +32,14 @@ HostArrayBufferVar::HostArrayBufferVar(uint32_t size_in_bytes)
HostArrayBufferVar::HostArrayBufferVar(const WebArrayBuffer& buffer)
: buffer_(buffer), valid_(true) {}
-HostArrayBufferVar::HostArrayBufferVar(uint32_t size_in_bytes,
- base::SharedMemoryHandle handle)
+HostArrayBufferVar::HostArrayBufferVar(
+ uint32_t size_in_bytes,
+ const base::UnsafeSharedMemoryRegion& region)
: buffer_(WebArrayBuffer::Create(size_in_bytes, 1 /* element_size */)) {
- base::SharedMemory s(handle, true);
- valid_ = s.Map(size_in_bytes);
- if (valid_) {
- memcpy(buffer_.Data(), s.memory(), size_in_bytes);
- s.Unmap();
+ base::WritableSharedMemoryMapping shm_mapping =
+ region.MapAt(0, size_in_bytes);
+ if (shm_mapping.IsValid()) {
+ memcpy(buffer_.Data(), shm_mapping.memory(), size_in_bytes);
}
}
@@ -61,26 +62,24 @@ uint32_t HostArrayBufferVar::ByteLength() {
bool HostArrayBufferVar::CopyToNewShmem(
PP_Instance instance,
int* host_shm_handle_id,
- base::SharedMemoryHandle* plugin_shm_handle) {
- std::unique_ptr<base::SharedMemory> shm(
- RenderThread::Get()
- ->HostAllocateSharedMemoryBuffer(ByteLength())
- .release());
- if (!shm)
+ base::UnsafeSharedMemoryRegion* plugin_shm_region) {
+ base::UnsafeSharedMemoryRegion shm =
+ mojo::CreateUnsafeSharedMemoryRegion(ByteLength());
+ if (!shm.IsValid())
return false;
- shm->Map(ByteLength());
- memcpy(shm->memory(), Map(), ByteLength());
- shm->Unmap();
+ base::WritableSharedMemoryMapping shm_mapping = shm.MapAt(0, ByteLength());
+ if (!shm_mapping.IsValid())
+ return false;
+ memcpy(shm_mapping.memory(), Map(), ByteLength());
- // Duplicate the handle here; the SharedMemory destructor closes
+ // Duplicate the handle here; the UnsafeSharedMemoryRegion destructor closes
// its handle on us.
HostGlobals* hg = HostGlobals::Get();
PluginModule* pm = hg->GetModule(hg->GetModuleForInstance(instance));
- *plugin_shm_handle =
- pm->renderer_ppapi_host()->ShareSharedMemoryHandleWithRemote(
- shm->handle());
+ *plugin_shm_region =
+ pm->renderer_ppapi_host()->ShareUnsafeSharedMemoryRegionWithRemote(shm);
*host_shm_handle_id = -1;
return true;
}
diff --git a/chromium/content/renderer/pepper/host_array_buffer_var.h b/chromium/content/renderer/pepper/host_array_buffer_var.h
index 5808d765594..febd896efd7 100644
--- a/chromium/content/renderer/pepper/host_array_buffer_var.h
+++ b/chromium/content/renderer/pepper/host_array_buffer_var.h
@@ -8,7 +8,7 @@
#include <stdint.h>
#include "base/macros.h"
-#include "base/memory/shared_memory.h"
+#include "base/memory/unsafe_shared_memory_region.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/shared_impl/host_resource.h"
#include "ppapi/shared_impl/var.h"
@@ -22,15 +22,16 @@ class HostArrayBufferVar : public ppapi::ArrayBufferVar {
explicit HostArrayBufferVar(uint32_t size_in_bytes);
explicit HostArrayBufferVar(const blink::WebArrayBuffer& buffer);
explicit HostArrayBufferVar(uint32_t size_in_bytes,
- base::SharedMemoryHandle handle);
+ const base::UnsafeSharedMemoryRegion& Region);
// ArrayBufferVar implementation.
void* Map() override;
void Unmap() override;
uint32_t ByteLength() override;
- bool CopyToNewShmem(PP_Instance instance,
- int* host_shm_handle_id,
- base::SharedMemoryHandle* plugin_shm_handle) override;
+ bool CopyToNewShmem(
+ PP_Instance instance,
+ int* host_shm_handle_id,
+ base::UnsafeSharedMemoryRegion* plugin_shm_region) override;
blink::WebArrayBuffer& webkit_buffer() { return buffer_; }
diff --git a/chromium/content/renderer/pepper/host_var_tracker.cc b/chromium/content/renderer/pepper/host_var_tracker.cc
index 0424b3d736c..9141cc4618a 100644
--- a/chromium/content/renderer/pepper/host_var_tracker.cc
+++ b/chromium/content/renderer/pepper/host_var_tracker.cc
@@ -48,8 +48,8 @@ ArrayBufferVar* HostVarTracker::CreateArrayBuffer(uint32_t size_in_bytes) {
ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer(
uint32_t size_in_bytes,
- base::SharedMemoryHandle handle) {
- return new HostArrayBufferVar(size_in_bytes, handle);
+ base::UnsafeSharedMemoryRegion region) {
+ return new HostArrayBufferVar(size_in_bytes, region);
}
void HostVarTracker::AddV8ObjectVar(V8ObjectVar* object_var) {
@@ -152,12 +152,13 @@ HostVarTracker::ObjectMap::iterator HostVarTracker::GetForV8Object(
return object_map_.end();
}
-int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance,
- base::SharedMemoryHandle handle,
- uint32_t size_in_bytes) {
+int HostVarTracker::TrackSharedMemoryRegion(
+ PP_Instance instance,
+ base::UnsafeSharedMemoryRegion region,
+ uint32_t size_in_bytes) {
SharedMemoryMapEntry entry;
entry.instance = instance;
- entry.handle = handle;
+ entry.region = std::move(region);
entry.size_in_bytes = size_in_bytes;
// Find a free id for our map.
@@ -165,14 +166,14 @@ int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance,
shared_memory_map_.end()) {
++last_shared_memory_map_id_;
}
- shared_memory_map_[last_shared_memory_map_id_] = entry;
+ shared_memory_map_[last_shared_memory_map_id_] = std::move(entry);
return last_shared_memory_map_id_;
}
-bool HostVarTracker::StopTrackingSharedMemoryHandle(
+bool HostVarTracker::StopTrackingSharedMemoryRegion(
int id,
PP_Instance instance,
- base::SharedMemoryHandle* handle,
+ base::UnsafeSharedMemoryRegion* region,
uint32_t* size_in_bytes) {
auto it = shared_memory_map_.find(id);
if (it == shared_memory_map_.end())
@@ -180,7 +181,7 @@ bool HostVarTracker::StopTrackingSharedMemoryHandle(
if (it->second.instance != instance)
return false;
- *handle = it->second.handle;
+ *region = std::move(it->second.region);
*size_in_bytes = it->second.size_in_bytes;
shared_memory_map_.erase(it);
return true;
diff --git a/chromium/content/renderer/pepper/host_var_tracker.h b/chromium/content/renderer/pepper/host_var_tracker.h
index 53bd17d1b26..963f3accd21 100644
--- a/chromium/content/renderer/pepper/host_var_tracker.h
+++ b/chromium/content/renderer/pepper/host_var_tracker.h
@@ -51,12 +51,12 @@ class HostVarTracker : public ppapi::VarTracker {
ppapi::ResourceVar* MakeResourceVar(PP_Resource pp_resource) override;
void DidDeleteInstance(PP_Instance pp_instance) override;
- int TrackSharedMemoryHandle(PP_Instance instance,
- base::SharedMemoryHandle file,
+ int TrackSharedMemoryRegion(PP_Instance instance,
+ base::UnsafeSharedMemoryRegion region,
uint32_t size_in_bytes) override;
- bool StopTrackingSharedMemoryHandle(int id,
+ bool StopTrackingSharedMemoryRegion(int id,
PP_Instance instance,
- base::SharedMemoryHandle* handle,
+ base::UnsafeSharedMemoryRegion* region,
uint32_t* size_in_bytes) override;
private:
@@ -64,7 +64,7 @@ class HostVarTracker : public ppapi::VarTracker {
ppapi::ArrayBufferVar* CreateArrayBuffer(uint32_t size_in_bytes) override;
ppapi::ArrayBufferVar* CreateShmArrayBuffer(
uint32_t size_in_bytes,
- base::SharedMemoryHandle handle) override;
+ base::UnsafeSharedMemoryRegion region) override;
// Clear the reference count of the given object and remove it from
// live_vars_.
@@ -96,7 +96,7 @@ class HostVarTracker : public ppapi::VarTracker {
// Tracks all shared memory handles used for transmitting array buffers.
struct SharedMemoryMapEntry {
PP_Instance instance;
- base::SharedMemoryHandle handle;
+ base::UnsafeSharedMemoryRegion region;
uint32_t size_in_bytes;
};
typedef std::map<int, SharedMemoryMapEntry> SharedMemoryMap;
diff --git a/chromium/content/renderer/pepper/message_channel.cc b/chromium/content/renderer/pepper/message_channel.cc
index 963e5098779..76c0a994d80 100644
--- a/chromium/content/renderer/pepper/message_channel.cc
+++ b/chromium/content/renderer/pepper/message_channel.cc
@@ -385,11 +385,9 @@ void MessageChannel::EnqueuePluginMessage(v8::Local<v8::Value> v8_value) {
// support for Messaging.)
// TODO(raymes): Possibly change this to use TryCatch to do the conversion and
// throw an exception if necessary.
- V8VarConverter::VarResult conversion_result =
- var_converter_.FromV8Value(
- v8_value,
- v8::Isolate::GetCurrent()->GetCurrentContext(),
- base::Bind(&MessageChannel::FromV8ValueComplete,
+ V8VarConverter::VarResult conversion_result = var_converter_.FromV8Value(
+ v8_value, v8::Isolate::GetCurrent()->GetCurrentContext(),
+ base::BindOnce(&MessageChannel::FromV8ValueComplete,
weak_ptr_factory_.GetWeakPtr(),
&plugin_message_queue_.back()));
if (conversion_result.completed_synchronously) {
@@ -459,21 +457,20 @@ void MessageChannel::DrainJSMessageQueueSoon() {
}
void MessageChannel::UnregisterSyncMessageStatusObserver() {
- if (!unregister_observer_callback_.is_null()) {
- unregister_observer_callback_.Run();
- unregister_observer_callback_.Reset();
- }
+ if (unregister_observer_callback_)
+ std::move(unregister_observer_callback_).Run();
}
v8::Local<v8::FunctionTemplate> MessageChannel::GetFunctionTemplate(
v8::Isolate* isolate,
const std::string& name,
- void (MessageChannel::*memberFuncPtr)(gin::Arguments* args)) {
+ void (MessageChannel::*member_func_ptr)(gin::Arguments* args)) {
v8::Local<v8::FunctionTemplate> function_template = template_cache_.Get(name);
if (!function_template.IsEmpty())
return function_template;
function_template = gin::CreateFunctionTemplate(
- isolate, base::Bind(memberFuncPtr, weak_ptr_factory_.GetWeakPtr()));
+ isolate,
+ base::BindRepeating(member_func_ptr, weak_ptr_factory_.GetWeakPtr()));
template_cache_.Set(name, function_template);
return function_template;
}
diff --git a/chromium/content/renderer/pepper/message_channel.h b/chromium/content/renderer/pepper/message_channel.h
index 5d0c7e00a7a..93169b2cb2d 100644
--- a/chromium/content/renderer/pepper/message_channel.h
+++ b/chromium/content/renderer/pepper/message_channel.h
@@ -194,7 +194,7 @@ class MessageChannel :
// A callback to invoke at shutdown to ensure we unregister ourselves as
// Observers for sync messages.
- base::Closure unregister_observer_callback_;
+ base::OnceClosure unregister_observer_callback_;
v8::StdGlobalValueMap<std::string, v8::FunctionTemplate> template_cache_;
diff --git a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
index b6e43a61c81..3d3fd0580fd 100644
--- a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
+++ b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
@@ -30,8 +30,8 @@ class PepperDeviceEnumerationHostHelper::ScopedEnumerationRequest
public:
// |owner| must outlive this object.
ScopedEnumerationRequest(PepperDeviceEnumerationHostHelper* owner,
- const Delegate::DevicesCallback& callback)
- : callback_(callback), requested_(false), sync_call_(false) {
+ Delegate::DevicesOnceCallback callback)
+ : callback_(std::move(callback)), requested_(false), sync_call_(false) {
if (!owner->delegate_) {
// If no delegate, return an empty list of devices.
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -53,8 +53,8 @@ class PepperDeviceEnumerationHostHelper::ScopedEnumerationRequest
sync_call_ = true;
owner->delegate_->EnumerateDevices(
owner->device_type_,
- base::Bind(&ScopedEnumerationRequest::EnumerateDevicesCallbackBody,
- AsWeakPtr()));
+ base::BindOnce(&ScopedEnumerationRequest::EnumerateDevicesCallbackBody,
+ AsWeakPtr()));
sync_call_ = false;
}
@@ -70,12 +70,12 @@ class PepperDeviceEnumerationHostHelper::ScopedEnumerationRequest
&ScopedEnumerationRequest::EnumerateDevicesCallbackBody,
AsWeakPtr(), devices));
} else {
- callback_.Run(devices);
+ std::move(callback_).Run(devices);
// This object may have been destroyed at this point.
}
}
- PepperDeviceEnumerationHostHelper::Delegate::DevicesCallback callback_;
+ PepperDeviceEnumerationHostHelper::Delegate::DevicesOnceCallback callback_;
bool requested_;
bool sync_call_;
@@ -89,9 +89,9 @@ class PepperDeviceEnumerationHostHelper::ScopedMonitoringRequest
public:
// |owner| must outlive this object.
ScopedMonitoringRequest(PepperDeviceEnumerationHostHelper* owner,
- const Delegate::DevicesCallback& callback)
+ Delegate::DevicesCallback callback)
: owner_(owner),
- callback_(callback),
+ callback_(std::move(callback)),
requested_(false),
subscription_id_(0u) {
DCHECK(owner_);
@@ -104,7 +104,7 @@ class PepperDeviceEnumerationHostHelper::ScopedMonitoringRequest
// |callback| is never called synchronously by StartMonitoringDevices(),
// so it is OK to pass it directly, even if |callback| destroys |this|.
subscription_id_ = owner_->delegate_->StartMonitoringDevices(
- owner_->device_type_, callback);
+ owner_->device_type_, callback_);
}
~ScopedMonitoringRequest() {
@@ -170,10 +170,10 @@ int32_t PepperDeviceEnumerationHostHelper::OnEnumerateDevices(
if (enumerate_devices_context_.is_valid())
return PP_ERROR_INPROGRESS;
- enumerate_.reset(new ScopedEnumerationRequest(
- this,
- base::Bind(&PepperDeviceEnumerationHostHelper::OnEnumerateDevicesComplete,
- base::Unretained(this))));
+ enumerate_ = std::make_unique<ScopedEnumerationRequest>(
+ this, base::BindOnce(
+ &PepperDeviceEnumerationHostHelper::OnEnumerateDevicesComplete,
+ base::Unretained(this)));
if (!enumerate_->requested())
return PP_ERROR_FAILED;
@@ -184,9 +184,10 @@ int32_t PepperDeviceEnumerationHostHelper::OnEnumerateDevices(
int32_t PepperDeviceEnumerationHostHelper::OnMonitorDeviceChange(
HostMessageContext* /* context */,
uint32_t callback_id) {
- monitor_.reset(new ScopedMonitoringRequest(
- this, base::Bind(&PepperDeviceEnumerationHostHelper::OnNotifyDeviceChange,
- base::Unretained(this), callback_id)));
+ monitor_ = std::make_unique<ScopedMonitoringRequest>(
+ this, base::BindRepeating(
+ &PepperDeviceEnumerationHostHelper::OnNotifyDeviceChange,
+ base::Unretained(this), callback_id));
return monitor_->requested() ? PP_OK : PP_ERROR_FAILED;
}
diff --git a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h
index 98c746a6beb..5c2d101d9c2 100644
--- a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h
+++ b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h
@@ -44,12 +44,14 @@ class CONTENT_EXPORT PepperDeviceEnumerationHostHelper {
public:
virtual ~Delegate() {}
- using DevicesCallback = base::Callback<void(
+ using DevicesCallback = base::RepeatingCallback<void(
+ const std::vector<ppapi::DeviceRefData>& /* devices */)>;
+ using DevicesOnceCallback = base::OnceCallback<void(
const std::vector<ppapi::DeviceRefData>& /* devices */)>;
// Enumerates devices of the specified type.
virtual void EnumerateDevices(PP_DeviceType_Dev type,
- const DevicesCallback& callback) = 0;
+ DevicesOnceCallback callback) = 0;
// Starts monitoring devices of the specified |type|. Returns a
// subscription ID that must be used to stop monitoring for the device
diff --git a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc
index 8e20a934c21..f040b607696 100644
--- a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc
@@ -53,8 +53,8 @@ class TestDelegate : public PepperDeviceEnumerationHostHelper::Delegate,
~TestDelegate() override { CHECK(monitoring_callbacks_.empty()); }
void EnumerateDevices(PP_DeviceType_Dev /* type */,
- const DevicesCallback& callback) override {
- callback.Run(TestEnumerationData());
+ DevicesOnceCallback callback) override {
+ std::move(callback).Run(TestEnumerationData());
}
size_t StartMonitoringDevices(PP_DeviceType_Dev /* type */,
diff --git a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
index 435b28d5687..d66674327ce 100644
--- a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
+++ b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
@@ -124,12 +124,9 @@ void PepperFileChooserHost::StoreChosenFiles(
if (!files.empty()) {
renderer_ppapi_host_->CreateBrowserResourceHosts(
- pp_instance(),
- create_msgs,
- base::Bind(&PepperFileChooserHost::DidCreateResourceHosts,
- weak_factory_.GetWeakPtr(),
- file_paths,
- display_names));
+ pp_instance(), create_msgs,
+ base::BindOnce(&PepperFileChooserHost::DidCreateResourceHosts,
+ weak_factory_.GetWeakPtr(), file_paths, display_names));
} else {
reply_context_.params.set_result(PP_ERROR_USERCANCEL);
std::vector<ppapi::FileRefCreateInfo> chosen_files;
diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
index 11a081b4d90..c7931408daa 100644
--- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
+++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/memory/read_only_shared_memory_region.h"
#include "base/numerics/checked_math.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
@@ -719,7 +720,7 @@ bool PepperGraphics2DHost::PrepareTransferableResource(
*release_callback = viz::SingleReleaseCallback::Create(
base::BindOnce(&ReleaseTextureCallback, this->AsWeakPtr(),
main_thread_context_, size, gpu_mailbox));
- *transferable_resource = viz::TransferableResource::MakeGLOverlay(
+ *transferable_resource = viz::TransferableResource::MakeGL(
std::move(gpu_mailbox), GL_LINEAR, texture_target,
std::move(out_sync_token), size, overlays_supported);
transferable_resource->format = format;
@@ -741,15 +742,15 @@ bool PepperGraphics2DHost::PrepareTransferableResource(
}
if (!shared_bitmap) {
viz::SharedBitmapId id = viz::SharedBitmap::GenerateId();
- std::unique_ptr<base::SharedMemory> shm =
- viz::bitmap_allocation::AllocateMappedBitmap(pixel_image_size,
+ base::MappedReadOnlyRegion shm =
+ viz::bitmap_allocation::AllocateSharedBitmap(pixel_image_size,
viz::RGBA_8888);
shared_bitmap = base::MakeRefCounted<cc::CrossThreadSharedBitmap>(
id, std::move(shm), pixel_image_size, viz::RGBA_8888);
registration = bitmap_registrar->RegisterSharedBitmapId(id, shared_bitmap);
}
void* src = image_data_->Map();
- memcpy(shared_bitmap->shared_memory()->memory(), src,
+ memcpy(shared_bitmap->memory(), src,
viz::ResourceSizes::CheckedSizeInBytes<size_t>(pixel_image_size,
viz::RGBA_8888));
image_data_->Unmap();
diff --git a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc
index d6c1b39ddbd..29331380673 100644
--- a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc
+++ b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc
@@ -124,6 +124,13 @@ PP_Resource PepperInProcessResourceCreation::CreatePrinting(
instance))->GetReference();
}
+PP_Resource PepperInProcessResourceCreation::CreateTrueTypeFont(
+ PP_Instance instance,
+ const PP_TrueTypeFontDesc_Dev* desc) {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
PP_Resource PepperInProcessResourceCreation::CreateURLLoader(
PP_Instance instance) {
return (new ppapi::proxy::URLLoaderResource(
diff --git a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.h b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.h
index a11690d9c31..d094658223c 100644
--- a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.h
+++ b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.h
@@ -58,6 +58,9 @@ class PepperInProcessResourceCreation : public ResourceCreationImpl {
const PP_Size* size,
PP_Bool is_always_opaque) override;
PP_Resource CreatePrinting(PP_Instance instance) override;
+ PP_Resource CreateTrueTypeFont(
+ PP_Instance instance,
+ const struct PP_TrueTypeFontDesc_Dev* desc) override;
PP_Resource CreateURLLoader(PP_Instance instance) override;
PP_Resource CreateURLRequestInfo(PP_Instance instance) override;
PP_Resource CreateWebSocket(PP_Instance instance) override;
diff --git a/chromium/content/renderer/pepper/pepper_in_process_router.cc b/chromium/content/renderer/pepper/pepper_in_process_router.cc
index be02edbf768..ce05b4a0e9c 100644
--- a/chromium/content/renderer/pepper/pepper_in_process_router.cc
+++ b/chromium/content/renderer/pepper/pepper_in_process_router.cc
@@ -23,7 +23,7 @@ namespace content {
class PepperInProcessRouter::Channel : public IPC::Sender {
public:
- Channel(const base::Callback<bool(IPC::Message*)>& callback)
+ Channel(const base::RepeatingCallback<bool(IPC::Message*)>& callback)
: callback_(callback) {}
~Channel() override {}
@@ -31,7 +31,7 @@ class PepperInProcessRouter::Channel : public IPC::Sender {
bool Send(IPC::Message* message) override { return callback_.Run(message); }
private:
- base::Callback<bool(IPC::Message*)> callback_;
+ base::RepeatingCallback<bool(IPC::Message*)> callback_;
};
PepperInProcessRouter::PepperInProcessRouter(RendererPpapiHostImpl* host_impl)
@@ -39,12 +39,12 @@ PepperInProcessRouter::PepperInProcessRouter(RendererPpapiHostImpl* host_impl)
pending_message_id_(0),
reply_result_(false),
weak_factory_(this) {
- browser_channel_.reset(new Channel(base::Bind(
+ browser_channel_.reset(new Channel(base::BindRepeating(
&PepperInProcessRouter::SendToBrowser, base::Unretained(this))));
- host_to_plugin_router_.reset(new Channel(base::Bind(
+ host_to_plugin_router_.reset(new Channel(base::BindRepeating(
&PepperInProcessRouter::SendToPlugin, base::Unretained(this))));
- plugin_to_host_router_.reset(new Channel(
- base::Bind(&PepperInProcessRouter::SendToHost, base::Unretained(this))));
+ plugin_to_host_router_.reset(new Channel(base::BindRepeating(
+ &PepperInProcessRouter::SendToHost, base::Unretained(this))));
}
PepperInProcessRouter::~PepperInProcessRouter() {}
diff --git a/chromium/content/renderer/pepper/pepper_media_device_manager.cc b/chromium/content/renderer/pepper/pepper_media_device_manager.cc
index 72f55ccdeca..f882acaa376 100644
--- a/chromium/content/renderer/pepper/pepper_media_device_manager.cc
+++ b/chromium/content/renderer/pepper/pepper_media_device_manager.cc
@@ -101,9 +101,8 @@ PepperMediaDeviceManager::~PepperMediaDeviceManager() {
DCHECK(open_callbacks_.empty());
}
-void PepperMediaDeviceManager::EnumerateDevices(
- PP_DeviceType_Dev type,
- const DevicesCallback& callback) {
+void PepperMediaDeviceManager::EnumerateDevices(PP_DeviceType_Dev type,
+ DevicesOnceCallback callback) {
bool request_audio_input = type == PP_DEVICETYPE_DEV_AUDIOCAPTURE;
bool request_video_input = type == PP_DEVICETYPE_DEV_VIDEOCAPTURE;
bool request_audio_output = type == PP_DEVICETYPE_DEV_AUDIOOUTPUT;
@@ -113,7 +112,7 @@ void PepperMediaDeviceManager::EnumerateDevices(
false /* request_video_input_capabilities */,
false /* request_audio_input_capabilities */,
base::BindOnce(&PepperMediaDeviceManager::DevicesEnumerated, AsWeakPtr(),
- callback, ToMediaDeviceType(type)));
+ std::move(callback), ToMediaDeviceType(type)));
}
size_t PepperMediaDeviceManager::StartMonitoringDevices(
@@ -151,8 +150,8 @@ void PepperMediaDeviceManager::StopMonitoringDevices(PP_DeviceType_Dev type,
int PepperMediaDeviceManager::OpenDevice(PP_DeviceType_Dev type,
const std::string& device_id,
PP_Instance pp_instance,
- const OpenDeviceCallback& callback) {
- open_callbacks_[next_id_] = callback;
+ OpenDeviceCallback callback) {
+ open_callbacks_[next_id_] = std::move(callback);
int request_id = next_id_++;
RendererPpapiHostImpl* host =
@@ -246,21 +245,22 @@ void PepperMediaDeviceManager::OnDeviceOpened(
if (success)
GetMediaStreamDeviceObserver()->AddStream(label, device);
- OpenDeviceCallback callback = iter->second;
+ OpenDeviceCallback callback = std::move(iter->second);
open_callbacks_.erase(iter);
std::move(callback).Run(request_id, success, success ? label : std::string());
}
void PepperMediaDeviceManager::DevicesEnumerated(
- const DevicesCallback& client_callback,
+ DevicesOnceCallback client_callback,
blink::MediaDeviceType type,
const std::vector<blink::WebMediaDeviceInfoArray>& enumeration,
std::vector<blink::mojom::VideoInputDeviceCapabilitiesPtr>
video_input_capabilities,
std::vector<blink::mojom::AudioInputDeviceCapabilitiesPtr>
audio_input_capabilities) {
- client_callback.Run(FromMediaDeviceInfoArray(type, enumeration[type]));
+ std::move(client_callback)
+ .Run(FromMediaDeviceInfoArray(type, enumeration[type]));
}
const blink::mojom::MediaStreamDispatcherHostPtr&
diff --git a/chromium/content/renderer/pepper/pepper_media_device_manager.h b/chromium/content/renderer/pepper/pepper_media_device_manager.h
index dd6f3e65568..9449668a735 100644
--- a/chromium/content/renderer/pepper/pepper_media_device_manager.h
+++ b/chromium/content/renderer/pepper/pepper_media_device_manager.h
@@ -37,7 +37,7 @@ class PepperMediaDeviceManager
// PepperDeviceEnumerationHostHelper::Delegate implementation:
void EnumerateDevices(PP_DeviceType_Dev type,
- const DevicesCallback& callback) override;
+ DevicesOnceCallback callback) override;
size_t StartMonitoringDevices(PP_DeviceType_Dev type,
const DevicesCallback& callback) override;
void StopMonitoringDevices(PP_DeviceType_Dev type,
@@ -48,10 +48,10 @@ class PepperMediaDeviceManager
blink::MediaDeviceType type,
const blink::WebMediaDeviceInfoArray& device_infos) override;
- typedef base::Callback<void(int /* request_id */,
+ using OpenDeviceCallback =
+ base::OnceCallback<void(int /* request_id */,
bool /* succeeded */,
- const std::string& /* label */)>
- OpenDeviceCallback;
+ const std::string& /* label */)>;
// Opens the specified device. The request ID passed into the callback will be
// the same as the return value. If successful, the label passed into the
@@ -60,7 +60,7 @@ class PepperMediaDeviceManager
int OpenDevice(PP_DeviceType_Dev type,
const std::string& device_id,
PP_Instance pp_instance,
- const OpenDeviceCallback& callback);
+ OpenDeviceCallback callback);
// Cancels an request to open device, using the request ID returned by
// OpenDevice(). It is guaranteed that the callback passed into OpenDevice()
// won't be called afterwards.
@@ -88,7 +88,7 @@ class PepperMediaDeviceManager
const blink::MediaStreamDevice& device);
void DevicesEnumerated(
- const DevicesCallback& callback,
+ DevicesOnceCallback callback,
blink::MediaDeviceType type,
const std::vector<blink::WebMediaDeviceInfoArray>& enumeration,
std::vector<blink::mojom::VideoInputDeviceCapabilitiesPtr>
diff --git a/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc b/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc
index 62bafdb77be..12f0d7ade30 100644
--- a/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc
+++ b/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc
@@ -92,33 +92,31 @@ PP_VideoFrame_Format GetTargetFormat(PP_VideoFrame_Format source,
return plugin != PP_VIDEOFRAME_FORMAT_UNKNOWN ? plugin : source;
}
-void ConvertFromMediaVideoFrame(const scoped_refptr<media::VideoFrame>& src,
+void ConvertFromMediaVideoFrame(const media::VideoFrame& src,
PP_VideoFrame_Format dst_format,
const gfx::Size& dst_size,
uint8_t* dst) {
- CHECK(src->format() == media::PIXEL_FORMAT_YV12 ||
- src->format() == media::PIXEL_FORMAT_I420);
+ CHECK(src.format() == media::PIXEL_FORMAT_YV12 ||
+ src.format() == media::PIXEL_FORMAT_I420);
if (dst_format == PP_VIDEOFRAME_FORMAT_BGRA) {
- if (src->visible_rect().size() == dst_size) {
- libyuv::I420ToARGB(src->visible_data(VideoFrame::kYPlane),
- src->stride(VideoFrame::kYPlane),
- src->visible_data(VideoFrame::kUPlane),
- src->stride(VideoFrame::kUPlane),
- src->visible_data(VideoFrame::kVPlane),
- src->stride(VideoFrame::kVPlane),
- dst,
- dst_size.width() * 4,
- dst_size.width(),
+ if (src.visible_rect().size() == dst_size) {
+ libyuv::I420ToARGB(src.visible_data(VideoFrame::kYPlane),
+ src.stride(VideoFrame::kYPlane),
+ src.visible_data(VideoFrame::kUPlane),
+ src.stride(VideoFrame::kUPlane),
+ src.visible_data(VideoFrame::kVPlane),
+ src.stride(VideoFrame::kVPlane), dst,
+ dst_size.width() * 4, dst_size.width(),
dst_size.height());
} else {
libyuv::YUVToARGBScaleClip(
- src->visible_data(VideoFrame::kYPlane),
- src->stride(VideoFrame::kYPlane),
- src->visible_data(VideoFrame::kUPlane),
- src->stride(VideoFrame::kUPlane),
- src->visible_data(VideoFrame::kVPlane),
- src->stride(VideoFrame::kVPlane), libyuv::FOURCC_YV12,
- src->visible_rect().width(), src->visible_rect().height(), dst,
+ src.visible_data(VideoFrame::kYPlane),
+ src.stride(VideoFrame::kYPlane),
+ src.visible_data(VideoFrame::kUPlane),
+ src.stride(VideoFrame::kUPlane),
+ src.visible_data(VideoFrame::kVPlane),
+ src.stride(VideoFrame::kVPlane), libyuv::FOURCC_YV12,
+ src.visible_rect().width(), src.visible_rect().height(), dst,
dst_size.width() * 4, libyuv::FOURCC_ARGB, dst_size.width(),
dst_size.height(), 0, 0, dst_size.width(), dst_size.height(),
kFilterMode);
@@ -134,39 +132,24 @@ void ConvertFromMediaVideoFrame(const scoped_refptr<media::VideoFrame>& src,
const int plane_order = (dst_format == PP_VIDEOFRAME_FORMAT_YV12) ? 0 : 1;
int dst_width = dst_size.width();
int dst_height = dst_size.height();
- libyuv::ScalePlane(src->visible_data(kPlanesOrder[plane_order][0]),
- src->stride(kPlanesOrder[plane_order][0]),
- src->visible_rect().width(),
- src->visible_rect().height(),
- dst,
- dst_width,
- dst_width,
- dst_height,
- kFilterMode);
+ libyuv::ScalePlane(src.visible_data(kPlanesOrder[plane_order][0]),
+ src.stride(kPlanesOrder[plane_order][0]),
+ src.visible_rect().width(), src.visible_rect().height(),
+ dst, dst_width, dst_width, dst_height, kFilterMode);
dst += dst_width * dst_height;
- const int src_halfwidth = (src->visible_rect().width() + 1) >> 1;
- const int src_halfheight = (src->visible_rect().height() + 1) >> 1;
+ const int src_halfwidth = (src.visible_rect().width() + 1) >> 1;
+ const int src_halfheight = (src.visible_rect().height() + 1) >> 1;
const int dst_halfwidth = (dst_width + 1) >> 1;
const int dst_halfheight = (dst_height + 1) >> 1;
- libyuv::ScalePlane(src->visible_data(kPlanesOrder[plane_order][1]),
- src->stride(kPlanesOrder[plane_order][1]),
- src_halfwidth,
- src_halfheight,
- dst,
- dst_halfwidth,
- dst_halfwidth,
- dst_halfheight,
- kFilterMode);
+ libyuv::ScalePlane(src.visible_data(kPlanesOrder[plane_order][1]),
+ src.stride(kPlanesOrder[plane_order][1]), src_halfwidth,
+ src_halfheight, dst, dst_halfwidth, dst_halfwidth,
+ dst_halfheight, kFilterMode);
dst += dst_halfwidth * dst_halfheight;
- libyuv::ScalePlane(src->visible_data(kPlanesOrder[plane_order][2]),
- src->stride(kPlanesOrder[plane_order][2]),
- src_halfwidth,
- src_halfheight,
- dst,
- dst_halfwidth,
- dst_halfwidth,
- dst_halfheight,
- kFilterMode);
+ libyuv::ScalePlane(src.visible_data(kPlanesOrder[plane_order][2]),
+ src.stride(kPlanesOrder[plane_order][2]), src_halfwidth,
+ src_halfheight, dst, dst_halfwidth, dst_halfwidth,
+ dst_halfheight, kFilterMode);
} else {
NOTREACHED();
}
@@ -184,13 +167,13 @@ class PepperMediaStreamVideoTrackHost::FrameDeliverer
FrameDeliverer(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const blink::VideoCaptureDeliverFrameCB& new_frame_callback);
- void DeliverVideoFrame(const scoped_refptr<media::VideoFrame>& frame);
+ void DeliverVideoFrame(scoped_refptr<media::VideoFrame> frame);
private:
friend class base::RefCountedThreadSafe<FrameDeliverer>;
virtual ~FrameDeliverer();
- void DeliverFrameOnIO(const scoped_refptr<media::VideoFrame>& frame);
+ void DeliverFrameOnIO(scoped_refptr<media::VideoFrame> frame);
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
blink::VideoCaptureDeliverFrameCB new_frame_callback_;
@@ -208,18 +191,18 @@ PepperMediaStreamVideoTrackHost::FrameDeliverer::~FrameDeliverer() {
}
void PepperMediaStreamVideoTrackHost::FrameDeliverer::DeliverVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
+ scoped_refptr<media::VideoFrame> frame) {
io_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&FrameDeliverer::DeliverFrameOnIO, this, frame));
+ FROM_HERE, base::BindOnce(&FrameDeliverer::DeliverFrameOnIO, this,
+ std::move(frame)));
}
void PepperMediaStreamVideoTrackHost::FrameDeliverer::DeliverFrameOnIO(
- const scoped_refptr<media::VideoFrame>& frame) {
+ scoped_refptr<media::VideoFrame> frame) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
// The time when this frame is generated is unknown so give a null value to
// |estimated_capture_time|.
- new_frame_callback_.Run(frame, base::TimeTicks());
+ new_frame_callback_.Run(std::move(frame), base::TimeTicks());
}
PepperMediaStreamVideoTrackHost::PepperMediaStreamVideoTrackHost(
@@ -364,14 +347,14 @@ int32_t PepperMediaStreamVideoTrackHost::SendFrameToTrack(int32_t index) {
}
void PepperMediaStreamVideoTrackHost::OnVideoFrame(
- const scoped_refptr<VideoFrame>& video_frame,
+ scoped_refptr<VideoFrame> video_frame,
base::TimeTicks estimated_capture_time) {
- DCHECK(video_frame.get());
+ DCHECK(video_frame);
// TODO(penghuang): Check |frame->end_of_stream()| and close the track.
scoped_refptr<media::VideoFrame> frame = video_frame;
// Drop alpha channel since we do not support it yet.
if (frame->format() == media::PIXEL_FORMAT_I420A)
- frame = media::WrapAsI420VideoFrame(video_frame);
+ frame = media::WrapAsI420VideoFrame(std::move(video_frame));
PP_VideoFrame_Format ppformat = ToPpapiFormat(frame->format());
if (ppformat == PP_VIDEOFRAME_FORMAT_UNKNOWN)
return;
@@ -403,7 +386,7 @@ void PepperMediaStreamVideoTrackHost::OnVideoFrame(
buffer->size.width = size.width();
buffer->size.height = size.height();
buffer->data_size = frame_data_size_;
- ConvertFromMediaVideoFrame(frame, ppformat, size, buffer->data);
+ ConvertFromMediaVideoFrame(*frame, ppformat, size, buffer->data);
SendEnqueueBufferMessageToPlugin(index);
}
@@ -451,8 +434,8 @@ void PepperMediaStreamVideoTrackHost::DidConnectPendingHostToResource() {
blink::MediaStreamVideoSink::ConnectToTrack(
track_,
media::BindToCurrentLoop(
- base::Bind(&PepperMediaStreamVideoTrackHost::OnVideoFrame,
- weak_factory_.GetWeakPtr())),
+ base::BindRepeating(&PepperMediaStreamVideoTrackHost::OnVideoFrame,
+ weak_factory_.GetWeakPtr())),
false);
}
@@ -523,8 +506,8 @@ void PepperMediaStreamVideoTrackHost::InitBlinkTrack() {
const bool enabled = true;
track_ = blink::MediaStreamVideoTrack::CreateVideoTrack(
source,
- base::Bind(&PepperMediaStreamVideoTrackHost::OnTrackStarted,
- base::Unretained(this)),
+ base::BindRepeating(&PepperMediaStreamVideoTrackHost::OnTrackStarted,
+ base::Unretained(this)),
enabled);
// Note: The call to CreateVideoTrack() returned a track that holds a
// ref-counted reference to |webkit_source| (and, implicitly, |source|).
diff --git a/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h b/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h
index 60a1e4e6093..1a13dfc3ecb 100644
--- a/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h
+++ b/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h
@@ -65,7 +65,7 @@ class PepperMediaStreamVideoTrackHost : public PepperMediaStreamTrackHostBase,
// Sends frame with |index| to |track_|.
int32_t SendFrameToTrack(int32_t index);
- void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame,
+ void OnVideoFrame(scoped_refptr<media::VideoFrame> frame,
base::TimeTicks estimated_capture_time);
// ResourceHost overrides:
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_input.cc b/chromium/content/renderer/pepper/pepper_platform_audio_input.cc
index fe4a9778901..05702dd25f3 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_input.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_input.cc
@@ -166,7 +166,7 @@ bool PepperPlatformAudioInput::Initialize(
device_id.empty() ? media::AudioDeviceDescription::kDefaultDeviceId
: device_id,
client->pp_instance(),
- base::Bind(&PepperPlatformAudioInput::OnDeviceOpened, this));
+ base::BindOnce(&PepperPlatformAudioInput::OnDeviceOpened, this));
pending_open_device_ = true;
return true;
diff --git a/chromium/content/renderer/pepper/pepper_platform_camera_device.cc b/chromium/content/renderer/pepper/pepper_platform_camera_device.cc
index d62cf6fe77e..f066404d836 100644
--- a/chromium/content/renderer/pepper/pepper_platform_camera_device.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_camera_device.cc
@@ -4,8 +4,9 @@
#include "content/renderer/pepper/pepper_platform_camera_device.h"
+#include <utility>
+
#include "base/bind.h"
-#include "base/callback_helpers.h"
#include "base/logging.h"
#include "content/renderer/media/video_capture/video_capture_impl_manager.h"
#include "content/renderer/pepper/gfx_conversion.h"
@@ -34,8 +35,8 @@ PepperPlatformCameraDevice::PepperPlatformCameraDevice(
if (device_manager) {
pending_open_device_id_ = device_manager->OpenDevice(
PP_DEVICETYPE_DEV_VIDEOCAPTURE, device_id, handler->pp_instance(),
- base::Bind(&PepperPlatformCameraDevice::OnDeviceOpened,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&PepperPlatformCameraDevice::OnDeviceOpened,
+ weak_factory_.GetWeakPtr()));
pending_open_device_ = true;
}
}
@@ -46,7 +47,7 @@ void PepperPlatformCameraDevice::GetSupportedVideoCaptureFormats() {
RenderThreadImpl::current()->video_capture_impl_manager();
manager->GetDeviceSupportedFormats(
session_id_,
- media::BindToCurrentLoop(base::Bind(
+ media::BindToCurrentLoop(base::BindOnce(
&PepperPlatformCameraDevice::OnDeviceSupportedFormatsEnumerated,
weak_factory_.GetWeakPtr())));
}
@@ -54,8 +55,8 @@ void PepperPlatformCameraDevice::GetSupportedVideoCaptureFormats() {
void PepperPlatformCameraDevice::DetachEventHandler() {
DCHECK(thread_checker_.CalledOnValidThread());
handler_ = nullptr;
- if (!release_device_cb_.is_null()) {
- base::ResetAndReturn(&release_device_cb_).Run();
+ if (release_device_cb_) {
+ std::move(release_device_cb_).Run();
}
if (!label_.empty()) {
PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager();
@@ -74,7 +75,7 @@ void PepperPlatformCameraDevice::DetachEventHandler() {
PepperPlatformCameraDevice::~PepperPlatformCameraDevice() {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(release_device_cb_.is_null());
+ DCHECK(!release_device_cb_);
DCHECK(label_.empty());
DCHECK(!pending_open_device_);
}
diff --git a/chromium/content/renderer/pepper/pepper_platform_camera_device.h b/chromium/content/renderer/pepper/pepper_platform_camera_device.h
index 84975f34e57..938f5f52ce4 100644
--- a/chromium/content/renderer/pepper/pepper_platform_camera_device.h
+++ b/chromium/content/renderer/pepper/pepper_platform_camera_device.h
@@ -49,7 +49,7 @@ class PepperPlatformCameraDevice {
std::string label_;
int session_id_;
- base::Closure release_device_cb_;
+ base::OnceClosure release_device_cb_;
PepperCameraDeviceHost* handler_;
diff --git a/chromium/content/renderer/pepper/pepper_platform_video_capture.cc b/chromium/content/renderer/pepper/pepper_platform_video_capture.cc
index 3d65ff76fb3..f0bd2503b1f 100644
--- a/chromium/content/renderer/pepper/pepper_platform_video_capture.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_video_capture.cc
@@ -34,8 +34,8 @@ PepperPlatformVideoCapture::PepperPlatformVideoCapture(
if (device_manager) {
pending_open_device_id_ = device_manager->OpenDevice(
PP_DEVICETYPE_DEV_VIDEOCAPTURE, device_id, handler->pp_instance(),
- base::Bind(&PepperPlatformVideoCapture::OnDeviceOpened,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&PepperPlatformVideoCapture::OnDeviceOpened,
+ weak_factory_.GetWeakPtr()));
pending_open_device_ = true;
}
}
@@ -43,35 +43,32 @@ PepperPlatformVideoCapture::PepperPlatformVideoCapture(
void PepperPlatformVideoCapture::StartCapture(
const media::VideoCaptureParams& params) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (!stop_capture_cb_.is_null())
+ if (stop_capture_cb_)
return;
VideoCaptureImplManager* manager =
RenderThreadImpl::current()->video_capture_impl_manager();
stop_capture_cb_ =
- manager->StartCapture(session_id_,
- params,
- media::BindToCurrentLoop(base::Bind(
+ manager->StartCapture(session_id_, params,
+ media::BindToCurrentLoop(base::BindRepeating(
&PepperPlatformVideoCapture::OnStateUpdate,
weak_factory_.GetWeakPtr())),
- media::BindToCurrentLoop(base::Bind(
+ media::BindToCurrentLoop(base::BindRepeating(
&PepperPlatformVideoCapture::OnFrameReady,
weak_factory_.GetWeakPtr())));
}
void PepperPlatformVideoCapture::StopCapture() {
DCHECK(thread_checker_.CalledOnValidThread());
- if (stop_capture_cb_.is_null())
+ if (!stop_capture_cb_)
return;
- stop_capture_cb_.Run();
- stop_capture_cb_.Reset();
+ std::move(stop_capture_cb_).Run();
}
void PepperPlatformVideoCapture::DetachEventHandler() {
handler_ = nullptr;
StopCapture();
- if (!release_device_cb_.is_null()) {
- release_device_cb_.Run();
- release_device_cb_.Reset();
+ if (release_device_cb_) {
+ std::move(release_device_cb_).Run();
}
if (!label_.empty()) {
PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager();
@@ -89,8 +86,8 @@ void PepperPlatformVideoCapture::DetachEventHandler() {
}
PepperPlatformVideoCapture::~PepperPlatformVideoCapture() {
- DCHECK(stop_capture_cb_.is_null());
- DCHECK(release_device_cb_.is_null());
+ DCHECK(!stop_capture_cb_);
+ DCHECK(!release_device_cb_);
DCHECK(label_.empty());
DCHECK(!pending_open_device_);
}
@@ -138,10 +135,10 @@ void PepperPlatformVideoCapture::OnStateUpdate(blink::VideoCaptureState state) {
}
void PepperPlatformVideoCapture::OnFrameReady(
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
base::TimeTicks estimated_capture_time) {
- if (handler_ && !stop_capture_cb_.is_null())
- handler_->OnFrameReady(frame);
+ if (handler_ && stop_capture_cb_)
+ handler_->OnFrameReady(*frame);
}
PepperMediaDeviceManager* PepperPlatformVideoCapture::GetMediaDeviceManager() {
diff --git a/chromium/content/renderer/pepper/pepper_platform_video_capture.h b/chromium/content/renderer/pepper/pepper_platform_video_capture.h
index f21937ddc97..46ac124e5a6 100644
--- a/chromium/content/renderer/pepper/pepper_platform_video_capture.h
+++ b/chromium/content/renderer/pepper/pepper_platform_video_capture.h
@@ -42,7 +42,7 @@ class PepperPlatformVideoCapture {
private:
void OnDeviceOpened(int request_id, bool succeeded, const std::string& label);
void OnStateUpdate(blink::VideoCaptureState state);
- void OnFrameReady(const scoped_refptr<media::VideoFrame>& frame,
+ void OnFrameReady(scoped_refptr<media::VideoFrame> frame,
base::TimeTicks estimated_capture_time);
// Can return NULL if the RenderFrame referenced by |render_frame_id_| has
@@ -54,8 +54,8 @@ class PepperPlatformVideoCapture {
std::string label_;
int session_id_;
- base::Closure release_device_cb_;
- base::Closure stop_capture_cb_;
+ base::OnceClosure release_device_cb_;
+ base::OnceClosure stop_capture_cb_;
PepperVideoCaptureHost* handler_;
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 0a40786b548..03ae76357fe 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -400,8 +400,8 @@ PepperPluginInstanceImpl* PepperPluginInstanceImpl::Create(
PluginModule* module,
WebPluginContainer* container,
const GURL& plugin_url) {
- base::Callback<const void*(const char*)> get_plugin_interface_func =
- base::Bind(&PluginModule::GetPluginInterface, module);
+ base::RepeatingCallback<const void*(const char*)> get_plugin_interface_func =
+ base::BindRepeating(&PluginModule::GetPluginInterface, module);
PPP_Instance_Combined* ppp_instance_combined =
PPP_Instance_Combined::Create(std::move(get_plugin_interface_func));
if (!ppp_instance_combined)
@@ -1182,11 +1182,16 @@ bool PepperPluginInstanceImpl::HandleInputEvent(
// gesture after processing has finished here.
if (WebUserGestureIndicator::IsProcessingUserGesture(
render_frame_->GetWebFrame())) {
- pending_user_gesture_ =
- ppapi::TimeTicksToPPTimeTicks(base::TimeTicks::Now());
- pending_user_gesture_token_ =
+ auto user_gesture_token =
WebUserGestureIndicator::CurrentUserGestureToken();
- WebUserGestureIndicator::ExtendTimeout();
+ // Checking user_gesture_token.HasGestures() to make sure we are
+ // processing user geasture.
+ if (user_gesture_token.HasGestures()) {
+ pending_user_gesture_ =
+ ppapi::TimeTicksToPPTimeTicks(base::TimeTicks::Now());
+ pending_user_gesture_token_ = user_gesture_token;
+ WebUserGestureIndicator::ExtendTimeout();
+ }
}
// Each input event may generate more than one PP_InputEvent.
@@ -2685,6 +2690,7 @@ ppapi::Resource* PepperPluginInstanceImpl::GetSingletonResource(
case ppapi::ISOLATED_FILESYSTEM_SINGLETON_ID:
case ppapi::NETWORK_PROXY_SINGLETON_ID:
case ppapi::PDF_SINGLETON_ID:
+ case ppapi::TRUETYPE_FONT_SINGLETON_ID:
NOTIMPLEMENTED();
return nullptr;
case ppapi::GAMEPAD_SINGLETON_ID:
@@ -2950,8 +2956,8 @@ PP_ExternalPluginResult PepperPluginInstanceImpl::ResetAsProxied(
// can shut it down by calling its DidDestroy in our Delete() method.
original_instance_interface_ = std::move(instance_interface_);
- base::Callback<const void*(const char*)> get_plugin_interface_func =
- base::Bind(&PluginModule::GetPluginInterface, module_);
+ base::RepeatingCallback<const void*(const char*)> get_plugin_interface_func =
+ base::BindRepeating(&PluginModule::GetPluginInterface, module_);
PPP_Instance_Combined* ppp_instance_combined =
PPP_Instance_Combined::Create(std::move(get_plugin_interface_func));
if (!ppp_instance_combined) {
diff --git a/chromium/content/renderer/pepper/pepper_video_capture_host.cc b/chromium/content/renderer/pepper/pepper_video_capture_host.cc
index 248f8a2ab6e..0a84c54a182 100644
--- a/chromium/content/renderer/pepper/pepper_video_capture_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_capture_host.cc
@@ -120,16 +120,13 @@ void PepperVideoCaptureHost::PostErrorReply() {
static_cast<uint32_t>(PP_ERROR_FAILED)));
}
-void PepperVideoCaptureHost::OnFrameReady(
- const scoped_refptr<media::VideoFrame>& frame) {
- DCHECK(frame.get());
-
- if (alloc_size_ != frame->visible_rect().size() || buffers_.empty()) {
- alloc_size_ = frame->visible_rect().size();
+void PepperVideoCaptureHost::OnFrameReady(const media::VideoFrame& frame) {
+ if (alloc_size_ != frame.visible_rect().size() || buffers_.empty()) {
+ alloc_size_ = frame.visible_rect().size();
double frame_rate;
int rounded_frame_rate;
- if (frame->metadata()->GetDouble(media::VideoFrameMetadata::FRAME_RATE,
- &frame_rate))
+ if (frame.metadata()->GetDouble(media::VideoFrameMetadata::FRAME_RATE,
+ &frame_rate))
rounded_frame_rate = static_cast<int>(frame_rate + 0.5 /* round */);
else
rounded_frame_rate = blink::MediaStreamVideoSource::kUnknownFrameRate;
@@ -138,9 +135,9 @@ void PepperVideoCaptureHost::OnFrameReady(
for (uint32_t i = 0; i < buffers_.size(); ++i) {
if (!buffers_[i].in_use) {
- DCHECK_EQ(frame->format(), media::PIXEL_FORMAT_I420);
+ DCHECK_EQ(frame.format(), media::PIXEL_FORMAT_I420);
if (buffers_[i].buffer->size() <
- media::VideoFrame::AllocationSize(frame->format(), alloc_size_)) {
+ media::VideoFrame::AllocationSize(frame.format(), alloc_size_)) {
// TODO(ihf): handle size mismatches gracefully here.
return;
}
@@ -148,12 +145,12 @@ void PepperVideoCaptureHost::OnFrameReady(
static_assert(media::VideoFrame::kYPlane == 0, "y plane should be 0");
static_assert(media::VideoFrame::kUPlane == 1, "u plane should be 1");
static_assert(media::VideoFrame::kVPlane == 2, "v plane should be 2");
- for (size_t j = 0; j < media::VideoFrame::NumPlanes(frame->format());
+ for (size_t j = 0; j < media::VideoFrame::NumPlanes(frame.format());
++j) {
- const uint8_t* src = frame->visible_data(j);
- const size_t row_bytes = frame->row_bytes(j);
- const size_t src_stride = frame->stride(j);
- for (int k = 0; k < frame->rows(j); ++k) {
+ const uint8_t* src = frame.visible_data(j);
+ const size_t row_bytes = frame.row_bytes(j);
+ const size_t src_stride = frame.stride(j);
+ for (int k = 0; k < frame.rows(j); ++k) {
memcpy(dst, src, row_bytes);
dst += row_bytes;
src += src_stride;
diff --git a/chromium/content/renderer/pepper/pepper_video_capture_host.h b/chromium/content/renderer/pepper/pepper_video_capture_host.h
index 0efb69cc4ba..17e16c60186 100644
--- a/chromium/content/renderer/pepper/pepper_video_capture_host.h
+++ b/chromium/content/renderer/pepper/pepper_video_capture_host.h
@@ -64,7 +64,7 @@ class PepperVideoCaptureHost : public ppapi::host::ResourceHost {
void OnError();
// Called when a video frame is ready.
- void OnFrameReady(const scoped_refptr<media::VideoFrame>& frame);
+ void OnFrameReady(const media::VideoFrame& frame);
private:
int32_t OnOpen(ppapi::host::HostMessageContext* context,
diff --git a/chromium/content/renderer/pepper/pepper_video_decoder_host.cc b/chromium/content/renderer/pepper/pepper_video_decoder_host.cc
index fa05ef99613..44c5f661cd0 100644
--- a/chromium/content/renderer/pepper/pepper_video_decoder_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_decoder_host.cc
@@ -248,8 +248,11 @@ int32_t PepperVideoDecoderHost::OnHostMsgDecode(
context->MakeReplyMessageContext()));
shm_buffer_busy_[shm_id] = true;
- decoder_->Decode(
- media::BitstreamBuffer(decode_id, shm_buffers_[shm_id]->handle(), size));
+ // TODO(crbug.com/844456): The decode buffer should probably be read-only, but
+ // then shm_buffers_ will need to be refactored to use a
+ // ReadOnlySharedMemoryRegion with an associated writable mapping.
+ decoder_->Decode(media::BitstreamBuffer(
+ decode_id, shm_buffers_[shm_id]->handle(), false /* read_only */, size));
return PP_OK_COMPLETIONPENDING;
}
@@ -545,8 +548,11 @@ bool PepperVideoDecoderHost::TryFallbackToSoftwareDecoder() {
// Resubmit all pending decodes.
for (const PendingDecode& decode : pending_decodes_) {
DCHECK(shm_buffer_busy_[decode.shm_id]);
+ // TODO(crbug.com/844456): As with OnHostMsgDecode, the decode buffer should
+ // probably be read-only (see the todo there for more details).
decoder_->Decode(media::BitstreamBuffer(
- decode.decode_id, shm_buffers_[decode.shm_id]->handle(), decode.size));
+ decode.decode_id, shm_buffers_[decode.shm_id]->handle(),
+ false /* read_only */, decode.size));
}
// Flush the new decoder if Flush() was pending.
diff --git a/chromium/content/renderer/pepper/pepper_video_encoder_host.cc b/chromium/content/renderer/pepper/pepper_video_encoder_host.cc
index d17fd7607b2..350dcf45b43 100644
--- a/chromium/content/renderer/pepper/pepper_video_encoder_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_encoder_host.cc
@@ -168,7 +168,8 @@ PepperVideoEncoderHost::ShmBuffer::ShmBuffer(
PepperVideoEncoderHost::ShmBuffer::~ShmBuffer() {}
media::BitstreamBuffer PepperVideoEncoderHost::ShmBuffer::ToBitstreamBuffer() {
- return media::BitstreamBuffer(id, shm->handle(), shm->mapped_size());
+ return media::BitstreamBuffer(id, shm->handle(), false /* read_only */,
+ shm->mapped_size());
}
PepperVideoEncoderHost::PepperVideoEncoderHost(RendererPpapiHost* host,
diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
index 8ce7bdc0d89..f5d60db2f04 100644
--- a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
@@ -330,9 +330,9 @@ bool PepperWebPluginImpl::ExecuteEditCommand(const blink::WebString& name,
markup = instance_->GetSelectedText(true);
text = instance_->GetSelectedText(false);
}
- clipboard_->WriteHtml(ui::CLIPBOARD_TYPE_COPY_PASTE, markup, GURL());
- clipboard_->WriteText(ui::CLIPBOARD_TYPE_COPY_PASTE, text);
- clipboard_->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ clipboard_->WriteHtml(markup, GURL());
+ clipboard_->WriteText(text);
+ clipboard_->CommitWrite();
instance_->ReplaceSelection("");
return true;
diff --git a/chromium/content/renderer/pepper/plugin_instance_throttler_impl.cc b/chromium/content/renderer/pepper/plugin_instance_throttler_impl.cc
index 961d0b2a680..1720f22b824 100644
--- a/chromium/content/renderer/pepper/plugin_instance_throttler_impl.cc
+++ b/chromium/content/renderer/pepper/plugin_instance_throttler_impl.cc
@@ -171,8 +171,9 @@ void PluginInstanceThrottlerImpl::Initialize(
// is disabled.
frame->RegisterPeripheralPlugin(
content_origin,
- base::Bind(&PluginInstanceThrottlerImpl::MarkPluginEssential,
- weak_factory_.GetWeakPtr(), UNTHROTTLE_METHOD_BY_WHITELIST));
+ base::BindOnce(&PluginInstanceThrottlerImpl::MarkPluginEssential,
+ weak_factory_.GetWeakPtr(),
+ UNTHROTTLE_METHOD_BY_WHITELIST));
}
}
diff --git a/chromium/content/renderer/pepper/plugin_module.cc b/chromium/content/renderer/pepper/plugin_module.cc
index ac907cf3363..ebabd9beb57 100644
--- a/chromium/content/renderer/pepper/plugin_module.cc
+++ b/chromium/content/renderer/pepper/plugin_module.cc
@@ -50,6 +50,7 @@
#include "ppapi/c/dev/ppb_printing_dev.h"
#include "ppapi/c/dev/ppb_text_input_dev.h"
#include "ppapi/c/dev/ppb_trace_event_dev.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
#include "ppapi/c/dev/ppb_url_util_dev.h"
#include "ppapi/c/dev/ppb_var_deprecated.h"
#include "ppapi/c/dev/ppb_video_capture_dev.h"
diff --git a/chromium/content/renderer/pepper/plugin_object.cc b/chromium/content/renderer/pepper/plugin_object.cc
index 71e4a9bb976..35001d166bc 100644
--- a/chromium/content/renderer/pepper/plugin_object.cc
+++ b/chromium/content/renderer/pepper/plugin_object.cc
@@ -299,10 +299,9 @@ v8::Local<v8::FunctionTemplate> PluginObject::GetFunctionTemplate(
v8::Local<v8::FunctionTemplate> function_template = template_cache_.Get(name);
if (!function_template.IsEmpty())
return function_template;
- function_template =
- gin::CreateFunctionTemplate(
- isolate, base::Bind(&PluginObject::Call, weak_factory_.GetWeakPtr(),
- name));
+ function_template = gin::CreateFunctionTemplate(
+ isolate, base::BindRepeating(&PluginObject::Call,
+ weak_factory_.GetWeakPtr(), name));
template_cache_.Set(name, function_template);
return function_template;
}
diff --git a/chromium/content/renderer/pepper/plugin_power_saver_helper.cc b/chromium/content/renderer/pepper/plugin_power_saver_helper.cc
index 7b5c4db65f4..fe35e53c303 100644
--- a/chromium/content/renderer/pepper/plugin_power_saver_helper.cc
+++ b/chromium/content/renderer/pepper/plugin_power_saver_helper.cc
@@ -31,15 +31,17 @@ const char kPeripheralHeuristicHistogram[] =
PluginPowerSaverHelper::PeripheralPlugin::PeripheralPlugin(
const url::Origin& content_origin,
- const base::Closure& unthrottle_callback)
+ base::OnceClosure unthrottle_callback)
: content_origin(content_origin),
- unthrottle_callback(unthrottle_callback) {}
+ unthrottle_callback(std::move(unthrottle_callback)) {}
-PluginPowerSaverHelper::PeripheralPlugin::PeripheralPlugin(
- const PeripheralPlugin& other) = default;
+PluginPowerSaverHelper::PeripheralPlugin::~PeripheralPlugin() = default;
-PluginPowerSaverHelper::PeripheralPlugin::~PeripheralPlugin() {
-}
+PluginPowerSaverHelper::PeripheralPlugin::PeripheralPlugin(PeripheralPlugin&&) =
+ default;
+PluginPowerSaverHelper::PeripheralPlugin&
+PluginPowerSaverHelper::PeripheralPlugin::operator=(PeripheralPlugin&&) =
+ default;
PluginPowerSaverHelper::PluginPowerSaverHelper(RenderFrame* render_frame)
: RenderFrameObserver(render_frame) {}
@@ -82,8 +84,9 @@ void PluginPowerSaverHelper::OnUpdatePluginContentOriginWhitelist(
if (origin_whitelist.count(it->content_origin)) {
// Because the unthrottle callback may register another peripheral plugin
// and invalidate our iterator, we cannot run it synchronously.
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- it->unthrottle_callback);
+ render_frame()
+ ->GetTaskRunner(blink::TaskType::kInternalDefault)
+ ->PostTask(FROM_HERE, std::move(it->unthrottle_callback));
it = peripheral_plugins_.erase(it);
} else {
++it;
@@ -93,9 +96,9 @@ void PluginPowerSaverHelper::OnUpdatePluginContentOriginWhitelist(
void PluginPowerSaverHelper::RegisterPeripheralPlugin(
const url::Origin& content_origin,
- const base::Closure& unthrottle_callback) {
+ base::OnceClosure unthrottle_callback) {
peripheral_plugins_.push_back(
- PeripheralPlugin(content_origin, unthrottle_callback));
+ PeripheralPlugin(content_origin, std::move(unthrottle_callback)));
}
RenderFrame::PeripheralContentStatus
diff --git a/chromium/content/renderer/pepper/plugin_power_saver_helper.h b/chromium/content/renderer/pepper/plugin_power_saver_helper.h
index e178201b826..ba682b0a501 100644
--- a/chromium/content/renderer/pepper/plugin_power_saver_helper.h
+++ b/chromium/content/renderer/pepper/plugin_power_saver_helper.h
@@ -31,17 +31,19 @@ class CONTENT_EXPORT PluginPowerSaverHelper : public RenderFrameObserver {
struct PeripheralPlugin {
PeripheralPlugin(const url::Origin& content_origin,
- const base::Closure& unthrottle_callback);
- PeripheralPlugin(const PeripheralPlugin& other);
+ base::OnceClosure unthrottle_callback);
~PeripheralPlugin();
+ PeripheralPlugin(PeripheralPlugin&&);
+ PeripheralPlugin& operator=(PeripheralPlugin&&);
+
url::Origin content_origin;
- base::Closure unthrottle_callback;
+ base::OnceClosure unthrottle_callback;
};
// See RenderFrame for documentation.
void RegisterPeripheralPlugin(const url::Origin& content_origin,
- const base::Closure& unthrottle_callback);
+ base::OnceClosure unthrottle_callback);
RenderFrame::PeripheralContentStatus GetPeripheralContentStatus(
const url::Origin& main_frame_origin,
const url::Origin& content_origin,
diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
index 85a1162ac72..ef2861a9acf 100644
--- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -186,10 +186,9 @@ int32_t PPB_Graphics3D_Impl::DoSwapBuffers(const gpu::SyncToken& sync_token,
if (use_image_chromium_)
target = GL_TEXTURE_RECTANGLE_ARB;
#endif
- viz::TransferableResource resource =
- viz::TransferableResource::MakeGLOverlay(taken_front_buffer_, GL_LINEAR,
- target, sync_token, size,
- is_overlay_candidate);
+ viz::TransferableResource resource = viz::TransferableResource::MakeGL(
+ taken_front_buffer_, GL_LINEAR, target, sync_token, size,
+ is_overlay_candidate);
HostGlobals::Get()
->GetInstance(pp_instance())
->CommitTransferableResource(resource);
diff --git a/chromium/content/renderer/pepper/ppb_image_data_impl.cc b/chromium/content/renderer/pepper/ppb_image_data_impl.cc
index fa2b937dd1d..00119aeb7bd 100644
--- a/chromium/content/renderer/pepper/ppb_image_data_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_image_data_impl.cc
@@ -12,6 +12,7 @@
#include "content/common/pepper_file_util.h"
#include "content/common/view_messages.h"
#include "content/renderer/render_thread_impl.h"
+#include "mojo/public/cpp/base/shared_memory_utils.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_resource.h"
@@ -107,9 +108,9 @@ void* PPB_ImageData_Impl::Map() { return backend_->Map(); }
void PPB_ImageData_Impl::Unmap() { backend_->Unmap(); }
-int32_t PPB_ImageData_Impl::GetSharedMemory(base::SharedMemory** shm,
- uint32_t* byte_count) {
- return backend_->GetSharedMemory(shm, byte_count);
+int32_t PPB_ImageData_Impl::GetSharedMemoryRegion(
+ base::UnsafeSharedMemoryRegion** region) {
+ return backend_->GetSharedMemoryRegion(region);
}
SkCanvas* PPB_ImageData_Impl::GetCanvas() { return backend_->GetCanvas(); }
@@ -135,25 +136,16 @@ bool ImageDataPlatformBackend::Init(PPB_ImageData_Impl* impl,
int width,
int height,
bool init_to_zero) {
- // TODO(brettw) use init_to_zero when we implement caching.
+ // TODO(brettw): use init_to_zero when we implement caching.
width_ = width;
height_ = height;
uint32_t buffer_size = width_ * height_ * 4;
- std::unique_ptr<base::SharedMemory> shared_memory =
- RenderThread::Get()->HostAllocateSharedMemoryBuffer(buffer_size);
- if (!shared_memory)
+ base::UnsafeSharedMemoryRegion region =
+ mojo::CreateUnsafeSharedMemoryRegion(buffer_size);
+ if (!region.IsValid())
return false;
- // The TransportDIB is always backed by shared memory, so give the shared
- // memory handle to it.
- base::SharedMemoryHandle handle = shared_memory->handle().Duplicate();
- shared_memory->Unmap();
- shared_memory->Close();
- if (!handle.IsValid())
- return false;
-
- dib_.reset(TransportDIB::CreateWithHandle(handle));
-
+ dib_ = TransportDIB::CreateWithHandle(std::move(region));
return !!dib_;
}
@@ -188,10 +180,9 @@ void ImageDataPlatformBackend::Unmap() {
// in the future to save some memory.
}
-int32_t ImageDataPlatformBackend::GetSharedMemory(base::SharedMemory** shm,
- uint32_t* byte_count) {
- *byte_count = dib_->size();
- *shm = dib_->shared_memory();
+int32_t ImageDataPlatformBackend::GetSharedMemoryRegion(
+ base::UnsafeSharedMemoryRegion** region) {
+ *region = dib_->shared_memory_region();
return PP_OK;
}
@@ -224,41 +215,42 @@ bool ImageDataSimpleBackend::Init(PPB_ImageData_Impl* impl,
bool init_to_zero) {
skia_bitmap_.setInfo(
SkImageInfo::MakeN32Premul(impl->width(), impl->height()));
- shared_memory_.reset(
- RenderThread::Get()
- ->HostAllocateSharedMemoryBuffer(skia_bitmap_.computeByteSize())
- .release());
- return !!shared_memory_.get();
+ shm_region_ =
+ mojo::CreateUnsafeSharedMemoryRegion(skia_bitmap_.computeByteSize());
+ return shm_region_.IsValid();
}
-bool ImageDataSimpleBackend::IsMapped() const { return map_count_ > 0; }
+bool ImageDataSimpleBackend::IsMapped() const {
+ return shm_mapping_.IsValid();
+}
TransportDIB* ImageDataSimpleBackend::GetTransportDIB() const {
return nullptr;
}
void* ImageDataSimpleBackend::Map() {
- DCHECK(shared_memory_.get());
+ DCHECK(shm_region_.IsValid());
if (map_count_++ == 0) {
- shared_memory_->Map(skia_bitmap_.computeByteSize());
- skia_bitmap_.setPixels(shared_memory_->memory());
+ shm_mapping_ = shm_region_.Map();
+ if (!shm_mapping_.IsValid())
+ return nullptr;
+
+ skia_bitmap_.setPixels(shm_mapping_.memory());
// Our platform bitmaps are set to opaque by default, which we don't want.
skia_bitmap_.setAlphaType(kPremul_SkAlphaType);
skia_canvas_ = std::make_unique<SkCanvas>(skia_bitmap_);
- return skia_bitmap_.getAddr32(0, 0);
}
- return shared_memory_->memory();
+ return skia_bitmap_.isNull() ? nullptr : skia_bitmap_.getAddr32(0, 0);
}
void ImageDataSimpleBackend::Unmap() {
if (--map_count_ == 0)
- shared_memory_->Unmap();
+ shm_mapping_ = base::WritableSharedMemoryMapping();
}
-int32_t ImageDataSimpleBackend::GetSharedMemory(base::SharedMemory** shm,
- uint32_t* byte_count) {
- *byte_count = skia_bitmap_.computeByteSize();
- *shm = shared_memory_.get();
+int32_t ImageDataSimpleBackend::GetSharedMemoryRegion(
+ base::UnsafeSharedMemoryRegion** region) {
+ *region = &shm_region_;
return PP_OK;
}
diff --git a/chromium/content/renderer/pepper/ppb_image_data_impl.h b/chromium/content/renderer/pepper/ppb_image_data_impl.h
index 757ec17667b..edaeeab34fc 100644
--- a/chromium/content/renderer/pepper/ppb_image_data_impl.h
+++ b/chromium/content/renderer/pepper/ppb_image_data_impl.h
@@ -10,7 +10,8 @@
#include <memory>
#include "base/macros.h"
-#include "base/memory/shared_memory.h"
+#include "base/memory/shared_memory_mapping.h"
+#include "base/memory/unsafe_shared_memory_region.h"
#include "content/common/content_export.h"
#include "ppapi/c/ppb_image_data.h"
#include "ppapi/shared_impl/ppb_image_data_shared.h"
@@ -21,10 +22,6 @@
class SkCanvas;
class TransportDIB;
-namespace base {
-class SharedMemory;
-}
-
namespace content {
class CONTENT_EXPORT PPB_ImageData_Impl
@@ -48,8 +45,8 @@ class CONTENT_EXPORT PPB_ImageData_Impl
virtual TransportDIB* GetTransportDIB() const = 0;
virtual void* Map() = 0;
virtual void Unmap() = 0;
- virtual int32_t GetSharedMemory(base::SharedMemory** shm,
- uint32_t* byte_count) = 0;
+ virtual int32_t GetSharedMemoryRegion(
+ base::UnsafeSharedMemoryRegion** region) = 0;
virtual SkCanvas* GetCanvas() = 0;
virtual SkBitmap GetMappedBitmap() const = 0;
};
@@ -93,8 +90,8 @@ class CONTENT_EXPORT PPB_ImageData_Impl
PP_Bool Describe(PP_ImageDataDesc* desc) override;
void* Map() override;
void Unmap() override;
- int32_t GetSharedMemory(base::SharedMemory** shm,
- uint32_t* byte_count) override;
+ int32_t GetSharedMemoryRegion(
+ base::UnsafeSharedMemoryRegion** region) override;
SkCanvas* GetCanvas() override;
void SetIsCandidateForReuse() override;
@@ -132,8 +129,8 @@ class ImageDataPlatformBackend : public PPB_ImageData_Impl::Backend {
TransportDIB* GetTransportDIB() const override;
void* Map() override;
void Unmap() override;
- int32_t GetSharedMemory(base::SharedMemory** shm,
- uint32_t* byte_count) override;
+ int32_t GetSharedMemoryRegion(
+ base::UnsafeSharedMemoryRegion** region) override;
SkCanvas* GetCanvas() override;
SkBitmap GetMappedBitmap() const override;
@@ -165,13 +162,14 @@ class ImageDataSimpleBackend : public PPB_ImageData_Impl::Backend {
TransportDIB* GetTransportDIB() const override;
void* Map() override;
void Unmap() override;
- int32_t GetSharedMemory(base::SharedMemory** shm,
- uint32_t* byte_count) override;
+ int32_t GetSharedMemoryRegion(
+ base::UnsafeSharedMemoryRegion** region) override;
SkCanvas* GetCanvas() override;
SkBitmap GetMappedBitmap() const override;
private:
- std::unique_ptr<base::SharedMemory> shared_memory_;
+ base::UnsafeSharedMemoryRegion shm_region_;
+ base::WritableSharedMemoryMapping shm_mapping_;
// skia_bitmap_ is backed by shared_memory_.
SkBitmap skia_bitmap_;
std::unique_ptr<SkCanvas> skia_canvas_;
diff --git a/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc b/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
index fd2f082da60..bc85f004009 100644
--- a/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
@@ -162,14 +162,16 @@ int32_t PPB_VideoDecoder_Impl::Decode(
PPB_Buffer_Impl* buffer = static_cast<PPB_Buffer_Impl*>(enter.object());
DCHECK_GE(bitstream_buffer->id, 0);
- media::BitstreamBuffer decode_buffer(bitstream_buffer->id,
- buffer->shared_memory()->handle(),
- bitstream_buffer->size);
+ // TODO(crbug.com/844456): The shared memory buffer probably can be read-only,
+ // but only after PPB_Buffer_Impl is updated to deal with that.
+ media::BitstreamBuffer decode_buffer(
+ bitstream_buffer->id, buffer->shared_memory()->handle(),
+ false /* read_only */, bitstream_buffer->size);
if (!SetBitstreamBufferCallback(bitstream_buffer->id, callback))
return PP_ERROR_BADARGUMENT;
FlushCommandBuffer();
- decoder_->Decode(decode_buffer);
+ decoder_->Decode(std::move(decode_buffer));
return PP_OK_COMPLETIONPENDING;
}
diff --git a/chromium/content/renderer/pepper/resource_converter.cc b/chromium/content/renderer/pepper/resource_converter.cc
index e97b9afb726..cb4e045e6cd 100644
--- a/chromium/content/renderer/pepper/resource_converter.cc
+++ b/chromium/content/renderer/pepper/resource_converter.cc
@@ -32,14 +32,14 @@ namespace content {
namespace {
void FlushComplete(
- const base::Callback<void(bool)>& callback,
- const std::vector<scoped_refptr<content::HostResourceVar> >& browser_vars,
+ base::OnceCallback<void(bool)> callback,
+ const std::vector<scoped_refptr<content::HostResourceVar>>& browser_vars,
const std::vector<int>& pending_host_ids) {
CHECK(browser_vars.size() == pending_host_ids.size());
for (size_t i = 0; i < browser_vars.size(); ++i) {
browser_vars[i]->set_pending_browser_host_id(pending_host_ids[i]);
}
- callback.Run(true);
+ std::move(callback).Run(true);
}
PP_FileSystemType WebFileSystemTypeToPPAPI(blink::WebFileSystemType type) {
@@ -272,11 +272,10 @@ bool ResourceConverterImpl::NeedsFlush() {
return !browser_host_create_messages_.empty();
}
-void ResourceConverterImpl::Flush(const base::Callback<void(bool)>& callback) {
+void ResourceConverterImpl::Flush(base::OnceCallback<void(bool)> callback) {
RendererPpapiHost::GetForPPInstance(instance_)->CreateBrowserResourceHosts(
- instance_,
- browser_host_create_messages_,
- base::Bind(&FlushComplete, callback, browser_vars_));
+ instance_, browser_host_create_messages_,
+ base::BindOnce(&FlushComplete, std::move(callback), browser_vars_));
browser_host_create_messages_.clear();
browser_vars_.clear();
}
diff --git a/chromium/content/renderer/pepper/resource_converter.h b/chromium/content/renderer/pepper/resource_converter.h
index 68f18d5e764..012b750d289 100644
--- a/chromium/content/renderer/pepper/resource_converter.h
+++ b/chromium/content/renderer/pepper/resource_converter.h
@@ -38,7 +38,7 @@ class CONTENT_EXPORT ResourceConverter {
// If NeedsFlush() is true then Flush() must be called before any vars created
// by the ResourceConverter are valid. It handles creating any resource hosts
// that need to be created. |callback| will always be called asynchronously.
- virtual void Flush(const base::Callback<void(bool)>& callback) = 0;
+ virtual void Flush(base::OnceCallback<void(bool)> callback) = 0;
// Attempts to convert a V8 object to a PP_Var with type PP_VARTYPE_RESOURCE.
// On success, writes the resulting var to |result|, sets |was_resource| to
@@ -65,7 +65,7 @@ class ResourceConverterImpl : public ResourceConverter {
// ResourceConverter overrides.
void Reset() override;
bool NeedsFlush() override;
- void Flush(const base::Callback<void(bool)>& callback) override;
+ void Flush(base::OnceCallback<void(bool)> callback) override;
bool FromV8Value(v8::Local<v8::Object> val,
v8::Local<v8::Context> context,
PP_Var* result,
diff --git a/chromium/content/renderer/pepper/v8_var_converter.cc b/chromium/content/renderer/pepper/v8_var_converter.cc
index 55a5deae3be..97d125e3617 100644
--- a/chromium/content/renderer/pepper/v8_var_converter.cc
+++ b/chromium/content/renderer/pepper/v8_var_converter.cc
@@ -446,14 +446,14 @@ bool V8VarConverter::ToV8Value(const PP_Var& var,
V8VarConverter::VarResult V8VarConverter::FromV8Value(
v8::Local<v8::Value> val,
v8::Local<v8::Context> context,
- const base::Callback<void(const ScopedPPVar&, bool)>& callback) {
+ base::OnceCallback<void(const ScopedPPVar&, bool)> callback) {
VarResult result;
result.success = FromV8ValueInternal(val, context, &result.var);
if (!result.success)
resource_converter_->Reset();
result.completed_synchronously = !resource_converter_->NeedsFlush();
if (!result.completed_synchronously)
- resource_converter_->Flush(base::Bind(callback, result.var));
+ resource_converter_->Flush(base::BindOnce(std::move(callback), result.var));
return result;
}
diff --git a/chromium/content/renderer/pepper/v8_var_converter.h b/chromium/content/renderer/pepper/v8_var_converter.h
index 835a8e48209..6496df59913 100644
--- a/chromium/content/renderer/pepper/v8_var_converter.h
+++ b/chromium/content/renderer/pepper/v8_var_converter.h
@@ -69,7 +69,7 @@ class CONTENT_EXPORT V8VarConverter {
VarResult FromV8Value(
v8::Local<v8::Value> val,
v8::Local<v8::Context> context,
- const base::Callback<void(const ppapi::ScopedPPVar&, bool)>& callback);
+ base::OnceCallback<void(const ppapi::ScopedPPVar&, bool)> callback);
bool FromV8ValueSync(v8::Local<v8::Value> val,
v8::Local<v8::Context> context,
ppapi::ScopedPPVar* result_var);
diff --git a/chromium/content/renderer/pepper/v8_var_converter_unittest.cc b/chromium/content/renderer/pepper/v8_var_converter_unittest.cc
index 1f016c03f5f..5fe799bd27b 100644
--- a/chromium/content/renderer/pepper/v8_var_converter_unittest.cc
+++ b/chromium/content/renderer/pepper/v8_var_converter_unittest.cc
@@ -58,9 +58,7 @@ class MockResourceConverter : public content::ResourceConverter {
~MockResourceConverter() override {}
void Reset() override {}
bool NeedsFlush() override { return false; }
- void Flush(const base::Callback<void(bool)>& callback) override {
- NOTREACHED();
- }
+ void Flush(base::OnceCallback<void(bool)> callback) override { NOTREACHED(); }
bool FromV8Value(v8::Local<v8::Object> val,
v8::Local<v8::Context> context,
PP_Var* result,
@@ -199,10 +197,8 @@ class V8VarConverterTest : public testing::Test {
bool FromV8ValueSync(v8::Local<v8::Value> val,
v8::Local<v8::Context> context,
PP_Var* result) {
- V8VarConverter::VarResult conversion_result =
- converter_->FromV8Value(val,
- context,
- base::Bind(&FromV8ValueComplete));
+ V8VarConverter::VarResult conversion_result = converter_->FromV8Value(
+ val, context, base::BindOnce(&FromV8ValueComplete));
DCHECK(conversion_result.completed_synchronously);
if (conversion_result.success)
*result = conversion_result.var.Release();
diff --git a/chromium/content/renderer/pepper/video_decoder_shim.cc b/chromium/content/renderer/pepper/video_decoder_shim.cc
index c5c5d8ecc15..325fd13cbae 100644
--- a/chromium/content/renderer/pepper/video_decoder_shim.cc
+++ b/chromium/content/renderer/pepper/video_decoder_shim.cc
@@ -63,7 +63,7 @@ class VideoDecoderShim::YUVConverter {
YUVConverter(scoped_refptr<ws::ContextProviderCommandBuffer>);
~YUVConverter();
bool Initialize();
- void Convert(const scoped_refptr<media::VideoFrame>& frame, GLuint tex_out);
+ void Convert(const media::VideoFrame* frame, GLuint tex_out);
private:
GLuint CreateShader();
@@ -353,9 +353,8 @@ bool VideoDecoderShim::YUVConverter::Initialize() {
return (program_ != 0);
}
-void VideoDecoderShim::YUVConverter::Convert(
- const scoped_refptr<media::VideoFrame>& frame,
- GLuint tex_out) {
+void VideoDecoderShim::YUVConverter::Convert(const media::VideoFrame* frame,
+ GLuint tex_out) {
const float* yuv_matrix = nullptr;
const float* yuv_adjust = nullptr;
@@ -610,8 +609,7 @@ VideoDecoderShim::PendingDecode::~PendingDecode() {
struct VideoDecoderShim::PendingFrame {
explicit PendingFrame(uint32_t decode_id);
- PendingFrame(uint32_t decode_id,
- const scoped_refptr<media::VideoFrame>& frame);
+ PendingFrame(uint32_t decode_id, scoped_refptr<media::VideoFrame> frame);
~PendingFrame();
const uint32_t decode_id;
@@ -628,9 +626,8 @@ VideoDecoderShim::PendingFrame::PendingFrame(uint32_t decode_id)
VideoDecoderShim::PendingFrame::PendingFrame(
uint32_t decode_id,
- const scoped_refptr<media::VideoFrame>& frame)
- : decode_id(decode_id), video_frame(frame) {
-}
+ scoped_refptr<media::VideoFrame> frame)
+ : decode_id(decode_id), video_frame(std::move(frame)) {}
VideoDecoderShim::PendingFrame::~PendingFrame() {
}
@@ -653,7 +650,7 @@ class VideoDecoderShim::DecoderImpl {
void OnInitDone(bool success);
void DoDecode();
void OnDecodeComplete(media::DecodeStatus status);
- void OnOutputComplete(const scoped_refptr<media::VideoFrame>& frame);
+ void OnOutputComplete(scoped_refptr<media::VideoFrame> frame);
void OnResetComplete();
// WeakPtr is bound to main_message_loop_. Use only in shim callbacks.
@@ -709,10 +706,10 @@ void VideoDecoderShim::DecoderImpl::Initialize(
decoder_->Initialize(
config, true /* low_delay */, nullptr,
- base::Bind(&VideoDecoderShim::DecoderImpl::OnInitDone,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&VideoDecoderShim::DecoderImpl::OnOutputComplete,
- weak_ptr_factory_.GetWeakPtr()),
+ base::BindOnce(&VideoDecoderShim::DecoderImpl::OnInitDone,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::BindRepeating(&VideoDecoderShim::DecoderImpl::OnOutputComplete,
+ weak_ptr_factory_.GetWeakPtr()),
base::NullCallback());
#else
OnInitDone(false);
@@ -745,8 +742,9 @@ void VideoDecoderShim::DecoderImpl::Reset() {
return;
}
- decoder_->Reset(base::Bind(&VideoDecoderShim::DecoderImpl::OnResetComplete,
- weak_ptr_factory_.GetWeakPtr()));
+ decoder_->Reset(
+ base::BindOnce(&VideoDecoderShim::DecoderImpl::OnResetComplete,
+ weak_ptr_factory_.GetWeakPtr()));
}
void VideoDecoderShim::DecoderImpl::Stop() {
@@ -778,9 +776,10 @@ void VideoDecoderShim::DecoderImpl::DoDecode() {
awaiting_decoder_ = true;
const PendingDecode& decode = pending_decodes_.front();
decode_id_ = decode.decode_id;
- decoder_->Decode(decode.buffer,
- base::Bind(&VideoDecoderShim::DecoderImpl::OnDecodeComplete,
- weak_ptr_factory_.GetWeakPtr()));
+ decoder_->Decode(
+ decode.buffer,
+ base::BindOnce(&VideoDecoderShim::DecoderImpl::OnDecodeComplete,
+ weak_ptr_factory_.GetWeakPtr()));
pending_decodes_.pop();
}
@@ -808,14 +807,14 @@ void VideoDecoderShim::DecoderImpl::OnDecodeComplete(
}
void VideoDecoderShim::DecoderImpl::OnOutputComplete(
- const scoped_refptr<media::VideoFrame>& frame) {
+ scoped_refptr<media::VideoFrame> frame) {
// Software decoders are expected to generated frames only when a Decode()
// call is pending.
DCHECK(awaiting_decoder_);
std::unique_ptr<PendingFrame> pending_frame;
if (!frame->metadata()->IsTrue(media::VideoFrameMetadata::END_OF_STREAM))
- pending_frame.reset(new PendingFrame(decode_id_, frame));
+ pending_frame.reset(new PendingFrame(decode_id_, std::move(frame)));
else
pending_frame.reset(new PendingFrame(decode_id_));
@@ -894,7 +893,7 @@ bool VideoDecoderShim::Initialize(const Config& vda_config, Client* client) {
media::VideoDecoderConfig video_decoder_config(
codec, vda_config.profile, media::PIXEL_FORMAT_I420,
- media::VideoColorSpace(), media::VIDEO_ROTATION_0,
+ media::VideoColorSpace(), media::kNoTransformation,
gfx::Size(32, 24), // Small sizes that won't fail.
gfx::Rect(32, 24), gfx::Size(32, 24),
// TODO(bbudge): Verify extra data isn't needed.
@@ -912,7 +911,7 @@ bool VideoDecoderShim::Initialize(const Config& vda_config, Client* client) {
return true;
}
-void VideoDecoderShim::Decode(const media::BitstreamBuffer& bitstream_buffer) {
+void VideoDecoderShim::Decode(media::BitstreamBuffer bitstream_buffer) {
DCHECK(RenderThreadImpl::current());
DCHECK_EQ(state_, DECODING);
@@ -1056,7 +1055,7 @@ void VideoDecoderShim::SendPictures() {
uint32_t local_texture_id = texture_id_map_[texture_id];
- yuv_converter_->Convert(frame->video_frame, local_texture_id);
+ yuv_converter_->Convert(frame->video_frame.get(), local_texture_id);
host_->PictureReady(media::Picture(texture_id, frame->decode_id,
frame->video_frame->visible_rect(),
diff --git a/chromium/content/renderer/pepper/video_decoder_shim.h b/chromium/content/renderer/pepper/video_decoder_shim.h
index 7f1e824e793..99502fa43c2 100644
--- a/chromium/content/renderer/pepper/video_decoder_shim.h
+++ b/chromium/content/renderer/pepper/video_decoder_shim.h
@@ -42,7 +42,7 @@ class VideoDecoderShim : public media::VideoDecodeAccelerator {
// media::VideoDecodeAccelerator implementation.
bool Initialize(const Config& config, Client* client) override;
- void Decode(const media::BitstreamBuffer& bitstream_buffer) override;
+ void Decode(media::BitstreamBuffer bitstream_buffer) override;
void AssignPictureBuffers(
const std::vector<media::PictureBuffer>& buffers) override;
void ReusePictureBuffer(int32_t picture_buffer_id) override;
diff --git a/chromium/content/renderer/pepper/video_encoder_shim.cc b/chromium/content/renderer/pepper/video_encoder_shim.cc
index cfafc83ee9d..7474e001c39 100644
--- a/chromium/content/renderer/pepper/video_encoder_shim.cc
+++ b/chromium/content/renderer/pepper/video_encoder_shim.cc
@@ -98,18 +98,15 @@ class VideoEncoderShim::EncoderImpl {
~EncoderImpl();
void Initialize(const media::VideoEncodeAccelerator::Config& config);
- void Encode(const scoped_refptr<media::VideoFrame>& frame,
- bool force_keyframe);
- void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer,
- uint8_t* mem);
+ void Encode(scoped_refptr<media::VideoFrame> frame, bool force_keyframe);
+ void UseOutputBitstreamBuffer(media::BitstreamBuffer buffer, uint8_t* mem);
void RequestEncodingParametersChange(uint32_t bitrate, uint32_t framerate);
void Stop();
private:
struct PendingEncode {
- PendingEncode(const scoped_refptr<media::VideoFrame>& frame,
- bool force_keyframe)
- : frame(frame), force_keyframe(force_keyframe) {}
+ PendingEncode(scoped_refptr<media::VideoFrame> frame, bool force_keyframe)
+ : frame(std::move(frame)), force_keyframe(force_keyframe) {}
~PendingEncode() {}
scoped_refptr<media::VideoFrame> frame;
@@ -117,8 +114,9 @@ class VideoEncoderShim::EncoderImpl {
};
struct BitstreamBuffer {
- BitstreamBuffer(const media::BitstreamBuffer buffer, uint8_t* mem)
- : buffer(buffer), mem(mem) {}
+ BitstreamBuffer(media::BitstreamBuffer buffer, uint8_t* mem)
+ : buffer(std::move(buffer)), mem(mem) {}
+ BitstreamBuffer(BitstreamBuffer&&) = default;
~BitstreamBuffer() {}
media::BitstreamBuffer buffer;
@@ -238,16 +236,16 @@ void VideoEncoderShim::EncoderImpl::Initialize(const Config& config) {
}
void VideoEncoderShim::EncoderImpl::Encode(
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
bool force_keyframe) {
- frames_.push_back(PendingEncode(frame, force_keyframe));
+ frames_.push_back(PendingEncode(std::move(frame), force_keyframe));
DoEncode();
}
void VideoEncoderShim::EncoderImpl::UseOutputBitstreamBuffer(
- const media::BitstreamBuffer& buffer,
+ media::BitstreamBuffer buffer,
uint8_t* mem) {
- buffers_.push_back(BitstreamBuffer(buffer, mem));
+ buffers_.emplace_back(std::move(buffer), mem);
DoEncode();
}
@@ -322,7 +320,7 @@ void VideoEncoderShim::EncoderImpl::DoEncode() {
if (packet->kind != VPX_CODEC_CX_FRAME_PKT)
continue;
- BitstreamBuffer buffer = buffers_.front();
+ BitstreamBuffer buffer = std::move(buffers_.front());
buffers_.pop_front();
CHECK(buffer.buffer.size() >= packet->data.frame.sz);
@@ -417,24 +415,23 @@ bool VideoEncoderShim::Initialize(
return true;
}
-void VideoEncoderShim::Encode(const scoped_refptr<media::VideoFrame>& frame,
+void VideoEncoderShim::Encode(scoped_refptr<media::VideoFrame> frame,
bool force_keyframe) {
DCHECK(RenderThreadImpl::current());
media_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VideoEncoderShim::EncoderImpl::Encode,
- base::Unretained(encoder_impl_.get()), frame,
- force_keyframe));
+ base::Unretained(encoder_impl_.get()),
+ std::move(frame), force_keyframe));
}
-void VideoEncoderShim::UseOutputBitstreamBuffer(
- const media::BitstreamBuffer& buffer) {
+void VideoEncoderShim::UseOutputBitstreamBuffer(media::BitstreamBuffer buffer) {
DCHECK(RenderThreadImpl::current());
media_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VideoEncoderShim::EncoderImpl::UseOutputBitstreamBuffer,
- base::Unretained(encoder_impl_.get()), buffer,
+ base::Unretained(encoder_impl_.get()), std::move(buffer),
host_->ShmHandleToAddress(buffer.id())));
}
diff --git a/chromium/content/renderer/pepper/video_encoder_shim.h b/chromium/content/renderer/pepper/video_encoder_shim.h
index 771fa5ea3d3..6f717796cec 100644
--- a/chromium/content/renderer/pepper/video_encoder_shim.h
+++ b/chromium/content/renderer/pepper/video_encoder_shim.h
@@ -41,9 +41,9 @@ class VideoEncoderShim : public media::VideoEncodeAccelerator {
override;
bool Initialize(const media::VideoEncodeAccelerator::Config& config,
media::VideoEncodeAccelerator::Client* client) override;
- void Encode(const scoped_refptr<media::VideoFrame>& frame,
+ void Encode(scoped_refptr<media::VideoFrame> frame,
bool force_keyframe) override;
- void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer) override;
+ void UseOutputBitstreamBuffer(media::BitstreamBuffer buffer) override;
void RequestEncodingParametersChange(uint32_t bitrate,
uint32_t framerate) override;
void Destroy() override;
diff --git a/chromium/content/renderer/push_messaging/push_messaging_client.cc b/chromium/content/renderer/push_messaging/push_messaging_client.cc
index f5e3e137a24..6961f408015 100644
--- a/chromium/content/renderer/push_messaging/push_messaging_client.cc
+++ b/chromium/content/renderer/push_messaging/push_messaging_client.cc
@@ -11,19 +11,18 @@
#include "base/bind_helpers.h"
#include "base/strings/utf_string_conversions.h"
#include "content/child/child_thread_impl.h"
-#include "content/common/push_messaging.mojom.h"
-#include "content/public/common/push_messaging_status.mojom.h"
#include "content/public/common/service_names.mojom.h"
-#include "content/renderer/push_messaging/push_provider.h"
+#include "content/renderer/push_messaging/push_messaging_utils.h"
#include "content/renderer/render_frame_impl.h"
#include "services/service_manager/public/cpp/connector.h"
-#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
+#include "third_party/blink/public/common/push_messaging/web_push_subscription_options.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom.h"
#include "third_party/blink/public/platform/modules/push_messaging/web_push_error.h"
#include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription.h"
-#include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription_options.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/web/web_console_message.h"
#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_manifest_manager.h"
#include "url/gurl.h"
namespace content {
@@ -55,19 +54,20 @@ void PushMessagingClient::Subscribe(
// If a developer provided an application server key in |options|, skip
// fetching the manifest.
- if (options.application_server_key.IsEmpty()) {
- RenderFrameImpl::FromRoutingID(routing_id())
- ->GetManifestManager()
- .RequestManifest(base::BindOnce(&PushMessagingClient::DidGetManifest,
- base::Unretained(this),
- service_worker_registration_id, options,
- user_gesture, std::move(callbacks)));
+ if (options.application_server_key.empty()) {
+ blink::WebManifestManager* manifest_manager =
+ blink::WebManifestManager::FromFrame(
+ RenderFrameImpl::FromRoutingID(routing_id())->GetWebFrame());
+ manifest_manager->RequestManifest(
+ base::BindOnce(&PushMessagingClient::DidGetManifest,
+ base::Unretained(this), service_worker_registration_id,
+ options, user_gesture, std::move(callbacks)));
} else {
- PushSubscriptionOptions content_options;
+ blink::WebPushSubscriptionOptions content_options;
content_options.user_visible_only = options.user_visible_only;
// Just treat the server key as a string of bytes and pass it to the push
// service.
- content_options.sender_info = options.application_server_key.Latin1();
+ content_options.application_server_key = options.application_server_key;
DoSubscribe(service_worker_registration_id, content_options, user_gesture,
std::move(callbacks));
}
@@ -78,21 +78,22 @@ void PushMessagingClient::DidGetManifest(
const blink::WebPushSubscriptionOptions& options,
bool user_gesture,
std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks,
- const GURL& manifest_url,
+ const blink::WebURL& manifest_url,
const blink::Manifest& manifest) {
- // Get the sender_info from the manifest since it wasn't provided by
- // the caller.
+ // Get the application_server_key from the manifest since it wasn't provided
+ // by the caller.
if (manifest.IsEmpty()) {
- DidSubscribe(std::move(callbacks),
- mojom::PushRegistrationStatus::MANIFEST_EMPTY_OR_MISSING,
- base::nullopt, base::nullopt, base::nullopt, base::nullopt);
+ DidSubscribe(
+ std::move(callbacks),
+ blink::mojom::PushRegistrationStatus::MANIFEST_EMPTY_OR_MISSING,
+ base::nullopt, base::nullopt, base::nullopt, base::nullopt);
return;
}
- PushSubscriptionOptions content_options;
+ blink::WebPushSubscriptionOptions content_options;
content_options.user_visible_only = options.user_visible_only;
if (!manifest.gcm_sender_id.is_null()) {
- content_options.sender_info =
+ content_options.application_server_key =
base::UTF16ToUTF8(manifest.gcm_sender_id.string());
}
@@ -102,13 +103,13 @@ void PushMessagingClient::DidGetManifest(
void PushMessagingClient::DoSubscribe(
int64_t service_worker_registration_id,
- const PushSubscriptionOptions& options,
+ const blink::WebPushSubscriptionOptions& options,
bool user_gesture,
std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) {
- if (options.sender_info.empty()) {
+ if (options.application_server_key.empty()) {
DidSubscribe(std::move(callbacks),
- mojom::PushRegistrationStatus::NO_SENDER_ID, base::nullopt,
- base::nullopt, base::nullopt, base::nullopt);
+ blink::mojom::PushRegistrationStatus::NO_SENDER_ID,
+ base::nullopt, base::nullopt, base::nullopt, base::nullopt);
return;
}
@@ -123,17 +124,18 @@ void PushMessagingClient::DoSubscribe(
void PushMessagingClient::DidSubscribe(
std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks,
- mojom::PushRegistrationStatus status,
+ blink::mojom::PushRegistrationStatus status,
const base::Optional<GURL>& endpoint,
- const base::Optional<PushSubscriptionOptions>& options,
+ const base::Optional<blink::WebPushSubscriptionOptions>& options,
const base::Optional<std::vector<uint8_t>>& p256dh,
const base::Optional<std::vector<uint8_t>>& auth) {
DCHECK(callbacks);
- if (status == mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE ||
- status == mojom::PushRegistrationStatus::
+ if (status ==
+ blink::mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE ||
+ status == blink::mojom::PushRegistrationStatus::
SUCCESS_NEW_SUBSCRIPTION_FROM_PUSH_SERVICE ||
- status == mojom::PushRegistrationStatus::SUCCESS_FROM_CACHE) {
+ status == blink::mojom::PushRegistrationStatus::SUCCESS_FROM_CACHE) {
DCHECK(endpoint);
DCHECK(options);
DCHECK(p256dh);
@@ -141,7 +143,7 @@ void PushMessagingClient::DidSubscribe(
callbacks->OnSuccess(std::make_unique<blink::WebPushSubscription>(
endpoint.value(), options.value().user_visible_only,
- blink::WebString::FromLatin1(options.value().sender_info),
+ blink::WebString::FromLatin1(options.value().application_server_key),
p256dh.value(), auth.value()));
} else {
callbacks->OnError(PushRegistrationStatusToWebPushError(status));
diff --git a/chromium/content/renderer/push_messaging/push_messaging_client.h b/chromium/content/renderer/push_messaging/push_messaging_client.h
index b8ef9bc0c6a..94f845289ac 100644
--- a/chromium/content/renderer/push_messaging/push_messaging_client.h
+++ b/chromium/content/renderer/push_messaging/push_messaging_client.h
@@ -12,25 +12,25 @@
#include <vector>
#include "base/macros.h"
-#include "content/common/push_messaging.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom.h"
#include "third_party/blink/public/platform/modules/push_messaging/web_push_client.h"
class GURL;
namespace blink {
-struct Manifest;
-struct WebPushSubscriptionOptions;
-}
-
-namespace content {
namespace mojom {
enum class PushRegistrationStatus;
}
-struct PushSubscriptionOptions;
+struct Manifest;
+struct WebPushSubscriptionOptions;
+struct WebPushSubscriptionOptions;
+} // namespace blink
+
+namespace content {
class PushMessagingClient : public RenderFrameObserver,
public blink::WebPushClient {
@@ -54,24 +54,24 @@ class PushMessagingClient : public RenderFrameObserver,
const blink::WebPushSubscriptionOptions& options,
bool user_gesture,
std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks,
- const GURL& manifest_url,
+ const blink::WebURL& manifest_url,
const blink::Manifest& manifest);
void DoSubscribe(
int64_t service_worker_registration_id,
- const PushSubscriptionOptions& options,
+ const blink::WebPushSubscriptionOptions& options,
bool user_gesture,
std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks);
void DidSubscribe(
std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks,
- mojom::PushRegistrationStatus status,
+ blink::mojom::PushRegistrationStatus status,
const base::Optional<GURL>& endpoint,
- const base::Optional<PushSubscriptionOptions>& options,
+ const base::Optional<blink::WebPushSubscriptionOptions>& options,
const base::Optional<std::vector<uint8_t>>& p256dh,
const base::Optional<std::vector<uint8_t>>& auth);
- mojom::PushMessagingPtr push_messaging_manager_;
+ blink::mojom::PushMessagingPtr push_messaging_manager_;
DISALLOW_COPY_AND_ASSIGN(PushMessagingClient);
};
diff --git a/chromium/content/renderer/push_messaging/push_messaging_utils.cc b/chromium/content/renderer/push_messaging/push_messaging_utils.cc
new file mode 100644
index 00000000000..9b6bc81db47
--- /dev/null
+++ b/chromium/content/renderer/push_messaging/push_messaging_utils.cc
@@ -0,0 +1,115 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/push_messaging/push_messaging_utils.h"
+
+#include "content/public/common/service_names.mojom.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom.h"
+#include "third_party/blink/public/platform/web_string.h"
+
+namespace content {
+
+namespace {
+
+const char* PushRegistrationStatusToString(
+ blink::mojom::PushRegistrationStatus status) {
+ switch (status) {
+ case blink::mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE:
+ case blink::mojom::PushRegistrationStatus::
+ SUCCESS_NEW_SUBSCRIPTION_FROM_PUSH_SERVICE:
+ return "Registration successful - from push service";
+
+ case blink::mojom::PushRegistrationStatus::NO_SERVICE_WORKER:
+ return "Registration failed - no Service Worker";
+
+ case blink::mojom::PushRegistrationStatus::SERVICE_NOT_AVAILABLE:
+ return "Registration failed - push service not available";
+
+ case blink::mojom::PushRegistrationStatus::LIMIT_REACHED:
+ return "Registration failed - registration limit has been reached";
+
+ case blink::mojom::PushRegistrationStatus::PERMISSION_DENIED:
+ return "Registration failed - permission denied";
+
+ case blink::mojom::PushRegistrationStatus::SERVICE_ERROR:
+ return "Registration failed - push service error";
+
+ case blink::mojom::PushRegistrationStatus::NO_SENDER_ID:
+ return "Registration failed - missing applicationServerKey, and "
+ "gcm_sender_id not found in manifest";
+
+ case blink::mojom::PushRegistrationStatus::STORAGE_ERROR:
+ return "Registration failed - storage error";
+
+ case blink::mojom::PushRegistrationStatus::SUCCESS_FROM_CACHE:
+ return "Registration successful - from cache";
+
+ case blink::mojom::PushRegistrationStatus::NETWORK_ERROR:
+ return "Registration failed - could not connect to push server";
+
+ case blink::mojom::PushRegistrationStatus::INCOGNITO_PERMISSION_DENIED:
+ // We split this out for UMA, but it must be indistinguishable to JS.
+ return PushRegistrationStatusToString(
+ blink::mojom::PushRegistrationStatus::PERMISSION_DENIED);
+
+ case blink::mojom::PushRegistrationStatus::PUBLIC_KEY_UNAVAILABLE:
+ return "Registration failed - could not retrieve the public key";
+
+ case blink::mojom::PushRegistrationStatus::MANIFEST_EMPTY_OR_MISSING:
+ return "Registration failed - missing applicationServerKey, and manifest "
+ "empty or missing";
+
+ case blink::mojom::PushRegistrationStatus::SENDER_ID_MISMATCH:
+ return "Registration failed - A subscription with a different "
+ "applicationServerKey (or gcm_sender_id) already exists; to "
+ "change the applicationServerKey, unsubscribe then resubscribe.";
+
+ case blink::mojom::PushRegistrationStatus::STORAGE_CORRUPT:
+ return "Registration failed - storage corrupt";
+
+ case blink::mojom::PushRegistrationStatus::RENDERER_SHUTDOWN:
+ return "Registration failed - renderer shutdown";
+ }
+ NOTREACHED();
+ return "";
+}
+
+} // namespace
+
+blink::WebPushError PushRegistrationStatusToWebPushError(
+ blink::mojom::PushRegistrationStatus status) {
+ blink::WebPushError::ErrorType error_type =
+ blink::WebPushError::kErrorTypeAbort;
+ switch (status) {
+ case blink::mojom::PushRegistrationStatus::PERMISSION_DENIED:
+ error_type = blink::WebPushError::kErrorTypeNotAllowed;
+ break;
+ case blink::mojom::PushRegistrationStatus::SENDER_ID_MISMATCH:
+ error_type = blink::WebPushError::kErrorTypeInvalidState;
+ break;
+ case blink::mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE:
+ case blink::mojom::PushRegistrationStatus::
+ SUCCESS_NEW_SUBSCRIPTION_FROM_PUSH_SERVICE:
+ case blink::mojom::PushRegistrationStatus::NO_SERVICE_WORKER:
+ case blink::mojom::PushRegistrationStatus::SERVICE_NOT_AVAILABLE:
+ case blink::mojom::PushRegistrationStatus::LIMIT_REACHED:
+ case blink::mojom::PushRegistrationStatus::SERVICE_ERROR:
+ case blink::mojom::PushRegistrationStatus::NO_SENDER_ID:
+ case blink::mojom::PushRegistrationStatus::STORAGE_ERROR:
+ case blink::mojom::PushRegistrationStatus::SUCCESS_FROM_CACHE:
+ case blink::mojom::PushRegistrationStatus::NETWORK_ERROR:
+ case blink::mojom::PushRegistrationStatus::INCOGNITO_PERMISSION_DENIED:
+ case blink::mojom::PushRegistrationStatus::PUBLIC_KEY_UNAVAILABLE:
+ case blink::mojom::PushRegistrationStatus::MANIFEST_EMPTY_OR_MISSING:
+ case blink::mojom::PushRegistrationStatus::STORAGE_CORRUPT:
+ case blink::mojom::PushRegistrationStatus::RENDERER_SHUTDOWN:
+ error_type = blink::WebPushError::kErrorTypeAbort;
+ break;
+ }
+ return blink::WebPushError(
+ error_type,
+ blink::WebString::FromUTF8(PushRegistrationStatusToString(status)));
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/push_messaging/push_messaging_utils.h b/chromium/content/renderer/push_messaging/push_messaging_utils.h
new file mode 100644
index 00000000000..40b0ceeb960
--- /dev/null
+++ b/chromium/content/renderer/push_messaging/push_messaging_utils.h
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_PUSH_MESSAGING_PUSH_MESSAGING_UTILS_H_
+#define CONTENT_RENDERER_PUSH_MESSAGING_PUSH_MESSAGING_UTILS_H_
+
+#include "third_party/blink/public/platform/modules/push_messaging/web_push_error.h"
+
+namespace blink {
+
+namespace mojom {
+enum class PushRegistrationStatus;
+} // namespace mojom
+
+} // namespace blink
+
+namespace content {
+
+blink::WebPushError PushRegistrationStatusToWebPushError(
+ blink::mojom::PushRegistrationStatus status);
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_PUSH_MESSAGING_PUSH_MESSAGING_UTILS_H_
diff --git a/chromium/content/renderer/push_messaging/push_provider.cc b/chromium/content/renderer/push_messaging/push_provider.cc
deleted file mode 100644
index fd239253961..00000000000
--- a/chromium/content/renderer/push_messaging/push_provider.cc
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/push_messaging/push_provider.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/lazy_instance.h"
-#include "base/threading/thread_local.h"
-#include "content/child/child_thread_impl.h"
-#include "content/public/common/child_process_host.h"
-#include "content/public/common/push_messaging_status.mojom.h"
-#include "content/public/common/push_subscription_options.h"
-#include "content/public/common/service_names.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription.h"
-#include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription_options.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace content {
-namespace {
-
-const char* PushRegistrationStatusToString(
- mojom::PushRegistrationStatus status) {
- switch (status) {
- case mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE:
- case mojom::PushRegistrationStatus::
- SUCCESS_NEW_SUBSCRIPTION_FROM_PUSH_SERVICE:
- return "Registration successful - from push service";
-
- case mojom::PushRegistrationStatus::NO_SERVICE_WORKER:
- return "Registration failed - no Service Worker";
-
- case mojom::PushRegistrationStatus::SERVICE_NOT_AVAILABLE:
- return "Registration failed - push service not available";
-
- case mojom::PushRegistrationStatus::LIMIT_REACHED:
- return "Registration failed - registration limit has been reached";
-
- case mojom::PushRegistrationStatus::PERMISSION_DENIED:
- return "Registration failed - permission denied";
-
- case mojom::PushRegistrationStatus::SERVICE_ERROR:
- return "Registration failed - push service error";
-
- case mojom::PushRegistrationStatus::NO_SENDER_ID:
- return "Registration failed - missing applicationServerKey, and "
- "gcm_sender_id not found in manifest";
-
- case mojom::PushRegistrationStatus::STORAGE_ERROR:
- return "Registration failed - storage error";
-
- case mojom::PushRegistrationStatus::SUCCESS_FROM_CACHE:
- return "Registration successful - from cache";
-
- case mojom::PushRegistrationStatus::NETWORK_ERROR:
- return "Registration failed - could not connect to push server";
-
- case mojom::PushRegistrationStatus::INCOGNITO_PERMISSION_DENIED:
- // We split this out for UMA, but it must be indistinguishable to JS.
- return PushRegistrationStatusToString(
- mojom::PushRegistrationStatus::PERMISSION_DENIED);
-
- case mojom::PushRegistrationStatus::PUBLIC_KEY_UNAVAILABLE:
- return "Registration failed - could not retrieve the public key";
-
- case mojom::PushRegistrationStatus::MANIFEST_EMPTY_OR_MISSING:
- return "Registration failed - missing applicationServerKey, and manifest "
- "empty or missing";
-
- case mojom::PushRegistrationStatus::SENDER_ID_MISMATCH:
- return "Registration failed - A subscription with a different "
- "applicationServerKey (or gcm_sender_id) already exists; to "
- "change the applicationServerKey, unsubscribe then resubscribe.";
-
- case mojom::PushRegistrationStatus::STORAGE_CORRUPT:
- return "Registration failed - storage corrupt";
-
- case mojom::PushRegistrationStatus::RENDERER_SHUTDOWN:
- return "Registration failed - renderer shutdown";
- }
- NOTREACHED();
- return "";
-}
-
-} // namespace
-
-blink::WebPushError PushRegistrationStatusToWebPushError(
- mojom::PushRegistrationStatus status) {
- blink::WebPushError::ErrorType error_type =
- blink::WebPushError::kErrorTypeAbort;
- switch (status) {
- case mojom::PushRegistrationStatus::PERMISSION_DENIED:
- error_type = blink::WebPushError::kErrorTypeNotAllowed;
- break;
- case mojom::PushRegistrationStatus::SENDER_ID_MISMATCH:
- error_type = blink::WebPushError::kErrorTypeInvalidState;
- break;
- case mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE:
- case mojom::PushRegistrationStatus::
- SUCCESS_NEW_SUBSCRIPTION_FROM_PUSH_SERVICE:
- case mojom::PushRegistrationStatus::NO_SERVICE_WORKER:
- case mojom::PushRegistrationStatus::SERVICE_NOT_AVAILABLE:
- case mojom::PushRegistrationStatus::LIMIT_REACHED:
- case mojom::PushRegistrationStatus::SERVICE_ERROR:
- case mojom::PushRegistrationStatus::NO_SENDER_ID:
- case mojom::PushRegistrationStatus::STORAGE_ERROR:
- case mojom::PushRegistrationStatus::SUCCESS_FROM_CACHE:
- case mojom::PushRegistrationStatus::NETWORK_ERROR:
- case mojom::PushRegistrationStatus::INCOGNITO_PERMISSION_DENIED:
- case mojom::PushRegistrationStatus::PUBLIC_KEY_UNAVAILABLE:
- case mojom::PushRegistrationStatus::MANIFEST_EMPTY_OR_MISSING:
- case mojom::PushRegistrationStatus::STORAGE_CORRUPT:
- case mojom::PushRegistrationStatus::RENDERER_SHUTDOWN:
- error_type = blink::WebPushError::kErrorTypeAbort;
- break;
- }
- return blink::WebPushError(
- error_type,
- blink::WebString::FromUTF8(PushRegistrationStatusToString(status)));
-}
-
-static base::LazyInstance<base::ThreadLocalPointer<PushProvider>>::Leaky
- g_push_provider_tls = LAZY_INSTANCE_INITIALIZER;
-
-PushProvider::PushProvider(const scoped_refptr<base::SingleThreadTaskRunner>&
- main_thread_task_runner) {
- DCHECK(main_thread_task_runner);
-
- auto request = mojo::MakeRequest(&push_messaging_manager_);
- if (!main_thread_task_runner->BelongsToCurrentThread()) {
- main_thread_task_runner->PostTask(
- FROM_HERE,
- base::BindOnce(&PushProvider::GetInterface, std::move(request)));
- } else {
- GetInterface(std::move(request));
- }
- g_push_provider_tls.Pointer()->Set(this);
-}
-
-PushProvider::~PushProvider() {
- g_push_provider_tls.Pointer()->Set(nullptr);
-}
-
-PushProvider* PushProvider::ThreadSpecificInstance(
- const scoped_refptr<base::SingleThreadTaskRunner>&
- main_thread_task_runner) {
- if (g_push_provider_tls.Pointer()->Get())
- return g_push_provider_tls.Pointer()->Get();
-
- PushProvider* provider = new PushProvider(main_thread_task_runner);
- if (WorkerThread::GetCurrentId())
- WorkerThread::AddObserver(provider);
- return provider;
-}
-
-// static
-void PushProvider::GetInterface(mojom::PushMessagingRequest request) {
- if (ChildThreadImpl::current()) {
- ChildThreadImpl::current()->GetConnector()->BindInterface(
- mojom::kBrowserServiceName, std::move(request));
- }
-}
-
-void PushProvider::WillStopCurrentWorkerThread() {
- delete this;
-}
-
-void PushProvider::Subscribe(
- int64_t service_worker_registration_id,
- const blink::WebPushSubscriptionOptions& options,
- bool user_gesture,
- std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) {
- DCHECK(callbacks);
-
- PushSubscriptionOptions content_options;
- content_options.user_visible_only = options.user_visible_only;
-
- // Just treat the server key as a string of bytes and pass it to the push
- // service.
- content_options.sender_info = options.application_server_key.Latin1();
-
- push_messaging_manager_->Subscribe(
- ChildProcessHost::kInvalidUniqueID, service_worker_registration_id,
- content_options, user_gesture,
- // Safe to use base::Unretained because |push_messaging_manager_ |is owned
- // by |this|.
- base::BindOnce(&PushProvider::DidSubscribe, base::Unretained(this),
- std::move(callbacks)));
-}
-
-void PushProvider::DidSubscribe(
- std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks,
- mojom::PushRegistrationStatus status,
- const base::Optional<GURL>& endpoint,
- const base::Optional<PushSubscriptionOptions>& options,
- const base::Optional<std::vector<uint8_t>>& p256dh,
- const base::Optional<std::vector<uint8_t>>& auth) {
- DCHECK(callbacks);
-
- if (status == mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE ||
- status == mojom::PushRegistrationStatus::
- SUCCESS_NEW_SUBSCRIPTION_FROM_PUSH_SERVICE ||
- status == mojom::PushRegistrationStatus::SUCCESS_FROM_CACHE) {
- DCHECK(endpoint);
- DCHECK(options);
- DCHECK(p256dh);
- DCHECK(auth);
-
- callbacks->OnSuccess(std::make_unique<blink::WebPushSubscription>(
- endpoint.value(), options.value().user_visible_only,
- blink::WebString::FromLatin1(options.value().sender_info),
- p256dh.value(), auth.value()));
- } else {
- callbacks->OnError(PushRegistrationStatusToWebPushError(status));
- }
-}
-
-void PushProvider::Unsubscribe(
- int64_t service_worker_registration_id,
- std::unique_ptr<blink::WebPushUnsubscribeCallbacks> callbacks) {
- DCHECK(callbacks);
-
- push_messaging_manager_->Unsubscribe(
- service_worker_registration_id,
- // Safe to use base::Unretained because |push_messaging_manager_ |is owned
- // by |this|.
- base::BindOnce(&PushProvider::DidUnsubscribe, base::Unretained(this),
- std::move(callbacks)));
-}
-
-void PushProvider::DidUnsubscribe(
- std::unique_ptr<blink::WebPushUnsubscribeCallbacks> callbacks,
- blink::WebPushError::ErrorType error_type,
- bool did_unsubscribe,
- const base::Optional<std::string>& error_message) {
- DCHECK(callbacks);
-
- // ErrorTypeNone indicates success.
- if (error_type == blink::WebPushError::kErrorTypeNone) {
- callbacks->OnSuccess(did_unsubscribe);
- } else {
- callbacks->OnError(blink::WebPushError(
- error_type, blink::WebString::FromUTF8(error_message->c_str())));
- }
-}
-
-void PushProvider::GetSubscription(
- int64_t service_worker_registration_id,
- std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) {
- DCHECK(callbacks);
-
- push_messaging_manager_->GetSubscription(
- service_worker_registration_id,
- // Safe to use base::Unretained because |push_messaging_manager_ |is owned
- // by |this|.
- base::BindOnce(&PushProvider::DidGetSubscription, base::Unretained(this),
- std::move(callbacks)));
-}
-
-void PushProvider::DidGetSubscription(
- std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks,
- mojom::PushGetRegistrationStatus status,
- const base::Optional<GURL>& endpoint,
- const base::Optional<PushSubscriptionOptions>& options,
- const base::Optional<std::vector<uint8_t>>& p256dh,
- const base::Optional<std::vector<uint8_t>>& auth) {
- DCHECK(callbacks);
-
- if (status == mojom::PushGetRegistrationStatus::SUCCESS) {
- DCHECK(endpoint);
- DCHECK(options);
- DCHECK(p256dh);
- DCHECK(auth);
-
- callbacks->OnSuccess(std::make_unique<blink::WebPushSubscription>(
- endpoint.value(), options.value().user_visible_only,
- blink::WebString::FromLatin1(options.value().sender_info),
- p256dh.value(), auth.value()));
- } else {
- // We are only expecting an error if we can't find a registration.
- callbacks->OnSuccess(nullptr);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/push_messaging/push_provider.h b/chromium/content/renderer/push_messaging/push_provider.h
deleted file mode 100644
index ad6b1fc41c0..00000000000
--- a/chromium/content/renderer/push_messaging/push_provider.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_PUSH_MESSAGING_PUSH_PROVIDER_H_
-#define CONTENT_RENDERER_PUSH_MESSAGING_PUSH_PROVIDER_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/common/push_messaging.mojom.h"
-#include "content/public/renderer/worker_thread.h"
-#include "third_party/blink/public/platform/modules/push_messaging/web_push_error.h"
-#include "third_party/blink/public/platform/modules/push_messaging/web_push_provider.h"
-
-class GURL;
-
-namespace blink {
-struct WebPushSubscriptionOptions;
-}
-
-namespace content {
-
-namespace mojom {
-enum class PushGetRegistrationStatus;
-enum class PushRegistrationStatus;
-} // namespace mojom
-
-struct PushSubscriptionOptions;
-
-blink::WebPushError PushRegistrationStatusToWebPushError(
- mojom::PushRegistrationStatus status);
-
-class PushProvider : public blink::WebPushProvider,
- public WorkerThread::Observer {
- public:
- ~PushProvider() override;
-
- static PushProvider* ThreadSpecificInstance(
- const scoped_refptr<base::SingleThreadTaskRunner>&
- main_thread_task_runner);
-
- // WorkerThread::Observer implementation.
- void WillStopCurrentWorkerThread() override;
-
- // blink::WebPushProvider implementation.
- void Subscribe(
- int64_t service_worker_registration_id,
- const blink::WebPushSubscriptionOptions& options,
- bool user_gesture,
- std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) override;
- void Unsubscribe(
- int64_t service_worker_registration_id,
- std::unique_ptr<blink::WebPushUnsubscribeCallbacks> callbacks) override;
- void GetSubscription(
- int64_t service_worker_registration_id,
- std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) override;
-
- private:
- explicit PushProvider(const scoped_refptr<base::SingleThreadTaskRunner>&
- main_thread_task_runner);
-
- static void GetInterface(mojom::PushMessagingRequest request);
-
- void DidSubscribe(
- std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks,
- mojom::PushRegistrationStatus status,
- const base::Optional<GURL>& endpoint,
- const base::Optional<PushSubscriptionOptions>& options,
- const base::Optional<std::vector<uint8_t>>& p256dh,
- const base::Optional<std::vector<uint8_t>>& auth);
-
- void DidUnsubscribe(
- std::unique_ptr<blink::WebPushUnsubscribeCallbacks> callbacks,
- blink::WebPushError::ErrorType error_type,
- bool did_unsubscribe,
- const base::Optional<std::string>& error_message);
-
- void DidGetSubscription(
- std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks,
- mojom::PushGetRegistrationStatus status,
- const base::Optional<GURL>& endpoint,
- const base::Optional<PushSubscriptionOptions>& options,
- const base::Optional<std::vector<uint8_t>>& p256dh,
- const base::Optional<std::vector<uint8_t>>& auth);
-
- mojom::PushMessagingPtr push_messaging_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(PushProvider);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_PUSH_MESSAGING_PUSH_PROVIDER_H_
diff --git a/chromium/content/renderer/queue_message_swap_promise.cc b/chromium/content/renderer/queue_message_swap_promise.cc
index 0edbb770760..18572edbb74 100644
--- a/chromium/content/renderer/queue_message_swap_promise.cc
+++ b/chromium/content/renderer/queue_message_swap_promise.cc
@@ -22,34 +22,20 @@ QueueMessageSwapPromise::QueueMessageSwapPromise(
: message_sender_(message_sender),
message_queue_(message_queue),
source_frame_number_(source_frame_number)
-#if DCHECK_IS_ON()
- ,
- completed_(false)
-#endif
{
DCHECK(message_sender_.get());
DCHECK(message_queue_.get());
}
QueueMessageSwapPromise::~QueueMessageSwapPromise() {
- // The promise should have either been kept or broken before it's deleted.
-#if DCHECK_IS_ON()
- DCHECK(completed_);
-#endif
}
void QueueMessageSwapPromise::DidActivate() {
-#if DCHECK_IS_ON()
- DCHECK(!completed_);
-#endif
message_queue_->DidActivate(source_frame_number_);
// The OutputSurface will take care of the Drain+Send.
}
void QueueMessageSwapPromise::WillSwap(viz::CompositorFrameMetadata* metadata) {
-#if DCHECK_IS_ON()
- DCHECK(!completed_);
-#endif
message_queue_->DidSwap(source_frame_number_);
if (!message_queue_->AreFramesDiscarded()) {
@@ -67,30 +53,21 @@ void QueueMessageSwapPromise::WillSwap(viz::CompositorFrameMetadata* metadata) {
messages_to_send));
}
}
-
- PromiseCompleted();
}
void QueueMessageSwapPromise::DidSwap() {}
-void QueueMessageSwapPromise::DidNotSwap(DidNotSwapReason reason) {
-#if DCHECK_IS_ON()
- DCHECK(!completed_);
-#endif
+cc::SwapPromise::DidNotSwapAction QueueMessageSwapPromise::DidNotSwap(
+ DidNotSwapReason reason) {
// TODO(eseckler): Deliver messages with the next swap instead of sending
// them here directly.
std::vector<std::unique_ptr<IPC::Message>> messages;
- message_queue_->DidNotSwap(source_frame_number_, reason, &messages);
+ cc::SwapPromise::DidNotSwapAction action =
+ message_queue_->DidNotSwap(source_frame_number_, reason, &messages);
for (auto& msg : messages) {
message_sender_->Send(msg.release());
}
- PromiseCompleted();
-}
-
-void QueueMessageSwapPromise::PromiseCompleted() {
-#if DCHECK_IS_ON()
- completed_ = true;
-#endif
+ return action;
}
int64_t QueueMessageSwapPromise::TraceId() const {
diff --git a/chromium/content/renderer/queue_message_swap_promise.h b/chromium/content/renderer/queue_message_swap_promise.h
index f77cc64150b..2c31b90639b 100644
--- a/chromium/content/renderer/queue_message_swap_promise.h
+++ b/chromium/content/renderer/queue_message_swap_promise.h
@@ -29,19 +29,14 @@ class QueueMessageSwapPromise : public cc::SwapPromise {
void DidActivate() override;
void WillSwap(viz::CompositorFrameMetadata* metadata) override;
void DidSwap() override;
- void DidNotSwap(DidNotSwapReason reason) override;
+ DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override;
int64_t TraceId() const override;
private:
- void PromiseCompleted();
-
scoped_refptr<IPC::SyncMessageFilter> message_sender_;
scoped_refptr<content::FrameSwapMessageQueue> message_queue_;
int source_frame_number_;
-#if DCHECK_IS_ON()
- bool completed_;
-#endif
};
} // namespace content
diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc
index dc3c7420d89..e18fd3c17dd 100644
--- a/chromium/content/renderer/render_frame_impl.cc
+++ b/chromium/content/renderer/render_frame_impl.cc
@@ -11,6 +11,7 @@
#include <vector>
#include "base/auto_reset.h"
+#include "base/base64.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
@@ -109,7 +110,6 @@
#include "content/renderer/input/frame_input_handler_impl.h"
#include "content/renderer/input/input_target_client_impl.h"
#include "content/renderer/input/widget_input_handler_manager.h"
-#include "content/renderer/installedapp/related_apps_fetcher.h"
#include "content/renderer/internal_document_state_data.h"
#include "content/renderer/loader/navigation_body_loader.h"
#include "content/renderer/loader/request_extra_data.h"
@@ -119,8 +119,6 @@
#include "content/renderer/loader/web_url_request_util.h"
#include "content/renderer/loader/web_worker_fetch_context_impl.h"
#include "content/renderer/low_memory_mode_controller.h"
-#include "content/renderer/manifest/manifest_change_notifier.h"
-#include "content/renderer/manifest/manifest_manager.h"
#include "content/renderer/media/audio/audio_device_factory.h"
#include "content/renderer/media/audio/audio_output_ipc_factory.h"
#include "content/renderer/media/audio/audio_renderer_sink_cache.h"
@@ -141,7 +139,6 @@
#include "content/renderer/render_view_impl.h"
#include "content/renderer/render_widget_fullscreen_pepper.h"
#include "content/renderer/renderer_blink_platform_impl.h"
-#include "content/renderer/renderer_webapplicationcachehost_impl.h"
#include "content/renderer/resource_timing_info_conversions.h"
#include "content/renderer/savable_resources.h"
#include "content/renderer/service_worker/service_worker_network_provider_for_frame.h"
@@ -163,7 +160,6 @@
#include "ppapi/buildflags/buildflags.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
@@ -172,9 +168,11 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
#include "third_party/blink/public/common/frame/user_activation_update_type.h"
+#include "third_party/blink/public/common/logging/logging_utils.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
+#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom.h"
#include "third_party/blink/public/mojom/permissions/permission.mojom.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/interface_provider.h"
@@ -450,7 +448,7 @@ void FillNavigationParamsRequest(
navigation_params->url = !commit_params.original_url.is_empty()
? commit_params.original_url
: common_params.url;
- navigation_params->http_method = WebString::FromLatin1(
+ navigation_params->http_method = WebString::FromASCII(
!commit_params.original_method.empty() ? commit_params.original_method
: common_params.method);
@@ -490,7 +488,40 @@ void FillNavigationParamsRequest(
common_params.initiator_origin.value();
}
+ navigation_params->initiator_origin_trial_features = {
+ common_params.initiator_origin_trial_features.begin(),
+ common_params.initiator_origin_trial_features.end()};
+
navigation_params->was_discarded = commit_params.was_discarded;
+
+ if (!commit_params.prefetched_signed_exchanges.empty()) {
+ DCHECK(base::FeatureList::IsEnabled(
+ features::kSignedExchangeSubresourcePrefetch));
+ navigation_params->prefetched_signed_exchanges = WebVector<std::unique_ptr<
+ blink::WebNavigationParams::PrefetchedSignedExchange>>();
+
+ for (const auto& exchange : commit_params.prefetched_signed_exchanges) {
+ blink::WebURLResponse web_response;
+ WebURLLoaderImpl::PopulateURLResponse(
+ exchange.inner_url, exchange.inner_response, &web_response,
+ false /* report_security_info*/, -1 /* request_id */);
+ std::string header_integrity_base64;
+ base::Base64Encode(
+ base::StringPiece(
+ reinterpret_cast<const char*>(exchange.header_integrity.data),
+ sizeof(exchange.header_integrity.data)),
+ &header_integrity_base64);
+ navigation_params->prefetched_signed_exchanges.emplace_back(
+ std::make_unique<
+ blink::WebNavigationParams::PrefetchedSignedExchange>(
+ exchange.outer_url,
+ WebString::FromLatin1(std::string("sha256-") +
+ header_integrity_base64),
+ exchange.inner_url, web_response,
+ mojo::ScopedMessagePipeHandle(exchange.loader_factory_handle)));
+ }
+ }
+
#if defined(OS_ANDROID)
navigation_params->had_transient_activation = common_params.has_user_gesture;
#endif
@@ -501,7 +532,8 @@ CommonNavigationParams MakeCommonNavigationParams(
std::unique_ptr<blink::WebNavigationInfo> info,
int load_flags,
bool has_download_sandbox_flag,
- bool from_ad) {
+ bool from_ad,
+ bool is_history_navigation_in_new_child_frame) {
// A valid RequestorOrigin is always expected to be present.
DCHECK(!info->url_request.RequestorOrigin().IsNull());
@@ -541,6 +573,11 @@ CommonNavigationParams MakeCommonNavigationParams(
static_cast<RequestExtraData*>(info->url_request.GetExtraData());
DCHECK(extra_data);
+ // Convert from WebVector<int> to std::vector<int>.
+ std::vector<int> initiator_origin_trial_features(
+ info->initiator_origin_trial_features.begin(),
+ info->initiator_origin_trial_features.end());
+
NavigationDownloadPolicy download_policy;
RenderFrameImpl::MaybeSetDownloadFramePolicy(
info->is_opener_navigation, info->url_request, current_origin,
@@ -562,7 +599,8 @@ CommonNavigationParams MakeCommonNavigationParams(
? base::Optional<CSPSource>(BuildCSPSource(
info->initiator_csp.self_source.value()))
: base::nullopt),
- info->href_translate.Latin1(), info->input_start);
+ initiator_origin_trial_features, info->href_translate.Latin1(),
+ is_history_navigation_in_new_child_frame, info->input_start);
}
WebFrameLoadType NavigationTypeToLoadType(
@@ -1788,9 +1826,10 @@ RenderFrameImpl::RenderFrameImpl(CreateParams params)
mhtml_file_writer_binding_(this),
navigation_client_impl_(nullptr),
has_accessed_initial_document_(false),
- media_factory_(this,
- base::Bind(&RenderFrameImpl::RequestOverlayRoutingToken,
- base::Unretained(this))),
+ media_factory_(
+ this,
+ base::BindRepeating(&RenderFrameImpl::RequestOverlayRoutingToken,
+ base::Unretained(this))),
input_target_client_impl_(this),
devtools_frame_token_(params.devtools_frame_token),
weak_factory_(this) {
@@ -1825,15 +1864,6 @@ RenderFrameImpl::RenderFrameImpl(CreateParams params)
// Manages its own lifetime.
plugin_power_saver_helper_ = new PluginPowerSaverHelper(this);
#endif
-
- manifest_manager_ = std::make_unique<ManifestManager>(this);
- // TODO(ajwong): This always returns true as is_main_frame_ gets initialized
- // later in RenderFrameImpl::Initialize(). Should the conditional be in
- // RenderFrameImpl::Initialize()? https://crbug.com/840533
- if (IsMainFrame()) {
- // Manages its own lifetime.
- new ManifestChangeNotifier(this);
- }
}
mojom::FrameHost* RenderFrameImpl::GetFrameHost() {
@@ -1987,7 +2017,7 @@ void RenderFrameImpl::PepperTextInputTypeChanged(
GetLocalRootRenderWidget()->UpdateTextInputState();
- FocusedNodeChangedForAccessibility(WebNode());
+ FocusedElementChangedForAccessibility(WebElement());
}
void RenderFrameImpl::PepperCaretPositionChanged(
@@ -2308,10 +2338,6 @@ void RenderFrameImpl::BindNavigationClient(
navigation_client_impl_->Bind(std::move(request));
}
-blink::mojom::ManifestManager& RenderFrameImpl::GetManifestManager() {
- return *manifest_manager_;
-}
-
void RenderFrameImpl::OnBeforeUnload(bool is_reload) {
TRACE_EVENT1("navigation,rail", "RenderFrameImpl::OnBeforeUnload",
"id", routing_id_);
@@ -2464,6 +2490,7 @@ void RenderFrameImpl::OnDeleteFrame(FrameDeleteIntention intent) {
// frame when a commit (and ownership transfer) is imminent.
// TODO(dcheng): This is the case of https://crbug.com/838348.
DCHECK(is_main_frame_);
+ CHECK(!in_frame_tree_);
break;
}
@@ -2541,8 +2568,9 @@ void RenderFrameImpl::OnSaveImageAt(int x, int y) {
void RenderFrameImpl::OnAddMessageToConsole(
blink::mojom::ConsoleMessageLevel level,
- const std::string& message) {
- AddMessageToConsole(level, message);
+ const std::string& message,
+ bool discard_duplicates) {
+ AddMessageToConsoleImpl(level, message, discard_duplicates);
}
void RenderFrameImpl::JavaScriptExecuteRequest(
@@ -2718,18 +2746,20 @@ void RenderFrameImpl::OnSnapshotAccessibilityTree(int callback_id,
void RenderFrameImpl::OnPortalActivated(
const base::UnguessableToken& portal_token,
blink::mojom::PortalAssociatedPtrInfo portal,
+ blink::mojom::PortalClientAssociatedRequest portal_client,
blink::TransferableMessage data,
OnPortalActivatedCallback callback) {
- frame_->OnPortalActivated(portal_token, portal.PassHandle(), std::move(data),
+ frame_->OnPortalActivated(portal_token, portal.PassHandle(),
+ portal_client.PassHandle(), std::move(data),
std::move(callback));
}
-void RenderFrameImpl::ForwardMessageToPortalHost(
+void RenderFrameImpl::ForwardMessageFromHost(
blink::TransferableMessage message,
const url::Origin& source_origin,
const base::Optional<url::Origin>& target_origin) {
- frame_->ForwardMessageToPortalHost(std::move(message), source_origin,
- target_origin);
+ frame_->ForwardMessageFromHost(std::move(message), source_origin,
+ target_origin);
}
void RenderFrameImpl::SetLifecycleState(
@@ -2931,9 +2961,9 @@ bool RenderFrameImpl::RunJavaScriptDialog(JavaScriptDialogType type,
return success;
}
-void RenderFrameImpl::DidFailProvisionalLoad(
- const WebURLError& error,
- blink::WebHistoryCommitType commit_type) {
+void RenderFrameImpl::DidFailProvisionalLoad(const WebURLError& error,
+ const WebString& http_method) {
+ DCHECK_EQ(net::ERR_ABORTED, error.reason());
TRACE_EVENT1("navigation,benchmark,rail",
"RenderFrameImpl::didFailProvisionalLoad", "id", routing_id_);
// Note: It is important this notification occur before DidStopLoading so the
@@ -2942,36 +2972,12 @@ void RenderFrameImpl::DidFailProvisionalLoad(
//
NotifyObserversOfFailedProvisionalLoad(error);
- WebDocumentLoader* document_loader = frame_->GetProvisionalDocumentLoader();
- if (!document_loader)
- return;
-
// Notify the browser that we failed a provisional load with an error.
- SendFailedProvisionalLoad(document_loader->HttpMethod().Ascii(), error,
- frame_);
-
- if (!ShouldDisplayErrorPageForFailedLoad(error.reason(), error.url()))
- return;
-
- // If this is a failed back/forward/reload navigation, then we need to do a
- // 'replace' load. This is necessary to avoid messing up session history.
- // Otherwise, we do a normal load, which simulates a 'go' navigation as far
- // as session history is concerned.
- bool replace_current_item = commit_type != blink::kWebStandardCommit;
-
- // If we failed on a browser initiated request, then make sure that our error
- // page load is regarded as the same browser initiated request.
- bool inherit_document_state =
- !NavigationState::FromDocumentLoader(document_loader)
- ->IsContentInitiated();
- LoadNavigationErrorPage(document_loader, error, base::nullopt,
- replace_current_item, inherit_document_state);
+ SendFailedProvisionalLoad(http_method.Ascii(), error, frame_);
}
void RenderFrameImpl::NotifyObserversOfFailedProvisionalLoad(
const blink::WebURLError& error) {
- for (auto& observer : render_view_->observers())
- observer.DidFailProvisionalLoad(frame_, error);
for (auto& observer : observers_)
observer.DidFailProvisionalLoad(error);
}
@@ -2980,8 +2986,7 @@ void RenderFrameImpl::LoadNavigationErrorPage(
WebDocumentLoader* document_loader,
const WebURLError& error,
const base::Optional<std::string>& error_page_content,
- bool replace_current_item,
- bool inherit_document_state) {
+ bool replace_current_item) {
std::string error_html;
if (error_page_content) {
error_html = error_page_content.value();
@@ -2997,36 +3002,13 @@ void RenderFrameImpl::LoadNavigationErrorPage(
auto navigation_params = WebNavigationParams::CreateForErrorPage(
document_loader, error_html, GURL(kUnreachableWebDataURL), error.url(),
error.reason());
- std::unique_ptr<DocumentState> document_state;
-
- if (inherit_document_state) {
- NavigationState* navigation_state =
- NavigationState::FromDocumentLoader(document_loader);
- // The error page load (not to confuse with a failed load of original page)
- // was not initiated through BeginNavigation, therefore
- // |was_initiated_in_this_frame| is false.
- document_state = BuildDocumentStateFromParams(
- navigation_state->common_params(), navigation_state->commit_params(),
- base::TimeTicks(), // Not used for failed navigation.
- mojom::FrameNavigationControl::CommitNavigationCallback(),
- mojom::NavigationClient::CommitNavigationCallback(), nullptr, nullptr,
- ResourceDispatcher::MakeRequestID(),
- false /* was_initiated_in_this_frame */);
- FillMiscNavigationParams(navigation_state->common_params(),
- navigation_state->commit_params(),
- navigation_params.get());
- } else {
- document_state = BuildDocumentState();
- }
-
if (replace_current_item)
navigation_params->frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
navigation_params->service_worker_network_provider =
ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance();
// The load of the error page can result in this frame being removed.
- frame_->CommitNavigation(std::move(navigation_params),
- std::move(document_state));
+ frame_->CommitNavigation(std::move(navigation_params), BuildDocumentState());
// Do not access |this| or |frame_| without checking weak self.
}
@@ -3095,16 +3077,6 @@ void RenderFrameImpl::CancelContextMenu(int request_id) {
pending_context_menus_.Remove(request_id);
}
-void RenderFrameImpl::BindToFrame(blink::WebNavigationControl* frame) {
- DCHECK(!frame_);
-
- std::pair<FrameMap::iterator, bool> result =
- g_frame_map.Get().emplace(frame, this);
- CHECK(result.second) << "Inserting a duplicate item.";
-
- frame_ = frame;
-}
-
blink::WebPlugin* RenderFrameImpl::CreatePlugin(
const WebPluginInfo& info,
const blink::WebPluginParams& params,
@@ -3147,8 +3119,7 @@ blink::WebPlugin* RenderFrameImpl::CreatePlugin(
void RenderFrameImpl::LoadErrorPage(int reason) {
LoadNavigationErrorPage(frame_->GetDocumentLoader(),
WebURLError(reason, frame_->GetDocument().Url()),
- base::nullopt, true /* replace_current_item */,
- false /* inherit_document_state */);
+ base::nullopt, true /* replace_current_item */);
}
void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) {
@@ -3208,9 +3179,9 @@ RenderFrameImpl::GetRemoteAssociatedInterfaces() {
#if BUILDFLAG(ENABLE_PLUGINS)
void RenderFrameImpl::RegisterPeripheralPlugin(
const url::Origin& content_origin,
- const base::Closure& unthrottle_callback) {
+ base::OnceClosure unthrottle_callback) {
return plugin_power_saver_helper_->RegisterPeripheralPlugin(
- content_origin, unthrottle_callback);
+ content_origin, std::move(unthrottle_callback));
}
RenderFrame::PeripheralContentStatus
@@ -3267,8 +3238,7 @@ double RenderFrameImpl::GetZoomLevel() {
void RenderFrameImpl::AddMessageToConsole(
blink::mojom::ConsoleMessageLevel level,
const std::string& message) {
- blink::WebConsoleMessage wcm(level, WebString::FromUTF8(message));
- frame_->AddMessageToConsole(wcm);
+ AddMessageToConsoleImpl(level, message, false /* discard_duplicates */);
}
void RenderFrameImpl::SetPreviewsState(PreviewsState previews_state) {
@@ -3586,7 +3556,7 @@ void RenderFrameImpl::CommitNavigationWithParams(
// use the old web APIs.
// After completion of the migration, we should remove this.
// See crbug.com/924871 for detail.
- if (common_params.url.SchemeIs(content::kChromeUIScheme)) {
+ if (GetContentClient()->renderer()->RequiresHtmlImports(common_params.url)) {
blink::WebRuntimeFeatures::EnableShadowDOMV0(true);
blink::WebRuntimeFeatures::EnableCustomElementsV0(true);
blink::WebRuntimeFeatures::EnableHTMLImports(true);
@@ -3618,8 +3588,7 @@ void RenderFrameImpl::CommitNavigationWithParams(
// Check that the history navigation can commit.
commit_status = PrepareForHistoryNavigationCommit(
- common_params.navigation_type, commit_params,
- &item_for_history_navigation, &load_type);
+ common_params, commit_params, &item_for_history_navigation, &load_type);
}
if (commit_status != blink::mojom::CommitResult::Ok) {
@@ -3732,8 +3701,33 @@ void RenderFrameImpl::CommitFailedNavigationInternal(
// On load failure, a frame can ask its owner to render fallback content.
// When that happens, don't load an error page.
+ base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr();
blink::WebNavigationControl::FallbackContentResult fallback_result =
frame_->MaybeRenderFallbackContent(error);
+
+ // The rendering fallback content can result in this frame being removed.
+ // Use a WeakPtr as an easy way to detect whether this has occurred. If so,
+ // this method should return immediately and not touch any part of the object,
+ // otherwise it will result in a use-after-free bug.
+ if (!weak_this)
+ return;
+
+ if (commit_params.nav_entry_id == 0) {
+ // For renderer initiated navigations, we send out a
+ // DidFailProvisionalLoad() notification.
+ NotifyObserversOfFailedProvisionalLoad(error);
+
+ // |browser_side_navigation_pending_| can be false if we are committing
+ // failed navigation in a different process than it was started, e.g.
+ // an error page which is isolated.
+ if (browser_side_navigation_pending_) {
+ // TODO(dgozman): why do we need to notify browser in response
+ // to it's own request?
+ SendFailedProvisionalLoad(navigation_params->http_method.Ascii(), error,
+ frame_);
+ }
+ }
+
if (fallback_result != blink::WebNavigationControl::NoFallbackContent) {
if (fallback_result == blink::WebNavigationControl::NoLoadInProgress) {
// If the frame wasn't loading but was fallback-eligible, the fallback
@@ -3768,21 +3762,6 @@ void RenderFrameImpl::CommitFailedNavigationInternal(
if (commit_params.page_state.IsValid())
history_entry = PageStateToHistoryEntry(commit_params.page_state);
- if (commit_params.nav_entry_id == 0) {
- // For renderer initiated navigations, we send out a
- // DidFailProvisionalLoad() notification.
- NotifyObserversOfFailedProvisionalLoad(error);
-
- // Provisional document loader can be null in cases such as cross
- // process failures, e.g. error pages.
- if (frame_->GetProvisionalDocumentLoader()) {
- // TODO(dgozman): why do we need to notify browser in response
- // to it's own request?
- SendFailedProvisionalLoad(navigation_params->http_method.Ascii(), error,
- frame_);
- }
- }
-
std::string error_html;
if (error_page_content.has_value()) {
error_html = error_page_content.value();
@@ -3824,10 +3803,9 @@ void RenderFrameImpl::CommitFailedNavigationInternal(
false /* was_initiated_in_this_frame */);
// The load of the error page can result in this frame being removed.
- // Use a WeakPtr as an easy way to detect whether this has occured. If so,
+ // Use a WeakPtr as an easy way to detect whether this has occurred. If so,
// this method should return immediately and not touch any part of the object,
// otherwise it will result in a use-after-free bug.
- base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr();
frame_->CommitNavigation(std::move(navigation_params),
std::move(document_state));
if (!weak_this)
@@ -3862,10 +3840,9 @@ void RenderFrameImpl::CommitSameDocumentNavigation(
// which should be the case because history navigations are routed via the
// browser.
DCHECK_NE(0, commit_params.nav_entry_id);
- DCHECK(!commit_params.is_history_navigation_in_new_child);
+ DCHECK(!common_params.is_history_navigation_in_new_child_frame);
commit_status = PrepareForHistoryNavigationCommit(
- common_params.navigation_type, commit_params,
- &item_for_history_navigation, &load_type);
+ common_params, commit_params, &item_for_history_navigation, &load_type);
}
if (commit_status == blink::mojom::CommitResult::Ok) {
@@ -3997,13 +3974,13 @@ void RenderFrameImpl::SetHostZoomLevel(const GURL& url, double zoom_level) {
// blink::WebLocalFrameClient implementation
// ----------------------------------------
-bool RenderFrameImpl::MaybeCreateMimeHandlerView(
+bool RenderFrameImpl::IsPluginHandledExternally(
const blink::WebElement& plugin_element,
const blink::WebURL& url,
const blink::WebString& suggested_mime_type) {
DCHECK(content::MimeHandlerViewMode::UsesCrossProcessFrame());
#if BUILDFLAG(ENABLE_PLUGINS)
- return GetContentClient()->renderer()->MaybeCreateMimeHandlerView(
+ return GetContentClient()->renderer()->IsPluginHandledExternally(
this, plugin_element, GURL(url), suggested_mime_type.Utf8());
#else
return false;
@@ -4024,6 +4001,23 @@ v8::Local<v8::Object> RenderFrameImpl::GetScriptableObject(
#endif
}
+void RenderFrameImpl::UpdateSubresourceFactory(
+ std::unique_ptr<blink::URLLoaderFactoryBundleInfo> info) {
+ auto child_info =
+ std::make_unique<ChildURLLoaderFactoryBundleInfo>(std::move(info));
+ GetLoaderFactoryBundle()->Update(std::move(child_info));
+}
+
+void RenderFrameImpl::BindToFrame(blink::WebNavigationControl* frame) {
+ DCHECK(!frame_);
+
+ std::pair<FrameMap::iterator, bool> result =
+ g_frame_map.Get().emplace(frame, this);
+ CHECK(result.second) << "Inserting a duplicate item.";
+
+ frame_ = frame;
+}
+
blink::WebPlugin* RenderFrameImpl::CreatePlugin(
const blink::WebPluginParams& params) {
blink::WebPlugin* plugin = nullptr;
@@ -4038,6 +4032,8 @@ blink::WebPlugin* RenderFrameImpl::CreatePlugin(
BrowserPluginDelegate* delegate =
GetContentClient()->renderer()->CreateBrowserPluginDelegate(
this, WebPluginInfo(), kBrowserPluginMimeType, GURL(params.url));
+ if (!delegate)
+ return nullptr;
return BrowserPluginManager::Get()->CreateBrowserPlugin(
this, delegate->GetWeakPtr());
}
@@ -4087,9 +4083,10 @@ RenderFrameImpl::CreateApplicationCacheHost(
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
frame_->GetTaskRunner(blink::TaskType::kNetworking);
- return std::make_unique<RendererWebApplicationCacheHostImpl>(
- RenderViewImpl::FromWebView(frame_->View()), client,
- navigation_state->commit_params().appcache_host_id, routing_id_,
+ return blink::WebApplicationCacheHost::CreateWebApplicationCacheHostForFrame(
+ frame_, client,
+ navigation_state->commit_params().appcache_host_id.value_or(
+ base::UnguessableToken()),
std::move(task_runner));
}
@@ -4359,23 +4356,29 @@ blink::WebLocalFrame* RenderFrameImpl::CreateChildFrame(
}
std::pair<blink::WebRemoteFrame*, base::UnguessableToken>
-RenderFrameImpl::CreatePortal(mojo::ScopedInterfaceEndpointHandle pipe) {
+RenderFrameImpl::CreatePortal(mojo::ScopedInterfaceEndpointHandle request,
+ mojo::ScopedInterfaceEndpointHandle client) {
int proxy_routing_id = MSG_ROUTING_NONE;
base::UnguessableToken portal_token;
+ base::UnguessableToken devtools_frame_token;
GetFrameHost()->CreatePortal(
- blink::mojom::PortalAssociatedRequest(std::move(pipe)), &proxy_routing_id,
- &portal_token);
- RenderFrameProxy* proxy =
- RenderFrameProxy::CreateProxyForPortal(this, proxy_routing_id);
+ blink::mojom::PortalAssociatedRequest(std::move(request)),
+ blink::mojom::PortalClientAssociatedPtrInfo(
+ std::move(client), blink::mojom::PortalClient::Version_),
+ &proxy_routing_id, &portal_token, &devtools_frame_token);
+ RenderFrameProxy* proxy = RenderFrameProxy::CreateProxyForPortal(
+ this, proxy_routing_id, devtools_frame_token);
return std::make_pair(proxy->web_frame(), portal_token);
}
blink::WebRemoteFrame* RenderFrameImpl::AdoptPortal(
const base::UnguessableToken& portal_token) {
int proxy_routing_id = MSG_ROUTING_NONE;
- GetFrameHost()->AdoptPortal(portal_token, &proxy_routing_id);
- RenderFrameProxy* proxy =
- RenderFrameProxy::CreateProxyForPortal(this, proxy_routing_id);
+ base::UnguessableToken devtools_frame_token;
+ GetFrameHost()->AdoptPortal(portal_token, &proxy_routing_id,
+ &devtools_frame_token);
+ RenderFrameProxy* proxy = RenderFrameProxy::CreateProxyForPortal(
+ this, proxy_routing_id, devtools_frame_token);
return proxy->web_frame();
}
@@ -4482,9 +4485,6 @@ void RenderFrameImpl::DidChangeName(const blink::WebString& name) {
unique_name_helper_.UpdateName(name.Utf8());
}
GetFrameHost()->DidChangeName(name.Utf8(), unique_name_helper_.value());
-
- if (!committed_first_load_)
- name_changed_before_first_commit_ = true;
}
void RenderFrameImpl::DidEnforceInsecureRequestPolicy(
@@ -4570,35 +4570,17 @@ void RenderFrameImpl::DidAddMessageToConsole(
const blink::WebString& source_name,
unsigned source_line,
const blink::WebString& stack_trace) {
- logging::LogSeverity log_severity = logging::LOG_VERBOSE;
- switch (message.level) {
- case blink::mojom::ConsoleMessageLevel::kVerbose:
- log_severity = logging::LOG_VERBOSE;
- break;
- case blink::mojom::ConsoleMessageLevel::kInfo:
- log_severity = logging::LOG_INFO;
- break;
- case blink::mojom::ConsoleMessageLevel::kWarning:
- log_severity = logging::LOG_WARNING;
- break;
- case blink::mojom::ConsoleMessageLevel::kError:
- log_severity = logging::LOG_ERROR;
- break;
- default:
- log_severity = logging::LOG_VERBOSE;
- }
-
if (ShouldReportDetailedMessageForSource(source_name)) {
for (auto& observer : observers_) {
observer.DetailedConsoleMessageAdded(
message.text.Utf16(), source_name.Utf16(), stack_trace.Utf16(),
- source_line, static_cast<uint32_t>(log_severity));
+ source_line, blink::ConsoleMessageLevelToLogSeverity(message.level));
}
}
- Send(new FrameHostMsg_DidAddMessageToConsole(
- routing_id_, static_cast<int32_t>(log_severity), message.text.Utf16(),
- static_cast<int32_t>(source_line), source_name.Utf16()));
+ GetFrameHost()->DidAddMessageToConsole(message.level, message.text.Utf16(),
+ static_cast<int32_t>(source_line),
+ source_name.Utf16());
}
void RenderFrameImpl::DownloadURL(
@@ -4633,8 +4615,7 @@ void RenderFrameImpl::DidCreateDocumentLoader(
DocumentState* document_state =
DocumentState::FromDocumentLoader(document_loader);
if (!document_state) {
- // This is either a placeholder document loader or an initial empty
- // document.
+ // This must be an initial empty document.
document_loader->SetExtraData(BuildDocumentState());
document_loader->SetServiceWorkerNetworkProvider(
ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance());
@@ -4675,44 +4656,6 @@ void RenderFrameImpl::DidCommitProvisionalLoad(
TRACE_EVENT2("navigation,rail", "RenderFrameImpl::didCommitProvisionalLoad",
"id", routing_id_,
"url", GetLoadingUrl().possibly_invalid_spec());
- // TODO(dcheng): Remove this UMA once we have enough measurements.
- // Record the number of subframes where window.name changes between the
- // creation of the frame and the first commit that records a history entry
- // with a persisted unique name. We'd like to make unique name immutable to
- // simplify code, but it's unclear if there are site that depend on the
- // following pattern:
- // 1. Create a new subframe.
- // 2. Assign it a window.name.
- // 3. Navigate it.
- //
- // If unique name are immutable, then it's possible that session history would
- // become less reliable for subframes:
- // * A subframe with no initial name will receive a generated name that
- // depends on DOM insertion order instead of using a name baed on the
- // window.name assigned in step 2.
- // * A subframe may intentionally try to choose a non-conflicting
- // window.name if it detects a conflict. Immutability would prevent this
- // from having the desired effect.
- //
- // The logic for when to record the UMA is a bit subtle:
- // * if |committed_first_load_| is false and |current_history_item_| is
- // null, then this is being called to commit the initial empty document.
- // Don't record the UMA yet. |current_history_item_| will be non-null in
- // subsequent invocations of this callback.
- // * if |committed_first_load_| is false and |current_history_item_| is
- // *not* null, then the initial empty document has already committed.
- // Record if window.name has changed.
- if (!committed_first_load_ && !current_history_item_.IsNull()) {
- if (!IsMainFrame()) {
- UMA_HISTOGRAM_BOOLEAN(
- "SessionRestore.SubFrameUniqueNameChangedBeforeFirstCommit",
- name_changed_before_first_commit_);
- }
- // TODO(dcheng): This signal is likely calculated incorrectly, and will be
- // removed in a followup CL (as we've decided to try to preserve backwards
- // compatibility as much as possible for the time being).
- committed_first_load_ = true;
- }
InternalDocumentStateData* internal_data =
InternalDocumentStateData::FromDocumentLoader(
@@ -4744,13 +4687,13 @@ void RenderFrameImpl::DidCommitProvisionalLoad(
if (is_main_frame_) {
GetLocalRootRenderWidget()->DidNavigate();
- // Update the URL used to key Ukm metrics in the compositor if the
- // navigation is not in the same document, which represents a new source
- // URL.
+ // Update the URL and the document source id used to key UKM metrics in the
+ // compositor if the navigation is not in the same document, which
+ // represents a new UKM source.
// Note that this is only done for the main frame since the metrics for all
// frames are keyed to the main frame's URL.
- GetLocalRootRenderWidget()->layer_tree_view()->SetURLForUkm(
- GetLoadingUrl());
+ GetLocalRootRenderWidget()->layer_tree_view()->SetSourceURL(
+ frame_->GetDocument().GetUkmSourceId(), GetLoadingUrl());
}
service_manager::mojom::InterfaceProviderRequest
@@ -5015,8 +4958,7 @@ void RenderFrameImpl::RunScriptsAtDocumentReady(bool document_is_empty) {
// delete |this|.
LoadNavigationErrorPage(document_loader,
WebURLError(net::ERR_FAILED, unreachable_url),
- error_html, true /* replace_current_item */,
- false /* inherit_document_state */);
+ error_html, true /* replace_current_item */);
if (!weak_self)
return;
// Do not use |this| or |frame_| here without checking |weak_self|.
@@ -5047,9 +4989,8 @@ void RenderFrameImpl::DidFailLoad(const WebURLError& error,
base::string16 error_description;
GetContentClient()->renderer()->GetErrorDescription(
error, document_loader->HttpMethod().Ascii(), &error_description);
- Send(new FrameHostMsg_DidFailLoadWithError(
- routing_id_, document_loader->GetUrl(), error.reason(),
- error_description));
+ GetFrameHost()->DidFailLoadWithError(document_loader->GetUrl(),
+ error.reason(), error_description);
}
void RenderFrameImpl::DidFinishLoad() {
@@ -5167,8 +5108,11 @@ void RenderFrameImpl::AbortClientNavigation() {
browser_side_navigation_pending_ = false;
sync_navigation_callback_.Cancel();
mhtml_body_loader_client_.reset();
- if (!IsPerNavigationMojoInterfaceEnabled())
+ if (!IsPerNavigationMojoInterfaceEnabled()) {
Send(new FrameHostMsg_AbortNavigation(routing_id_));
+ } else {
+ navigation_client_impl_.reset();
+ }
}
void RenderFrameImpl::DidChangeSelection(bool is_empty_selection) {
@@ -5358,10 +5302,6 @@ void RenderFrameImpl::WillSendRequestInternal(
old_extra_data->TakeNavigationResponseOverrideOwnership();
}
- // Set an empty HTTP origin header for non GET methods if none is currently
- // present.
- request.SetHttpOriginIfNeeded(WebSecurityOrigin::CreateUnique());
-
WebDocument frame_document = frame_->GetDocument();
if (!request.GetExtraData())
request.SetExtraData(std::make_unique<RequestExtraData>());
@@ -5381,6 +5321,8 @@ void RenderFrameImpl::WillSendRequestInternal(
extra_data->set_initiated_in_secure_context(frame_document.IsSecureContext());
extra_data->set_attach_same_site_cookies(attach_same_site_cookies);
extra_data->set_frame_request_blocker(frame_request_blocker_);
+ extra_data->set_allow_cross_origin_auth_prompt(
+ render_view_->renderer_preferences().allow_cross_origin_auth_prompt);
request.SetDownloadToNetworkCacheOnly(
is_for_no_state_prefetch && resource_type != ResourceType::kMainFrame);
@@ -5588,9 +5530,10 @@ void RenderFrameImpl::DidObserveNewCssPropertyUsage(int css_property,
observer.DidObserveNewCssPropertyUsage(css_property, is_animated);
}
-void RenderFrameImpl::DidObserveLayoutJank(double jank_fraction) {
+void RenderFrameImpl::DidObserveLayoutJank(double jank_fraction,
+ bool after_input_or_scroll) {
for (auto& observer : observers_)
- observer.DidObserveLayoutJank(jank_fraction);
+ observer.DidObserveLayoutJank(jank_fraction, after_input_or_scroll);
}
void RenderFrameImpl::DidObserveLazyLoadBehavior(
@@ -5635,13 +5578,6 @@ blink::WebPushClient* RenderFrameImpl::PushClient() {
return push_messaging_client_;
}
-blink::WebRelatedAppsFetcher* RenderFrameImpl::GetRelatedAppsFetcher() {
- if (!related_apps_fetcher_)
- related_apps_fetcher_.reset(new RelatedAppsFetcher(&GetManifestManager()));
-
- return related_apps_fetcher_.get();
-}
-
void RenderFrameImpl::WillStartUsingPeerConnectionHandler(
blink::WebRTCPeerConnectionHandler* handler) {
static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame_);
@@ -5672,14 +5608,7 @@ blink::WebString RenderFrameImpl::UserAgentOverride() {
WebLocalFrame* main_frame =
render_view_->webview()->MainFrame()->ToWebLocalFrame();
- // If we're in the middle of committing a load, the data source we need
- // will still be provisional.
- WebDocumentLoader* document_loader = nullptr;
- if (main_frame->GetProvisionalDocumentLoader())
- document_loader = main_frame->GetProvisionalDocumentLoader();
- else
- document_loader = main_frame->GetDocumentLoader();
-
+ WebDocumentLoader* document_loader = main_frame->GetDocumentLoader();
InternalDocumentStateData* internal_data =
document_loader
? InternalDocumentStateData::FromDocumentLoader(document_loader)
@@ -5718,9 +5647,10 @@ bool RenderFrameImpl::AllowContentInitiatedDataUrlNavigations(
}
void RenderFrameImpl::PostAccessibilityEvent(const blink::WebAXObject& obj,
- ax::mojom::Event event) {
+ ax::mojom::Event event,
+ ax::mojom::EventFrom event_from) {
if (render_accessibility_)
- render_accessibility_->HandleWebAccessibilityEvent(obj, event);
+ render_accessibility_->HandleWebAccessibilityEvent(obj, event, event_from);
}
void RenderFrameImpl::MarkWebAXObjectDirty(const blink::WebAXObject& obj,
@@ -5743,11 +5673,6 @@ void RenderFrameImpl::HandleAccessibilityFindInPageResult(
}
}
-void RenderFrameImpl::DidChangeManifest() {
- for (auto& observer : observers_)
- observer.DidChangeManifest();
-}
-
void RenderFrameImpl::EnterFullscreen(
const blink::WebFullscreenOptions& options) {
Send(new FrameHostMsg_EnterFullscreen(routing_id_, options));
@@ -5818,7 +5743,7 @@ void RenderFrameImpl::OnStop() {
void RenderFrameImpl::OnDroppedNavigation() {
browser_side_navigation_pending_ = false;
browser_side_navigation_pending_url_ = GURL();
- frame_->ClientDroppedNavigation();
+ frame_->DidDropNavigation();
}
void RenderFrameImpl::OnCollapse(bool collapsed) {
@@ -5826,6 +5751,7 @@ void RenderFrameImpl::OnCollapse(bool collapsed) {
}
void RenderFrameImpl::WasHidden() {
+ frame_->WasHidden();
for (auto& observer : observers_)
observer.WasHidden();
@@ -5836,6 +5762,7 @@ void RenderFrameImpl::WasHidden() {
}
void RenderFrameImpl::WasShown() {
+ frame_->WasShown();
for (auto& observer : observers_)
observer.WasShown();
@@ -6018,8 +5945,18 @@ RenderFrameImpl::MakeDidCommitProvisionalLoadParams(
if (params->origin.scheme() != url::kFileScheme ||
!render_view_->GetWebkitPreferences()
.allow_universal_access_from_file_urls) {
- CHECK(params->origin.IsSameOriginWith(url::Origin::Create(params->url)))
- << " url:" << params->url << " origin:" << params->origin;
+ if (!params->origin.IsSameOriginWith(url::Origin::Create(params->url))) {
+ base::debug::CrashKeyString* url = base::debug::AllocateCrashKeyString(
+ "mismatched_url", base::debug::CrashKeySize::Size256);
+ base::debug::CrashKeyString* origin =
+ base::debug::AllocateCrashKeyString(
+ "mismatched_origin", base::debug::CrashKeySize::Size256);
+ base::debug::ScopedCrashKeyString(url,
+ params->url.possibly_invalid_spec());
+ base::debug::ScopedCrashKeyString(origin,
+ params->origin.GetDebugString());
+ CHECK(false) << " url:" << params->url << " origin:" << params->origin;
+ }
}
}
params->request_id = internal_data->request_id();
@@ -6112,8 +6049,6 @@ void RenderFrameImpl::NotifyObserversOfNavigationCommit(
bool is_new_navigation,
bool is_same_document,
ui::PageTransition transition) {
- for (auto& observer : render_view_->observers_)
- observer.DidCommitProvisionalLoad(frame_, is_new_navigation);
for (auto& observer : observers_)
observer.DidCommitProvisionalLoad(is_same_document, transition);
}
@@ -6215,10 +6150,11 @@ void RenderFrameImpl::PrepareFrameForCommit(
}
blink::mojom::CommitResult RenderFrameImpl::PrepareForHistoryNavigationCommit(
- FrameMsg_Navigate_Type::Value navigation_type,
+ const CommonNavigationParams& common_params,
const CommitNavigationParams& commit_params,
WebHistoryItem* item_for_history_navigation,
blink::WebFrameLoadType* load_type) {
+ FrameMsg_Navigate_Type::Value navigation_type = common_params.navigation_type;
DCHECK(navigation_type == FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT ||
navigation_type ==
FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT ||
@@ -6260,13 +6196,22 @@ blink::mojom::CommitResult RenderFrameImpl::PrepareForHistoryNavigationCommit(
}
// If this navigation is to a history item for a new child frame, we may
- // want to ignore it in some cases. If a Javascript navigation (i.e.,
- // client redirect) interrupted it and has either been scheduled,
- // started loading, or has committed, we should ignore the history item.
+ // want to ignore it if a Javascript navigation (i.e., client redirect)
+ // interrupted it.
+ // To detect this we need to check for the interrupt at different stages of
+ // navigation:
bool interrupted_by_client_redirect =
- frame_->IsNavigationScheduledWithin(0) ||
- frame_->GetProvisionalDocumentLoader() || !current_history_item_.IsNull();
- if (commit_params.is_history_navigation_in_new_child &&
+ // IsNavigationScheduleWithin() checks that we have something just
+ // started, sent to the browser or loading.
+ (frame_->IsNavigationScheduledWithin(0) &&
+ // The current navigation however is just returning from the browser. To
+ // check that it is not the current navigation, we verify the "initial
+ // history navigation in a subframe" flag of ClientNavigationState.
+ !frame_->IsClientNavigationInitialHistoryLoad()) ||
+ // The client navigation could already have finished, in which case there
+ // will be an history item.
+ !current_history_item_.IsNull();
+ if (common_params.is_history_navigation_in_new_child_frame &&
interrupted_by_client_redirect) {
return blink::mojom::CommitResult::Aborted;
}
@@ -6347,12 +6292,11 @@ void RenderFrameImpl::DidChangeLoadProgress(double load_progress) {
Send(new FrameHostMsg_DidChangeLoadProgress(routing_id_, load_progress));
}
-void RenderFrameImpl::FocusedNodeChanged(const WebNode& node) {
+void RenderFrameImpl::FocusedElementChanged(const WebElement& element) {
has_scrolled_focused_editable_node_into_rect_ = false;
bool is_editable = false;
gfx::Rect node_bounds;
- if (!node.IsNull() && node.IsElementNode()) {
- WebElement element = const_cast<WebNode&>(node).To<WebElement>();
+ if (!element.IsNull()) {
blink::WebRect rect = element.BoundsInViewport();
GetLocalRootRenderWidget()->ConvertViewportToWindow(&rect);
is_editable = element.IsEditable();
@@ -6365,12 +6309,13 @@ void RenderFrameImpl::FocusedNodeChanged(const WebNode& node) {
GetLocalRootRenderWidget()->ClearTextInputState();
for (auto& observer : observers_)
- observer.FocusedNodeChanged(node);
+ observer.FocusedElementChanged(element);
}
-void RenderFrameImpl::FocusedNodeChangedForAccessibility(const WebNode& node) {
+void RenderFrameImpl::FocusedElementChangedForAccessibility(
+ const WebElement& element) {
if (render_accessibility())
- render_accessibility()->AccessibilityFocusedNodeChanged(node);
+ render_accessibility()->AccessibilityFocusedElementChanged(element);
}
void RenderFrameImpl::OnReportContentSecurityPolicyViolation(
@@ -6430,7 +6375,7 @@ void RenderFrameImpl::BeginNavigation(
if (IsTopLevelNavigation(frame_) &&
render_view_->renderer_preferences_
.browser_handles_all_top_level_requests) {
- OpenURL(std::move(info), /*is_history_navigation_in_new_child=*/false);
+ OpenURL(std::move(info));
return; // Suppress the load here.
}
@@ -6442,38 +6387,33 @@ void RenderFrameImpl::BeginNavigation(
// it, because it will only be used once as the frame is created.)
// Note: Skip this logic for MHTML files (|use_archive|), which should load
// their subframes from the archive and not from history.
+ bool is_history_navigation_in_new_child_frame = false;
if (info->is_history_navigation_in_new_child_frame && frame_->Parent() &&
!use_archive) {
// Check whether the browser has a history item for this frame that isn't
// just staying at the initial about:blank document.
- bool should_ask_browser = false;
RenderFrameImpl* parent = RenderFrameImpl::FromWebFrame(frame_->Parent());
auto iter = parent->history_subframe_unique_names_.find(
unique_name_helper_.value());
if (iter != parent->history_subframe_unique_names_.end()) {
bool history_item_is_about_blank = iter->second;
- should_ask_browser =
+ is_history_navigation_in_new_child_frame =
!history_item_is_about_blank || url != url::kAboutBlankURL;
parent->history_subframe_unique_names_.erase(iter);
}
+ }
- if (should_ask_browser) {
- // Don't do this if |info| also says it is a client redirect, in which
- // case JavaScript on the page is trying to interrupt the history
- // navigation.
- if (!info->is_client_redirect) {
- OpenURL(std::move(info), /*is_history_navigation_in_new_child=*/true);
- // TODO(japhet): This case wants to flag the frame as loading and do
- // nothing else. It'd be nice if it could go through the placeholder
- // DocumentLoader path, too.
- frame_->MarkAsLoading();
- return;
- }
+ if (is_history_navigation_in_new_child_frame) {
+ // Don't do this if |info| also says it is a client redirect, in which
+ // case JavaScript on the page is trying to interrupt the history
+ // navigation.
+ if (info->is_client_redirect) {
// Client redirects during an initial history load should attempt to
// cancel the history navigation. They will create a provisional
// document loader, causing the history load to be ignored in
// NavigateInternal, and this IPC will try to cancel any cross-process
// history load.
+ is_history_navigation_in_new_child_frame = false;
GetFrameHost()->CancelInitialHistoryLoad();
}
}
@@ -6522,7 +6462,7 @@ void RenderFrameImpl::BeginNavigation(
}
if (should_fork) {
- OpenURL(std::move(info), /*is_history_navigation_in_new_child=*/false);
+ OpenURL(std::move(info));
return; // Suppress the load here.
}
}
@@ -6559,29 +6499,44 @@ void RenderFrameImpl::BeginNavigation(
for (auto& observer : observers_)
observer.DidStartNavigation(url, info->navigation_type);
- // Navigations which require network request should be sent to the browser.
- if (!use_archive && IsURLHandledByNetworkStack(url)) {
- BeginNavigationInternal(std::move(info));
- return;
- }
-
- // First navigaiton in a frame to an empty document must be handled
+ // First navigation in a frame to an empty document must be handled
// synchronously.
- if (WebDocumentLoader::WillLoadUrlAsEmpty(url) &&
- !frame_->HasCommittedFirstRealLoad()) {
+ bool is_first_real_empty_document_navigation =
+ WebDocumentLoader::WillLoadUrlAsEmpty(url) &&
+ !frame_->HasCommittedFirstRealLoad();
+
+ if (is_first_real_empty_document_navigation &&
+ !is_history_navigation_in_new_child_frame) {
CommitSyncNavigation(std::move(info));
return;
}
- // Everything else (does not require networking, not an empty document)
- // will be committed asynchronously in the renderer.
- if (!frame_->CreatePlaceholderDocumentLoader(*info, BuildDocumentState()))
+ // Navigation to about:blank, about:srcdoc or to an MHTML archive don't need
+ // to consult the browser. The document content is already available in the
+ // renderer process.
+ // TODO(arthursonzogni): Remove this. Everything should use the default code
+ // path and be driven by the browser process.
+ if (use_archive || (((url == content::kAboutSrcDocURL) ||
+ WebDocumentLoader::WillLoadUrlAsEmpty(url)) &&
+ !is_history_navigation_in_new_child_frame)) {
+ if (!frame_->WillStartNavigation(
+ *info, false /* is_history_navigation_in_new_child_frame */))
+ return;
+ // Only the first navigation in a frame to an empty document must be
+ // handled synchronously, the others are required to happen
+ // asynchronously. So a PostTask is used.
+ sync_navigation_callback_.Reset(
+ base::BindOnce(&RenderFrameImpl::CommitSyncNavigation,
+ weak_factory_.GetWeakPtr(), base::Passed(&info)));
+ frame_->GetTaskRunner(blink::TaskType::kInternalLoading)
+ ->PostTask(FROM_HERE, sync_navigation_callback_.callback());
return;
- sync_navigation_callback_.Reset(
- base::BindOnce(&RenderFrameImpl::CommitSyncNavigation,
- weak_factory_.GetWeakPtr(), base::Passed(&info)));
- frame_->GetTaskRunner(blink::TaskType::kInternalLoading)
- ->PostTask(FROM_HERE, sync_navigation_callback_.callback());
+ }
+
+ // Everything else is handled asynchronously by the browser process through
+ // BeginNavigation.
+ BeginNavigationInternal(std::move(info),
+ is_history_navigation_in_new_child_frame);
return;
}
@@ -6592,7 +6547,7 @@ void RenderFrameImpl::BeginNavigation(
blink::WebLocalFrameClient::CrossOriginRedirects::kFollow,
blob_url_token.PassHandle());
} else {
- OpenURL(std::move(info), /*is_history_navigation_in_new_child=*/false);
+ OpenURL(std::move(info));
}
}
@@ -6777,8 +6732,8 @@ void RenderFrameImpl::OnMixedContentFound(
void RenderFrameImpl::OnSetOverlayRoutingToken(
const base::UnguessableToken& token) {
overlay_routing_token_ = token;
- for (const auto& cb : pending_routing_token_callbacks_)
- cb.Run(overlay_routing_token_.value());
+ for (auto& cb : pending_routing_token_callbacks_)
+ std::move(cb).Run(overlay_routing_token_.value());
pending_routing_token_callbacks_.clear();
}
@@ -6849,8 +6804,7 @@ void RenderFrameImpl::OnSelectPopupMenuItems(
#endif
#endif
-void RenderFrameImpl::OpenURL(std::unique_ptr<blink::WebNavigationInfo> info,
- bool is_history_navigation_in_new_child) {
+void RenderFrameImpl::OpenURL(std::unique_ptr<blink::WebNavigationInfo> info) {
// A valid RequestorOrigin is always expected to be present.
DCHECK(!info->url_request.RequestorOrigin().IsNull());
@@ -6886,9 +6840,6 @@ void RenderFrameImpl::OpenURL(std::unique_ptr<blink::WebNavigationInfo> info,
WebUserGestureIndicator::ConsumeUserGesture(frame_);
}
- if (is_history_navigation_in_new_child)
- params.is_history_navigation_in_new_child = true;
-
params.href_translate = info->href_translate.Latin1();
bool current_frame_has_download_sandbox_flag =
@@ -7077,11 +7028,6 @@ void RenderFrameImpl::PrepareRenderViewForNavigation(
const CommitNavigationParams& commit_params) {
DCHECK(render_view_->webview());
- if (is_main_frame_) {
- for (auto& observer : render_view_->observers_)
- observer.Navigate(url);
- }
-
render_view_->history_list_offset_ =
commit_params.current_history_list_offset;
render_view_->history_list_length_ =
@@ -7112,13 +7058,12 @@ std::unique_ptr<base::DictionaryValue> GetDevToolsInitiator(
} // namespace
void RenderFrameImpl::BeginNavigationInternal(
- std::unique_ptr<blink::WebNavigationInfo> info) {
- std::unique_ptr<DocumentState> document_state_owned = BuildDocumentState();
- DocumentState* document_state = document_state_owned.get();
- if (!frame_->CreatePlaceholderDocumentLoader(
- *info, std::move(document_state_owned))) {
+ std::unique_ptr<blink::WebNavigationInfo> info,
+ bool is_history_navigation_in_new_child_frame) {
+ std::unique_ptr<DocumentState> document_state = BuildDocumentState();
+ if (!frame_->WillStartNavigation(*info,
+ is_history_navigation_in_new_child_frame))
return;
- }
browser_side_navigation_pending_ = true;
browser_side_navigation_pending_url_ = info->url_request.Url();
@@ -7154,7 +7099,7 @@ void RenderFrameImpl::BeginNavigationInternal(
WillSendRequestInternal(
request,
frame_->Parent() ? ResourceType::kSubFrame : ResourceType::kMainFrame,
- document_state, transition_type);
+ document_state.get(), transition_type);
if (!info->url_request.GetExtraData())
info->url_request.SetExtraData(std::make_unique<RequestExtraData>());
@@ -7180,6 +7125,9 @@ void RenderFrameImpl::BeginNavigationInternal(
info->navigation_type == blink::kWebNavigationTypeFormSubmitted ||
info->navigation_type == blink::kWebNavigationTypeFormResubmitted;
+ bool was_initiated_by_link_click =
+ info->navigation_type == blink::kWebNavigationTypeLinkClicked;
+
GURL searchable_form_url;
std::string searchable_form_encoding;
if (!info->form.IsNull()) {
@@ -7204,8 +7152,8 @@ void RenderFrameImpl::BeginNavigationInternal(
info->url_request.GetSkipServiceWorker(),
GetRequestContextTypeForWebURLRequest(info->url_request),
GetMixedContentContextTypeForWebURLRequest(info->url_request),
- is_form_submission, searchable_form_url, searchable_form_encoding,
- client_side_redirect_url,
+ is_form_submission, was_initiated_by_link_click, searchable_form_url,
+ searchable_form_encoding, client_side_redirect_url,
initiator ? base::make_optional<base::Value>(std::move(*initiator))
: base::nullopt);
@@ -7228,8 +7176,8 @@ void RenderFrameImpl::BeginNavigationInternal(
GetFrameHost()->BeginNavigation(
MakeCommonNavigationParams(frame_->GetSecurityOrigin(), std::move(info),
- load_flags, has_download_sandbox_flag,
- from_ad),
+ load_flags, has_download_sandbox_flag, from_ad,
+ is_history_navigation_in_new_child_frame),
std::move(begin_navigation_params), std::move(blob_url_token),
std::move(navigation_client_info), std::move(initiator_ptr));
}
@@ -7282,13 +7230,11 @@ void RenderFrameImpl::SendFailedProvisionalLoad(const std::string& http_method,
bool show_repost_interstitial =
error.reason() == net::ERR_CACHE_MISS && http_method == "POST";
- FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
- params.error_code = error.reason();
- GetContentClient()->renderer()->GetErrorDescription(
- error, http_method, &params.error_description);
- params.url = error.url(),
- params.showing_repost_interstitial = show_repost_interstitial;
- Send(new FrameHostMsg_DidFailProvisionalLoadWithError(routing_id_, params));
+ base::string16 error_description;
+ GetContentClient()->renderer()->GetErrorDescription(error, http_method,
+ &error_description);
+ GetFrameHost()->DidFailProvisionalLoadWithError(
+ error.url(), error.reason(), error_description, show_repost_interstitial);
}
bool RenderFrameImpl::ShouldDisplayErrorPageForFailedLoad(
@@ -7368,15 +7314,15 @@ void RenderFrameImpl::HandlePepperImeCommit(const base::string16& text) {
#endif // ENABLE_PLUGINS
void RenderFrameImpl::RegisterMojoInterfaces() {
- GetAssociatedInterfaceRegistry()->AddInterface(base::Bind(
+ GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating(
&RenderFrameImpl::BindAutoplayConfiguration, weak_factory_.GetWeakPtr()));
- GetAssociatedInterfaceRegistry()->AddInterface(base::Bind(
+ GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating(
&RenderFrameImpl::BindFrameBindingsControl, weak_factory_.GetWeakPtr()));
GetAssociatedInterfaceRegistry()->AddInterface(
- base::Bind(&RenderFrameImpl::BindFrameNavigationControl,
- weak_factory_.GetWeakPtr()));
+ base::BindRepeating(&RenderFrameImpl::BindFrameNavigationControl,
+ weak_factory_.GetWeakPtr()));
if (IsPerNavigationMojoInterfaceEnabled()) {
GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating(
@@ -7386,32 +7332,27 @@ void RenderFrameImpl::RegisterMojoInterfaces() {
GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating(
&RenderFrameImpl::BindFullscreen, weak_factory_.GetWeakPtr()));
- registry_.AddInterface(base::Bind(&FrameInputHandlerImpl::CreateMojoService,
- weak_factory_.GetWeakPtr()));
+ registry_.AddInterface(base::BindRepeating(
+ &FrameInputHandlerImpl::CreateMojoService, weak_factory_.GetWeakPtr()));
registry_.AddInterface(
- base::Bind(&InputTargetClientImpl::BindToRequest,
- base::Unretained(&input_target_client_impl_)));
+ base::BindRepeating(&InputTargetClientImpl::BindToRequest,
+ base::Unretained(&input_target_client_impl_)));
- registry_.AddInterface(
- base::Bind(&RenderFrameImpl::BindWidget, weak_factory_.GetWeakPtr()));
+ registry_.AddInterface(base::BindRepeating(&RenderFrameImpl::BindWidget,
+ weak_factory_.GetWeakPtr()));
GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating(
&RenderFrameImpl::BindMhtmlFileWriter, base::Unretained(this)));
if (!frame_->Parent()) {
// Only main frame have ImageDownloader service.
- registry_.AddInterface(base::Bind(&ImageDownloaderImpl::CreateMojoService,
- base::Unretained(this)));
+ registry_.AddInterface(base::BindRepeating(
+ &ImageDownloaderImpl::CreateMojoService, base::Unretained(this)));
// Host zoom is per-page, so only added on the main frame.
- GetAssociatedInterfaceRegistry()->AddInterface(base::Bind(
+ GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating(
&RenderFrameImpl::OnHostZoomClientRequest, weak_factory_.GetWeakPtr()));
-
- // Web manifests are only requested for main frames.
- registry_.AddInterface(
- base::Bind(&ManifestManager::BindToRequest,
- base::Unretained(manifest_manager_.get())));
}
}
@@ -7463,7 +7404,7 @@ void RenderFrameImpl::ScrollRectToVisibleInParentFrame(
void RenderFrameImpl::BubbleLogicalScrollInParentFrame(
blink::WebScrollDirection direction,
- blink::WebScrollGranularity granularity) {
+ ui::input_types::ScrollGranularity granularity) {
DCHECK(IsLocalRoot());
DCHECK(!IsMainFrame());
Send(new FrameHostMsg_BubbleLogicalScrollInParentFrame(routing_id_, direction,
@@ -7723,4 +7664,24 @@ void RenderFrameImpl::AbortCommitNavigation(
}
}
+void RenderFrameImpl::TransferUserActivationFrom(
+ blink::WebLocalFrame* source_frame) {
+ int32_t source_routing_id = MSG_ROUTING_NONE;
+ if (source_frame) {
+ RenderFrameImpl* source_render_frame =
+ RenderFrameImpl::FromWebFrame(source_frame);
+ source_routing_id = source_render_frame->GetRoutingID();
+ Send(new FrameHostMsg_TransferUserActivationFrom(routing_id_,
+ source_routing_id));
+ }
+}
+
+void RenderFrameImpl::AddMessageToConsoleImpl(
+ blink::mojom::ConsoleMessageLevel level,
+ const std::string& message,
+ bool discard_duplicates) {
+ blink::WebConsoleMessage wcm(level, WebString::FromUTF8(message));
+ frame_->AddMessageToConsole(wcm, discard_duplicates);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h
index d35cfb8dd67..b1241cfbe4c 100644
--- a/chromium/content/renderer/render_frame_impl.h
+++ b/chromium/content/renderer/render_frame_impl.h
@@ -81,7 +81,6 @@
#include "third_party/blink/public/mojom/commit_result/commit_result.mojom.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
-#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/platform/web_effective_connection_type.h"
@@ -121,7 +120,6 @@ class WebElement;
class WebLayerTreeView;
class WebLocalFrame;
class WebPushClient;
-class WebRelatedAppsFetcher;
class WebSecurityOrigin;
class WebString;
class WebURL;
@@ -161,13 +159,11 @@ class CompositorDependencies;
class DocumentState;
class ExternalPopupMenu;
class FrameRequestBlocker;
-class ManifestManager;
class MediaPermissionDispatcher;
class MediaStreamDeviceObserver;
class NavigationClient;
class PepperPluginInstanceImpl;
class PushMessagingClient;
-class RelatedAppsFetcher;
class RenderAccessibilityImpl;
class RendererPpapiHost;
class RenderFrameObserver;
@@ -360,14 +356,14 @@ class CONTENT_EXPORT RenderFrameImpl
void HandleWebAccessibilityEvent(const blink::WebAXObject& obj,
ax::mojom::Event event);
- // The focused node changed to |node|. If focus was lost from this frame,
- // |node| will be null.
- void FocusedNodeChanged(const blink::WebNode& node);
+ // The focused element changed to |element|. If focus was lost from this
+ // frame, |element| will be null.
+ void FocusedElementChanged(const blink::WebElement& element);
// TODO(dmazzoni): the only reason this is here is to plumb it through to
// RenderAccessibilityImpl. It should use the RenderFrameObserver method, once
// blink has a separate accessibility tree per frame.
- void FocusedNodeChangedForAccessibility(const blink::WebNode& node);
+ void FocusedElementChangedForAccessibility(const blink::WebElement& element);
// A RenderView opened by this RenderFrame needs to be shown.
void ShowCreatedWindow(bool opened_by_user_gesture,
@@ -468,7 +464,6 @@ class CONTENT_EXPORT RenderFrameImpl
int ShowContextMenu(ContextMenuClient* client,
const ContextMenuParams& params) override;
void CancelContextMenu(int request_id) override;
- void BindToFrame(blink::WebNavigationControl* frame) override;
blink::WebPlugin* CreatePlugin(
const WebPluginInfo& info,
const blink::WebPluginParams& params,
@@ -484,9 +479,8 @@ class CONTENT_EXPORT RenderFrameImpl
blink::AssociatedInterfaceRegistry* GetAssociatedInterfaceRegistry() override;
blink::AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override;
#if BUILDFLAG(ENABLE_PLUGINS)
- void RegisterPeripheralPlugin(
- const url::Origin& content_origin,
- const base::Closure& unthrottle_callback) override;
+ void RegisterPeripheralPlugin(const url::Origin& content_origin,
+ base::OnceClosure unthrottle_callback) override;
RenderFrame::PeripheralContentStatus GetPeripheralContentStatus(
const url::Origin& main_frame_origin,
const url::Origin& content_origin,
@@ -538,10 +532,6 @@ class CONTENT_EXPORT RenderFrameImpl
void BlockRequests() override;
void ResumeBlockedRequests() override;
void CancelBlockedRequests() override;
- void ForwardMessageToPortalHost(
- blink::TransferableMessage message,
- const url::Origin& source_origin,
- const base::Optional<url::Origin>& target_origin) override;
void SetLifecycleState(blink::mojom::FrameLifecycleState state) override;
#if defined(OS_ANDROID)
@@ -558,6 +548,10 @@ class CONTENT_EXPORT RenderFrameImpl
const base::string16& source_origin,
const base::string16& target_origin,
blink::TransferableMessage message) override;
+ void ForwardMessageFromHost(
+ blink::TransferableMessage message,
+ const url::Origin& source_origin,
+ const base::Optional<url::Origin>& target_origin) override;
// mojom::FrameNavigationControl implementation:
void CommitNavigation(
@@ -650,10 +644,12 @@ class CONTENT_EXPORT RenderFrameImpl
bool wants_result,
int32_t world_id,
JavaScriptExecuteRequestInIsolatedWorldCallback callback) override;
- void OnPortalActivated(const base::UnguessableToken& portal_token,
- blink::mojom::PortalAssociatedPtrInfo portal,
- blink::TransferableMessage data,
- OnPortalActivatedCallback callback) override;
+ void OnPortalActivated(
+ const base::UnguessableToken& portal_token,
+ blink::mojom::PortalAssociatedPtrInfo portal,
+ blink::mojom::PortalClientAssociatedRequest portal_client,
+ blink::TransferableMessage data,
+ OnPortalActivatedCallback callback) override;
// mojom::FullscreenVideoElementHandler implementation:
void RequestFullscreenVideoElement() override;
@@ -666,6 +662,7 @@ class CONTENT_EXPORT RenderFrameImpl
SerializeAsMHTMLCallback callback) override;
// blink::WebLocalFrameClient implementation:
+ void BindToFrame(blink::WebNavigationControl* frame) override;
blink::WebPlugin* CreatePlugin(const blink::WebPluginParams& params) override;
blink::WebMediaPlayer* CreateMediaPlayer(
const blink::WebMediaPlayerSource& source,
@@ -704,7 +701,8 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebFrameOwnerProperties& frame_owner_properties,
blink::FrameOwnerElementType frame_owner_element_type) override;
std::pair<blink::WebRemoteFrame*, base::UnguessableToken> CreatePortal(
- mojo::ScopedInterfaceEndpointHandle request) override;
+ mojo::ScopedInterfaceEndpointHandle request,
+ mojo::ScopedInterfaceEndpointHandle client) override;
blink::WebRemoteFrame* AdoptPortal(
const base::UnguessableToken& portal_token) override;
blink::WebFrame* FindFrame(const blink::WebString& name) override;
@@ -752,7 +750,7 @@ class CONTENT_EXPORT RenderFrameImpl
void DidStartProvisionalLoad(
blink::WebDocumentLoader* document_loader) override;
void DidFailProvisionalLoad(const blink::WebURLError& error,
- blink::WebHistoryCommitType commit_type) override;
+ const blink::WebString& http_method) override;
void DidCommitProvisionalLoad(
const blink::WebHistoryItem& item,
blink::WebHistoryCommitType commit_type,
@@ -819,7 +817,8 @@ class CONTENT_EXPORT RenderFrameImpl
void DidObserveNewFeatureUsage(blink::mojom::WebFeature feature) override;
void DidObserveNewCssPropertyUsage(int css_property,
bool is_animated) override;
- void DidObserveLayoutJank(double jank_fraction) override;
+ void DidObserveLayoutJank(double jank_fraction,
+ bool after_input_or_scroll) override;
void DidObserveLazyLoadBehavior(
blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) override;
bool ShouldTrackUseCounter(const blink::WebURL& url) override;
@@ -829,7 +828,6 @@ class CONTENT_EXPORT RenderFrameImpl
int world_id) override;
void DidChangeScrollOffset() override;
blink::WebPushClient* PushClient() override;
- blink::WebRelatedAppsFetcher* GetRelatedAppsFetcher() override;
void WillStartUsingPeerConnectionHandler(
blink::WebRTCPeerConnectionHandler* handler) override;
blink::WebUserMediaClient* UserMediaClient() override;
@@ -841,7 +839,8 @@ class CONTENT_EXPORT RenderFrameImpl
bool AllowContentInitiatedDataUrlNavigations(
const blink::WebURL& url) override;
void PostAccessibilityEvent(const blink::WebAXObject& obj,
- ax::mojom::Event event) override;
+ ax::mojom::Event event,
+ ax::mojom::EventFrom event_from) override;
void MarkWebAXObjectDirty(const blink::WebAXObject& obj,
bool subtree) override;
void HandleAccessibilityFindInPageResult(int identifier,
@@ -850,7 +849,6 @@ class CONTENT_EXPORT RenderFrameImpl
int start_offset,
const blink::WebNode& end_node,
int end_offset) override;
- void DidChangeManifest() override;
void EnterFullscreen(const blink::WebFullscreenOptions& options) override;
void ExitFullscreen() override;
void FullscreenStateChanged(bool is_fullscreen) override;
@@ -875,7 +873,7 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebScrollIntoViewParams& params) override;
void BubbleLogicalScrollInParentFrame(
blink::WebScrollDirection direction,
- blink::WebScrollGranularity granularity) override;
+ ui::input_types::ScrollGranularity granularity) override;
void VisibilityChanged(blink::mojom::FrameVisibility visibility) override;
// WebFrameSerializerClient implementation:
@@ -909,8 +907,6 @@ class CONTENT_EXPORT RenderFrameImpl
// Only used when PerNavigationMojoInterface is enabled.
void BindNavigationClient(mojom::NavigationClientAssociatedRequest request);
- blink::mojom::ManifestManager& GetManifestManager();
-
media::MediaPermission* GetMediaPermission();
// Sends the current frame's navigation state to the browser.
@@ -993,6 +989,8 @@ class CONTENT_EXPORT RenderFrameImpl
void DidCancelResponse(int request_id);
void DidReceiveTransferSizeUpdate(int request_id, int received_data_length);
+ void TransferUserActivationFrom(blink::WebLocalFrame* source_frame) override;
+
// Used in tests to override DocumentInterfaceBroker's methods
void SetDocumentInterfaceBrokerForTesting(
blink::mojom::DocumentInterfaceBrokerPtr test_broker);
@@ -1130,7 +1128,8 @@ class CONTENT_EXPORT RenderFrameImpl
void OnCopyImageAt(int x, int y);
void OnSaveImageAt(int x, int y);
void OnAddMessageToConsole(blink::mojom::ConsoleMessageLevel level,
- const std::string& message);
+ const std::string& message,
+ bool discard_duplicates);
void OnVisualStateRequest(uint64_t key);
void OnReload(bool bypass_cache);
void OnReloadLoFiImages();
@@ -1182,12 +1181,8 @@ class CONTENT_EXPORT RenderFrameImpl
base::TimeDelta main_thread_use_time,
mojom::MhtmlSaveStatus save_status);
- // Requests that the browser process navigates to |url|. If
- // |is_history_navigation_in_new_child| is true, the browser process should
- // look for a matching FrameNavigationEntry in the last committed entry to use
- // instead of |url|.
- void OpenURL(std::unique_ptr<blink::WebNavigationInfo> info,
- bool is_history_navigation_in_new_child);
+ // Requests that the browser process navigates to |url|.
+ void OpenURL(std::unique_ptr<blink::WebNavigationInfo> info);
// Returns a ChildURLLoaderFactoryBundle which can be used to request
// subresources for this frame.
@@ -1228,8 +1223,7 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebDocumentLoader* document_loader,
const blink::WebURLError& error,
const base::Optional<std::string>& error_page_content,
- bool replace_current_item,
- bool inherit_document_state);
+ bool replace_current_item);
base::Value GetJavaScriptExecutionResult(v8::Local<v8::Value> result);
@@ -1244,10 +1238,11 @@ class CONTENT_EXPORT RenderFrameImpl
const CommitNavigationParams& commit_params);
// Sends a FrameHostMsg_BeginNavigation to the browser
- void BeginNavigationInternal(std::unique_ptr<blink::WebNavigationInfo> info);
+ void BeginNavigationInternal(std::unique_ptr<blink::WebNavigationInfo> info,
+ bool is_history_navigation_in_new_child_frame);
// Commit a navigation that isn't handled by the browser (e.g., an empty
- // document or an MHTML archive).
+ // document, about:srcdoc or an MHTML archive).
void CommitSyncNavigation(std::unique_ptr<blink::WebNavigationInfo> info);
// Commit navigation with |navigation_params| prepared.
@@ -1279,7 +1274,7 @@ class CONTENT_EXPORT RenderFrameImpl
std::string* data,
GURL* base_url);
- // Sends a proper FrameHostMsg_DidFailProvisionalLoadWithError_Params IPC for
+ // Sends a proper DidFailProvisionalLoadWithError mojo IPC for
// the failed provisional load.
void SendFailedProvisionalLoad(const std::string& http_method,
const blink::WebURLError& error,
@@ -1367,7 +1362,7 @@ class CONTENT_EXPORT RenderFrameImpl
std::unique_ptr<blink::WebSocketHandshakeThrottle>
CreateWebSocketHandshakeThrottle() override;
- bool MaybeCreateMimeHandlerView(
+ bool IsPluginHandledExternally(
const blink::WebElement& plugin_element,
const blink::WebURL& url,
const blink::WebString& suggested_mime_type) override;
@@ -1375,6 +1370,9 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebElement& plugin_element,
v8::Isolate* isolate) override;
+ void UpdateSubresourceFactory(
+ std::unique_ptr<blink::URLLoaderFactoryBundleInfo> info) override;
+
// Updates the state of this frame when asked to commit a navigation.
void PrepareFrameForCommit(const GURL& url,
const CommitNavigationParams& commit_params);
@@ -1404,7 +1402,7 @@ class CONTENT_EXPORT RenderFrameImpl
// When this happens, the navigation will be sent back to the browser process
// so that it can be performed in cross-document fashion.
blink::mojom::CommitResult PrepareForHistoryNavigationCommit(
- FrameMsg_Navigate_Type::Value navigation_type,
+ const CommonNavigationParams& common_params,
const CommitNavigationParams& commit_params,
blink::WebHistoryItem* item_for_history_navigation,
blink::WebFrameLoadType* load_type);
@@ -1460,6 +1458,11 @@ class CONTENT_EXPORT RenderFrameImpl
mojom::FrameNavigationControl::CommitNavigationCallback callback,
blink::mojom::CommitResult reason);
+ // Implements AddMessageToConsole().
+ void AddMessageToConsoleImpl(blink::mojom::ConsoleMessageLevel level,
+ const std::string& message,
+ bool discard_duplicates);
+
// Stores the WebLocalFrame we are associated with. This is null from the
// constructor until BindToFrame() is called, and it is null after
// FrameDetached() is called until destruction (which is asynchronous in the
@@ -1608,10 +1611,6 @@ class CONTENT_EXPORT RenderFrameImpl
// The Connector proxy used to connect to services.
service_manager::mojom::ConnectorPtr connector_;
- // The Manifest Manager handles the manifest requests from the browser
- // process.
- std::unique_ptr<ManifestManager> manifest_manager_;
-
// The current accessibility mode.
ui::AXMode accessibility_mode_;
@@ -1619,8 +1618,6 @@ class CONTENT_EXPORT RenderFrameImpl
// flag set.
RenderAccessibilityImpl* render_accessibility_;
- std::unique_ptr<RelatedAppsFetcher> related_apps_fetcher_;
-
// The PreviewsState of this RenderFrame that indicates which Previews can
// be used. The PreviewsState is a bitmask of potentially several Previews
// optimizations.
@@ -1693,10 +1690,9 @@ class CONTENT_EXPORT RenderFrameImpl
std::unique_ptr<blink::AssociatedInterfaceProvider>
remote_associated_interfaces_;
- // TODO(dcheng): Remove these members.
- bool committed_first_load_ = false;
- bool name_changed_before_first_commit_ = false;
-
+ // This flag is true while browser process is processing a pending navigation,
+ // as a result of mojom::FrameHost::BeginNavigation call. It is reset when the
+ // navigation is either committed or cancelled.
bool browser_side_navigation_pending_ = false;
GURL browser_side_navigation_pending_url_;
@@ -1768,6 +1764,12 @@ class CONTENT_EXPORT RenderFrameImpl
RenderFrameMediaPlaybackOptions renderer_media_playback_options_;
+ // Used by renderer initiated navigations not driven by the browser process:
+ // - navigation to about:blank.
+ // - navigation to about:srcdoc.
+ // - navigation using an MHTML archive.
+ // TODO(arthursonzogni): Remove this. Everything should use the default code
+ // path and be driven by the browser process.
base::CancelableOnceCallback<void()> sync_navigation_callback_;
class MHTMLBodyLoaderClient;
diff --git a/chromium/content/renderer/render_frame_impl_browsertest.cc b/chromium/content/renderer/render_frame_impl_browsertest.cc
index c994c84d377..2a006f42a56 100644
--- a/chromium/content/renderer/render_frame_impl_browsertest.cc
+++ b/chromium/content/renderer/render_frame_impl_browsertest.cc
@@ -10,6 +10,7 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/debug/leak_annotations.h"
+#include "base/optional.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -230,7 +231,7 @@ TEST_F(RenderFrameImplTest, FrameWasShown) {
WidgetMsg_WasShown was_shown_message(
0, base::TimeTicks(), false /* was_evicted */,
- base::TimeTicks() /* tab_switch_start_time */);
+ base::nullopt /* tab_switch_start_state */);
frame_widget()->OnMessageReceived(was_shown_message);
EXPECT_FALSE(frame_widget()->is_hidden());
@@ -269,7 +270,7 @@ TEST_F(RenderFrameImplTest, LocalChildFrameWasShown) {
WidgetMsg_WasShown was_shown_message(
0, base::TimeTicks(), false /* was_evicted */,
- base::TimeTicks() /* tab_switch_start_time */);
+ base::nullopt /* tab_switch_start_state */);
frame_widget()->OnMessageReceived(was_shown_message);
EXPECT_FALSE(frame_widget()->is_hidden());
@@ -507,8 +508,8 @@ TEST_F(RenderFrameImplTest, TestOverlayRoutingTokenSendsLater) {
ASSERT_FALSE(overlay_routing_token_.has_value());
frame()->RequestOverlayRoutingToken(
- base::Bind(&RenderFrameImplTest::ReceiveOverlayRoutingToken,
- base::Unretained(this)));
+ base::BindOnce(&RenderFrameImplTest::ReceiveOverlayRoutingToken,
+ base::Unretained(this)));
ASSERT_FALSE(overlay_routing_token_.has_value());
// The host should receive a request for it sent to the frame.
@@ -537,8 +538,8 @@ TEST_F(RenderFrameImplTest, TestOverlayRoutingTokenSendsNow) {
// returning or posts a message.
base::RunLoop().RunUntilIdle();
frame()->RequestOverlayRoutingToken(
- base::Bind(&RenderFrameImplTest::ReceiveOverlayRoutingToken,
- base::Unretained(this)));
+ base::BindOnce(&RenderFrameImplTest::ReceiveOverlayRoutingToken,
+ base::Unretained(this)));
ASSERT_TRUE(overlay_routing_token_.has_value());
ASSERT_EQ(overlay_routing_token_.value(), token);
@@ -861,6 +862,9 @@ class TestSimpleDocumentInterfaceBrokerImpl
void GetVirtualAuthenticatorManager(
blink::test::mojom::VirtualAuthenticatorManagerRequest request) override {
}
+ void RegisterAppCacheHost(blink::mojom::AppCacheHostRequest host_request,
+ blink::mojom::AppCacheFrontendPtr frontend,
+ const base::UnguessableToken& id) override {}
mojo::Binding<blink::mojom::DocumentInterfaceBroker> binding_;
BinderCallback binder_callback_;
@@ -1196,52 +1200,37 @@ class RenderFrameRemoteInterfacesTest : public RenderViewTest {
// DocumentInterfaceBroker, InterfaceProviderRequest-related code will be
// removed.
TEST_F(RenderFrameRemoteInterfacesTest, ChildFrameAtFirstCommittedLoad) {
- constexpr struct {
- const char* main_frame_url_override;
- const char* child_frame_url;
- } kTestCases[] = {
- {kTestFirstURL, kAboutBlankURL},
- {kTestSecondURL, "data:text/html,Child"},
- {kAboutBlankURL, kAboutBlankURL},
- };
-
- for (const auto& test_case : kTestCases) {
- SCOPED_TRACE(::testing::Message()
- << "main_frame_url = " << test_case.main_frame_url_override
- << ", child_frame_url = " << test_case.child_frame_url);
-
- ScopedNewFrameInterfaceProviderExerciser child_frame_exerciser(
- frame_creation_observer());
- const std::string html = base::StringPrintf("<iframe src=\"%s\"></iframe>",
- test_case.child_frame_url);
- LoadHTMLWithUrlOverride(html.c_str(), test_case.main_frame_url_override);
+ ScopedNewFrameInterfaceProviderExerciser child_frame_exerciser(
+ frame_creation_observer());
+ const std::string html = base::StringPrintf("<iframe src=\"%s\"></iframe>",
+ "data:text/html,Child");
+ LoadHTMLWithUrlOverride(html.c_str(), kTestSecondURL);
- const GURL child_frame_url(test_case.child_frame_url);
- ASSERT_NO_FATAL_FAILURE(
- child_frame_exerciser.ExpectNewFrameAndWaitForLoad(child_frame_url));
+ const GURL child_frame_url("data:text/html,Child");
+ ASSERT_NO_FATAL_FAILURE(
+ child_frame_exerciser.ExpectNewFrameAndWaitForLoad(child_frame_url));
- // TODO(https://crbug.com/792410): It is unfortunate how many internal
- // details of frame/document creation this encodes. Need to decouple.
- const GURL initial_empty_url(kAboutBlankURL);
- ExpectPendingInterfaceRequestsFromSources(
- child_frame_exerciser.interface_request_for_initial_empty_document(),
- child_frame_exerciser
- .document_interface_broker_request_for_initial_empty_document(),
- {{GURL(kNoDocumentMarkerURL), kFrameEventDidCreateNewFrame},
- {initial_empty_url, kFrameEventDidCreateNewDocument},
- {initial_empty_url, kFrameEventDidCreateDocumentElement},
- {initial_empty_url, kFrameEventReadyToCommitNavigation},
- // TODO(https://crbug.com/555773): It seems strange that the new
- // document is created and DidCreateNewDocument is invoked *before* the
- // provisional load would have even committed.
- {child_frame_url, kFrameEventDidCreateNewDocument}});
- ExpectPendingInterfaceRequestsFromSources(
- child_frame_exerciser.interface_request_for_first_document(),
- child_frame_exerciser
- .document_interface_broker_request_for_first_document(),
- {{child_frame_url, kFrameEventDidCommitProvisionalLoad},
- {child_frame_url, kFrameEventDidCreateDocumentElement}});
- }
+ // TODO(https://crbug.com/792410): It is unfortunate how many internal
+ // details of frame/document creation this encodes. Need to decouple.
+ const GURL initial_empty_url(kAboutBlankURL);
+ ExpectPendingInterfaceRequestsFromSources(
+ child_frame_exerciser.interface_request_for_initial_empty_document(),
+ child_frame_exerciser
+ .document_interface_broker_request_for_initial_empty_document(),
+ {{GURL(kNoDocumentMarkerURL), kFrameEventDidCreateNewFrame},
+ {initial_empty_url, kFrameEventDidCreateNewDocument},
+ {initial_empty_url, kFrameEventDidCreateDocumentElement},
+ {initial_empty_url, kFrameEventReadyToCommitNavigation},
+ // TODO(https://crbug.com/555773): It seems strange that the new
+ // document is created and DidCreateNewDocument is invoked *before* the
+ // provisional load would have even committed.
+ {child_frame_url, kFrameEventDidCreateNewDocument}});
+ ExpectPendingInterfaceRequestsFromSources(
+ child_frame_exerciser.interface_request_for_first_document(),
+ child_frame_exerciser
+ .document_interface_broker_request_for_first_document(),
+ {{child_frame_url, kFrameEventDidCommitProvisionalLoad},
+ {child_frame_url, kFrameEventDidCreateDocumentElement}});
}
// Expect that |remote_interfaces_| is bound before the first committed load in
@@ -1251,59 +1240,44 @@ TEST_F(RenderFrameRemoteInterfacesTest, ChildFrameAtFirstCommittedLoad) {
// removed.
TEST_F(RenderFrameRemoteInterfacesTest,
MainFrameOfOpenedWindowAtFirstCommittedLoad) {
- constexpr struct {
- const char* main_frame_url_override;
- const char* new_window_url;
- } kTestCases[] = {
- {kTestFirstURL, kAboutBlankURL},
- {kTestSecondURL, "data:text/html,NewWindow"},
- {kAboutBlankURL, kAboutBlankURL},
- };
-
- for (const auto& test_case : kTestCases) {
- SCOPED_TRACE(::testing::Message()
- << "main_frame_url = " << test_case.main_frame_url_override
- << ", new_window_url = " << test_case.new_window_url);
-
- const GURL new_window_url(test_case.new_window_url);
- ScopedNewFrameInterfaceProviderExerciser main_frame_exerciser(
- frame_creation_observer(), std::string("foo"));
- const std::string html =
- base::StringPrintf("<script>window.open(\"%s\", \"_blank\")</script>",
- test_case.new_window_url);
- LoadHTMLWithUrlOverride(html.c_str(), test_case.main_frame_url_override);
- ASSERT_NO_FATAL_FAILURE(
- main_frame_exerciser.ExpectNewFrameAndWaitForLoad(new_window_url));
-
- // The URL of the initial empty document is "" for opened windows, in
- // contrast to child frames, where it is "about:blank". See
- // Document::Document and Document::SetURL for more details.
- //
- // Furthermore, for main frames, InitializeCoreFrame is invoked first, and
- // RenderFrameImpl::Initialize is invoked second, in contrast to child
- // frames where it is vice versa. ContentRendererClient::RenderFrameCreated
- // is invoked from RenderFrameImpl::Initialize, so we miss the events
- // related to initial empty document that is created from
- // InitializeCoreFrame, and there is already a document when
- // RenderFrameCreated is invoked.
- //
- // TODO(https://crbug.com/792410): It is unfortunate how many internal
- // details of frame/document creation this encodes. Need to decouple.
- const GURL initial_empty_url;
- ExpectPendingInterfaceRequestsFromSources(
- main_frame_exerciser.interface_request_for_initial_empty_document(),
- main_frame_exerciser
- .document_interface_broker_request_for_initial_empty_document(),
- {{initial_empty_url, kFrameEventDidCreateNewFrame},
- {initial_empty_url, kFrameEventReadyToCommitNavigation},
- {new_window_url, kFrameEventDidCreateNewDocument}});
- ExpectPendingInterfaceRequestsFromSources(
- main_frame_exerciser.interface_request_for_first_document(),
- main_frame_exerciser
- .document_interface_broker_request_for_first_document(),
- {{new_window_url, kFrameEventDidCommitProvisionalLoad},
- {new_window_url, kFrameEventDidCreateDocumentElement}});
- }
+ const GURL new_window_url("data:text/html,NewWindow");
+ ScopedNewFrameInterfaceProviderExerciser main_frame_exerciser(
+ frame_creation_observer(), std::string("foo"));
+ const std::string html =
+ base::StringPrintf("<script>window.open(\"%s\", \"_blank\")</script>",
+ "data:text/html,NewWindow");
+ LoadHTMLWithUrlOverride(html.c_str(), kTestSecondURL);
+ ASSERT_NO_FATAL_FAILURE(
+ main_frame_exerciser.ExpectNewFrameAndWaitForLoad(new_window_url));
+
+ // The URL of the initial empty document is "" for opened windows, in
+ // contrast to child frames, where it is "about:blank". See
+ // Document::Document and Document::SetURL for more details.
+ //
+ // Furthermore, for main frames, InitializeCoreFrame is invoked first, and
+ // RenderFrameImpl::Initialize is invoked second, in contrast to child
+ // frames where it is vice versa. ContentRendererClient::RenderFrameCreated
+ // is invoked from RenderFrameImpl::Initialize, so we miss the events
+ // related to initial empty document that is created from
+ // InitializeCoreFrame, and there is already a document when
+ // RenderFrameCreated is invoked.
+ //
+ // TODO(https://crbug.com/792410): It is unfortunate how many internal
+ // details of frame/document creation this encodes. Need to decouple.
+ const GURL initial_empty_url;
+ ExpectPendingInterfaceRequestsFromSources(
+ main_frame_exerciser.interface_request_for_initial_empty_document(),
+ main_frame_exerciser
+ .document_interface_broker_request_for_initial_empty_document(),
+ {{initial_empty_url, kFrameEventDidCreateNewFrame},
+ {initial_empty_url, kFrameEventReadyToCommitNavigation},
+ {new_window_url, kFrameEventDidCreateNewDocument}});
+ ExpectPendingInterfaceRequestsFromSources(
+ main_frame_exerciser.interface_request_for_first_document(),
+ main_frame_exerciser
+ .document_interface_broker_request_for_first_document(),
+ {{new_window_url, kFrameEventDidCommitProvisionalLoad},
+ {new_window_url, kFrameEventDidCreateDocumentElement}});
}
// Expect that |remote_interfaces_| is not bound to a new pipe if the first
@@ -1324,8 +1298,10 @@ TEST_F(RenderFrameRemoteInterfacesTest,
// 4) The global object in the child frame's browsing context is re-used.
// 5) Javascript objects stashed on the global object should continue to work.
//
-// TODO(https://crbug.com/778318): Once the Window object inheritance is fixed,
-// add a similar test for: <iframe src="javascript:'html'"></iframe>.
+// TODO(japhet?): javascript: urls are untestable here, because they don't
+// go through the normal commit pipeline. If we were to give javascript: urls
+// their own DocumentLoader in blink and model them as a real navigation, we
+// should add a test case here.
// TODO(crbug.com/718652): when all clients are converted to use
// DocumentInterfaceBroker, InterfaceProviderRequest-related code will be
// removed.
@@ -1333,37 +1309,43 @@ TEST_F(RenderFrameRemoteInterfacesTest,
ChildFrameReusingWindowOfInitialDocument) {
const GURL main_frame_url(kTestFirstURL);
const GURL initial_empty_url(kAboutBlankURL);
- const GURL child_frame_url(kTestSecondURL);
- // Override the URL for the first navigation in the newly created frame to
- // |child_frame_url|.
- ScopedNewFrameInterfaceProviderExerciser child_frame_exerciser(
- frame_creation_observer(), std::string("foo"));
+ constexpr const char* kTestCases[] = {kTestSecondURL, kAboutBlankURL};
- std::string html = "<iframe src='" + child_frame_url.spec() + "'></iframe>";
- LoadHTMLWithUrlOverride(html.c_str(), main_frame_url.spec().c_str());
+ for (const char* test_case : kTestCases) {
+ SCOPED_TRACE(::testing::Message() << "child_frame_url = " << test_case);
- ASSERT_NO_FATAL_FAILURE(
- child_frame_exerciser.ExpectNewFrameAndWaitForLoad(child_frame_url));
+ // Override the URL for the first navigation in the newly created frame to
+ // |child_frame_url|.
+ const GURL child_frame_url(test_case);
+ ScopedNewFrameInterfaceProviderExerciser child_frame_exerciser(
+ frame_creation_observer(), std::string("foo"));
- ExpectPendingInterfaceRequestsFromSources(
- child_frame_exerciser.interface_request_for_initial_empty_document(),
- child_frame_exerciser
- .document_interface_broker_request_for_initial_empty_document(),
- {{GURL(kNoDocumentMarkerURL), kFrameEventDidCreateNewFrame},
- {initial_empty_url, kFrameEventDidCreateNewDocument},
- {initial_empty_url, kFrameEventDidCreateDocumentElement},
- {initial_empty_url, kFrameEventReadyToCommitNavigation},
- {child_frame_url, kFrameEventDidCreateNewDocument},
- {child_frame_url, kFrameEventDidCommitProvisionalLoad},
- {child_frame_url, kFrameEventDidCreateDocumentElement}});
+ std::string html = "<iframe src='" + child_frame_url.spec() + "'></iframe>";
+ LoadHTMLWithUrlOverride(html.c_str(), main_frame_url.spec().c_str());
- auto request = child_frame_exerciser.interface_request_for_first_document();
- ASSERT_FALSE(request.is_pending());
- auto document_interface_broker_request =
- child_frame_exerciser
- .document_interface_broker_request_for_first_document();
- ASSERT_FALSE(document_interface_broker_request.is_pending());
+ ASSERT_NO_FATAL_FAILURE(
+ child_frame_exerciser.ExpectNewFrameAndWaitForLoad(child_frame_url));
+
+ ExpectPendingInterfaceRequestsFromSources(
+ child_frame_exerciser.interface_request_for_initial_empty_document(),
+ child_frame_exerciser
+ .document_interface_broker_request_for_initial_empty_document(),
+ {{GURL(kNoDocumentMarkerURL), kFrameEventDidCreateNewFrame},
+ {initial_empty_url, kFrameEventDidCreateNewDocument},
+ {initial_empty_url, kFrameEventDidCreateDocumentElement},
+ {initial_empty_url, kFrameEventReadyToCommitNavigation},
+ {child_frame_url, kFrameEventDidCreateNewDocument},
+ {child_frame_url, kFrameEventDidCommitProvisionalLoad},
+ {child_frame_url, kFrameEventDidCreateDocumentElement}});
+
+ auto request = child_frame_exerciser.interface_request_for_first_document();
+ ASSERT_FALSE(request.is_pending());
+ auto document_interface_broker_request =
+ child_frame_exerciser
+ .document_interface_broker_request_for_first_document();
+ ASSERT_FALSE(document_interface_broker_request.is_pending());
+ }
}
// Expect that |remote_interfaces_| is bound to a new pipe on cross-document
diff --git a/chromium/content/renderer/render_frame_metadata_observer_impl.cc b/chromium/content/renderer/render_frame_metadata_observer_impl.cc
index 31fe9a0ec50..6d723113ca4 100644
--- a/chromium/content/renderer/render_frame_metadata_observer_impl.cc
+++ b/chromium/content/renderer/render_frame_metadata_observer_impl.cc
@@ -59,7 +59,8 @@ void RenderFrameMetadataObserverImpl::OnRenderFrameSubmission(
}
// Allways cache the full metadata, so that it can correctly be sent upon
- // ReportAllFrameSubmissionsForTesting. This must only be done after we've
+ // ReportAllFrameSubmissionsForTesting or
+ // ReportAllRootScrollsForAccessibility. This must only be done after we've
// compared the two for changes.
last_render_frame_metadata_ = render_frame_metadata;
@@ -67,11 +68,11 @@ void RenderFrameMetadataObserverImpl::OnRenderFrameSubmission(
// generated for first time and same as the default value, update the default
// value to all the observers.
if (send_metadata && render_frame_metadata_observer_client_) {
- // Sending |root_scroll_offset| outside of tests would leave the browser
- // process with out of date information. It is an optional parameter
- // which we clear here.
auto metadata_copy = render_frame_metadata;
#if !defined(OS_ANDROID)
+ // On non-Android, sending |root_scroll_offset| outside of tests would
+ // leave the browser process with out of date information. It is an
+ // optional parameter which we clear here.
if (!report_all_frame_submissions_for_testing_enabled_)
metadata_copy.root_scroll_offset = base::nullopt;
#endif
@@ -107,11 +108,26 @@ void RenderFrameMetadataObserverImpl::OnRenderFrameSubmission(
}
}
+#if defined(OS_ANDROID)
+void RenderFrameMetadataObserverImpl::ReportAllRootScrollsForAccessibility(
+ bool enabled) {
+ report_all_root_scrolls_for_accessibility_enabled_ = enabled;
+
+ if (enabled)
+ SendLastRenderFrameMetadata();
+}
+#endif
+
void RenderFrameMetadataObserverImpl::ReportAllFrameSubmissionsForTesting(
bool enabled) {
report_all_frame_submissions_for_testing_enabled_ = enabled;
- if (!enabled || !last_frame_token_)
+ if (enabled)
+ SendLastRenderFrameMetadata();
+}
+
+void RenderFrameMetadataObserverImpl::SendLastRenderFrameMetadata() {
+ if (!last_frame_token_)
return;
// When enabled for testing send the cached metadata.
@@ -121,11 +137,10 @@ void RenderFrameMetadataObserverImpl::ReportAllFrameSubmissionsForTesting(
last_frame_token_, *last_render_frame_metadata_);
}
-// static
bool RenderFrameMetadataObserverImpl::ShouldSendRenderFrameMetadata(
const cc::RenderFrameMetadata& rfm1,
const cc::RenderFrameMetadata& rfm2,
- bool* needs_activation_notification) {
+ bool* needs_activation_notification) const {
if (rfm1.root_background_color != rfm2.root_background_color ||
rfm1.is_scroll_offset_at_top != rfm2.is_scroll_offset_at_top ||
rfm1.selection != rfm2.selection ||
@@ -142,6 +157,9 @@ bool RenderFrameMetadataObserverImpl::ShouldSendRenderFrameMetadata(
}
#if defined(OS_ANDROID)
+ bool need_send_root_scroll =
+ report_all_root_scrolls_for_accessibility_enabled_ &&
+ rfm1.root_scroll_offset != rfm2.root_scroll_offset;
if (rfm1.bottom_controls_height != rfm2.bottom_controls_height ||
rfm1.bottom_controls_shown_ratio != rfm2.bottom_controls_shown_ratio ||
rfm1.min_page_scale_factor != rfm2.min_page_scale_factor ||
@@ -149,7 +167,8 @@ bool RenderFrameMetadataObserverImpl::ShouldSendRenderFrameMetadata(
rfm1.root_overflow_y_hidden != rfm2.root_overflow_y_hidden ||
rfm1.scrollable_viewport_size != rfm2.scrollable_viewport_size ||
rfm1.root_layer_size != rfm2.root_layer_size ||
- rfm1.has_transparent_background != rfm2.has_transparent_background) {
+ rfm1.has_transparent_background != rfm2.has_transparent_background ||
+ need_send_root_scroll) {
*needs_activation_notification = true;
return true;
}
diff --git a/chromium/content/renderer/render_frame_metadata_observer_impl.h b/chromium/content/renderer/render_frame_metadata_observer_impl.h
index fc830dc9f19..c0335ae90b7 100644
--- a/chromium/content/renderer/render_frame_metadata_observer_impl.h
+++ b/chromium/content/renderer/render_frame_metadata_observer_impl.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_RENDER_FRAME_METADATA_OBSERVER_IMPL_H_
#define CONTENT_RENDERER_RENDER_FRAME_METADATA_OBSERVER_IMPL_H_
+#include "build/build_config.h"
#include "cc/trees/render_frame_metadata.h"
#include "cc/trees/render_frame_metadata_observer.h"
#include "content/common/content_export.h"
@@ -39,6 +40,9 @@ class CONTENT_EXPORT RenderFrameMetadataObserverImpl
bool force_send) override;
// mojom::RenderFrameMetadataObserver:
+#if defined(OS_ANDROID)
+ void ReportAllRootScrollsForAccessibility(bool enabled) override;
+#endif
void ReportAllFrameSubmissionsForTesting(bool enabled) override;
private:
@@ -50,12 +54,19 @@ class CONTENT_EXPORT RenderFrameMetadataObserverImpl
// |needs_activation_notification| indicates whether the browser process
// expects notification of activation of the assoicated CompositorFrame from
// Viz.
- static bool ShouldSendRenderFrameMetadata(
- const cc::RenderFrameMetadata& rfm1,
- const cc::RenderFrameMetadata& rfm2,
- bool* needs_activation_notification);
+ bool ShouldSendRenderFrameMetadata(const cc::RenderFrameMetadata& rfm1,
+ const cc::RenderFrameMetadata& rfm2,
+ bool* needs_activation_notification) const;
- // When true this will notifiy |render_frame_metadata_observer_client_| of all
+ void SendLastRenderFrameMetadata();
+
+#if defined(OS_ANDROID)
+ // When true this will notify |render_frame_metadata_observer_client_| of all
+ // frame submissions that involve a root scroll offset change.
+ bool report_all_root_scrolls_for_accessibility_enabled_ = false;
+#endif
+
+ // When true this will notify |render_frame_metadata_observer_client_| of all
// frame submissions.
bool report_all_frame_submissions_for_testing_enabled_ = false;
diff --git a/chromium/content/renderer/render_frame_metadata_observer_impl_unittest.cc b/chromium/content/renderer/render_frame_metadata_observer_impl_unittest.cc
index 1f5803a159c..c569d774229 100644
--- a/chromium/content/renderer/render_frame_metadata_observer_impl_unittest.cc
+++ b/chromium/content/renderer/render_frame_metadata_observer_impl_unittest.cc
@@ -156,6 +156,91 @@ TEST_F(RenderFrameMetadataObserverImplTest, ShouldSendFrameTokenOnAndroid) {
run_loop.Run();
}
}
+
+// This test verifies that a request to send root scroll changes for
+// accessibility is respected.
+TEST_F(RenderFrameMetadataObserverImplTest, SendRootScrollsForAccessibility) {
+ const uint32_t expected_frame_token = 1337;
+ viz::CompositorFrameMetadata compositor_frame_metadata;
+ compositor_frame_metadata.send_frame_token_to_embedder = false;
+ compositor_frame_metadata.frame_token = expected_frame_token;
+ cc::RenderFrameMetadata render_frame_metadata;
+
+ observer_impl().OnRenderFrameSubmission(render_frame_metadata,
+ &compositor_frame_metadata,
+ false /* force_send */);
+ // The first RenderFrameMetadata will always get a corresponding frame token
+ // from Viz because this is the first frame.
+ EXPECT_TRUE(compositor_frame_metadata.send_frame_token_to_embedder);
+ {
+ base::RunLoop run_loop;
+ EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
+ render_frame_metadata))
+ .WillOnce(InvokeClosure(run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+
+ // Submit with a root scroll change and then a scroll offset at top change, we
+ // should only get one notification, as the root scroll change will not
+ // trigger one,
+ render_frame_metadata.root_scroll_offset = gfx::Vector2dF(0.0f, 100.0f);
+ observer_impl().OnRenderFrameSubmission(render_frame_metadata,
+ &compositor_frame_metadata,
+ false /* force_send */);
+ render_frame_metadata.is_scroll_offset_at_top =
+ !render_frame_metadata.is_scroll_offset_at_top;
+ observer_impl().OnRenderFrameSubmission(render_frame_metadata,
+ &compositor_frame_metadata,
+ false /* force_send */);
+ {
+ base::RunLoop run_loop;
+ EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
+ render_frame_metadata))
+ .WillOnce(InvokeClosure(run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+
+ // Enable reporting for root scroll changes. This will generate one
+ // notification.
+ observer_impl().ReportAllRootScrollsForAccessibility(true);
+ {
+ base::RunLoop run_loop;
+ EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
+ render_frame_metadata))
+ .WillOnce(InvokeClosure(run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+
+ // Now send a single root scroll change, we should get the notification.
+ render_frame_metadata.root_scroll_offset = gfx::Vector2dF(0.0f, 200.0f);
+ observer_impl().OnRenderFrameSubmission(render_frame_metadata,
+ &compositor_frame_metadata,
+ false /* force_send */);
+ {
+ base::RunLoop run_loop;
+ // The 0u frame token indicates that the client should not expect
+ // a corresponding frame token from Viz.
+ EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
+ render_frame_metadata))
+ .WillOnce(InvokeClosure(run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+
+ // Send one more message to ensure that no spurious
+ // OnRenderFrameMetadataChanged messages were generated.
+ render_frame_metadata.is_scroll_offset_at_top =
+ !render_frame_metadata.is_scroll_offset_at_top;
+ observer_impl().OnRenderFrameSubmission(render_frame_metadata,
+ &compositor_frame_metadata,
+ false /* force_send */);
+ {
+ base::RunLoop run_loop;
+ EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
+ render_frame_metadata))
+ .WillOnce(InvokeClosure(run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+}
#endif
// This test verifies that a request to force send metadata is respected.
diff --git a/chromium/content/renderer/render_frame_proxy.cc b/chromium/content/renderer/render_frame_proxy.cc
index cdba17adf4c..9dbcd82b72c 100644
--- a/chromium/content/renderer/render_frame_proxy.cc
+++ b/chromium/content/renderer/render_frame_proxy.cc
@@ -46,14 +46,8 @@
#include "third_party/blink/public/web/web_triggering_event_info.h"
#include "third_party/blink/public/web/web_user_gesture_indicator.h"
#include "third_party/blink/public/web/web_view.h"
-#include "ui/base/ui_base_features.h"
#include "ui/gfx/geometry/size_conversions.h"
-#if defined(USE_AURA)
-#include "content/renderer/mus/mus_embedded_frame.h"
-#include "content/renderer/mus/renderer_window_tree_client.h"
-#endif
-
#if BUILDFLAG(ENABLE_PRINTING)
// nogncheck because dependency on //printing is conditional upon
// enable_basic_printing flags.
@@ -177,9 +171,11 @@ RenderFrameProxy* RenderFrameProxy::CreateFrameProxy(
RenderFrameProxy* RenderFrameProxy::CreateProxyForPortal(
RenderFrameImpl* parent,
- int proxy_routing_id) {
+ int proxy_routing_id,
+ const base::UnguessableToken& devtools_frame_token) {
std::unique_ptr<RenderFrameProxy> proxy(
new RenderFrameProxy(proxy_routing_id));
+ proxy->devtools_frame_token_ = devtools_frame_token;
blink::WebRemoteFrame* web_frame = blink::WebRemoteFrame::Create(
blink::WebTreeScopeType::kDocument, proxy.get());
proxy->Init(web_frame, parent->render_view(),
@@ -262,19 +258,6 @@ void RenderFrameProxy::Init(blink::WebRemoteFrame* web_frame,
pending_visual_properties_.screen_info =
render_widget_->GetOriginalScreenInfo();
-
-#if defined(USE_AURA)
- if (features::IsMultiProcessMash()) {
- RendererWindowTreeClient* renderer_window_tree_client =
- RendererWindowTreeClient::Get(render_widget_->routing_id());
- // It's possible a MusEmbeddedFrame has already been scheduled for creation
- // (that is, RendererWindowTreeClient::Embed() was called). Call to
- // OnRenderFrameProxyCreated() to potentially get the MusEmbeddedFrame.
- // OnRenderFrameProxyCreated() returns null if Embed() was not called.
- mus_embedded_frame_ =
- renderer_window_tree_client->OnRenderFrameProxyCreated(this);
- }
-#endif
}
void RenderFrameProxy::ResendVisualProperties() {
@@ -514,16 +497,13 @@ void RenderFrameProxy::OnDidStartLoading() {
void RenderFrameProxy::OnViewChanged(
const FrameMsg_ViewChanged_Params& params) {
crashed_ = false;
- // In mash the FrameSinkId comes from RendererWindowTreeClient.
- if (!features::IsMultiProcessMash()) {
- // The same ParentLocalSurfaceIdAllocator cannot provide LocalSurfaceIds for
- // two different frame sinks, so recreate it here.
- if (frame_sink_id_ != *params.frame_sink_id) {
- parent_local_surface_id_allocator_ =
- std::make_unique<viz::ParentLocalSurfaceIdAllocator>();
- }
- frame_sink_id_ = *params.frame_sink_id;
+ // The same ParentLocalSurfaceIdAllocator cannot provide LocalSurfaceIds for
+ // two different frame sinks, so recreate it here.
+ if (frame_sink_id_ != params.frame_sink_id) {
+ parent_local_surface_id_allocator_ =
+ std::make_unique<viz::ParentLocalSurfaceIdAllocator>();
}
+ frame_sink_id_ = params.frame_sink_id;
// Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view
// changes.
@@ -629,7 +609,7 @@ void RenderFrameProxy::OnScrollRectToVisible(
void RenderFrameProxy::OnBubbleLogicalScroll(
blink::WebScrollDirection direction,
- blink::WebScrollGranularity granularity) {
+ ui::input_types::ScrollGranularity granularity) {
web_frame_->BubbleLogicalScroll(direction, granularity);
}
@@ -659,13 +639,6 @@ void RenderFrameProxy::OnDisableAutoResize() {
SynchronizeVisualProperties();
}
-#if defined(USE_AURA)
-void RenderFrameProxy::SetMusEmbeddedFrame(
- std::unique_ptr<MusEmbeddedFrame> mus_embedded_frame) {
- mus_embedded_frame_ = std::move(mus_embedded_frame);
-}
-#endif
-
void RenderFrameProxy::SynchronizeVisualProperties() {
if (!frame_sink_id_.is_valid() || crashed_)
return;
@@ -724,15 +697,6 @@ void RenderFrameProxy::SynchronizeVisualProperties() {
pending_visual_properties_.screen_space_rect;
bool visual_properties_changed = synchronized_props_changed || rect_changed;
-#if defined(USE_AURA)
- if (rect_changed && mus_embedded_frame_) {
- mus_embedded_frame_->SetWindowBounds(
- parent_local_surface_id_allocator_
- ->GetCurrentLocalSurfaceIdAllocation(),
- gfx::Rect(local_frame_size()));
- }
-#endif
-
if (!visual_properties_changed)
return;
@@ -770,10 +734,6 @@ void RenderFrameProxy::OnRenderFallbackContent() const {
}
void RenderFrameProxy::FrameDetached(DetachType type) {
-#if defined(USE_AURA)
- mus_embedded_frame_.reset();
-#endif
-
if (type == DetachType::kRemove) {
// Let the browser process know this subframe is removed, so that it is
// destroyed in its current process.
@@ -871,8 +831,8 @@ void RenderFrameProxy::Navigate(
params.blob_url_token = blob_url_token.release();
// Note: For the AdFrame download policy here it only covers the case where
- // the navigation initiator frame is ad.
- // TODO(yaoxia): Also cover the case where the navigating frame is ad.
+ // the navigation initiator frame is ad. The download_policy may be further
+ // augmented in RenderFrameProxyHost::OnOpenURL if the navigating frame is ad.
RenderFrameImpl::MaybeSetDownloadFramePolicy(
is_opener_navigation, request, web_frame_->GetSecurityOrigin(),
has_download_sandbox_flag,
@@ -961,24 +921,6 @@ base::UnguessableToken RenderFrameProxy::GetDevToolsFrameToken() {
return devtools_frame_token_;
}
-#if defined(USE_AURA)
-void RenderFrameProxy::OnMusEmbeddedFrameSinkIdAllocated(
- const viz::FrameSinkId& frame_sink_id) {
- // RendererWindowTreeClient should only call this when mus is hosting viz.
- DCHECK(features::IsMultiProcessMash());
- // The same ParentLocalSurfaceIdAllocator cannot provide LocalSurfaceIds for
- // two different frame sinks, so re-create it here.
- if (frame_sink_id_ != frame_sink_id) {
- parent_local_surface_id_allocator_ =
- std::make_unique<viz::ParentLocalSurfaceIdAllocator>();
- }
- frame_sink_id_ = frame_sink_id;
- // Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view
- // changes.
- ResendVisualProperties();
-}
-#endif
-
cc::Layer* RenderFrameProxy::GetLayer() {
return embedded_layer_.get();
}
diff --git a/chromium/content/renderer/render_frame_proxy.h b/chromium/content/renderer/render_frame_proxy.h
index 385a553b732..04a8e0fcb06 100644
--- a/chromium/content/renderer/render_frame_proxy.h
+++ b/chromium/content/renderer/render_frame_proxy.h
@@ -24,10 +24,6 @@
#include "third_party/blink/public/web/web_remote_frame_client.h"
#include "url/origin.h"
-#if defined(USE_AURA)
-#include "content/renderer/mus/mus_embedded_frame_delegate.h"
-#endif
-
namespace blink {
struct FramePolicy;
struct WebRect;
@@ -49,10 +45,6 @@ struct FrameOwnerProperties;
struct FrameReplicationState;
struct ResourceTimingInfo;
-#if defined(USE_AURA)
-class MusEmbeddedFrame;
-#endif
-
// When a page's frames are rendered by multiple processes, each renderer has a
// full copy of the frame tree. It has full RenderFrames for the frames it is
// responsible for rendering and placeholder objects for frames rendered by
@@ -75,9 +67,6 @@ class MusEmbeddedFrame;
// RenderFrame is created for it.
class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
public IPC::Sender,
-#if defined(USE_AURA)
- public MusEmbeddedFrameDelegate,
-#endif
public ChildFrameCompositor,
public blink::WebRemoteFrameClient {
public:
@@ -114,8 +103,10 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
// Creates a RenderFrameProxy to be used with a portal owned by |parent|.
// |routing_id| is the routing id of this new RenderFrameProxy.
- static RenderFrameProxy* CreateProxyForPortal(RenderFrameImpl* parent,
- int proxy_routing_id);
+ static RenderFrameProxy* CreateProxyForPortal(
+ RenderFrameImpl* parent,
+ int proxy_routing_id,
+ const base::UnguessableToken& devtools_frame_token);
// Returns the RenderFrameProxy for the given routing ID.
static RenderFrameProxy* FromRoutingID(int routing_id);
@@ -171,11 +162,6 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
// Returns the widget used for the local frame root.
RenderWidget* render_widget() { return render_widget_; }
-#if defined(USE_AURA)
- void SetMusEmbeddedFrame(
- std::unique_ptr<MusEmbeddedFrame> mus_embedded_frame);
-#endif
-
void SynchronizeVisualProperties();
const gfx::Rect& screen_space_rect() const {
@@ -280,19 +266,13 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
void OnScrollRectToVisible(const gfx::Rect& rect_to_scroll,
const blink::WebScrollIntoViewParams& params);
void OnBubbleLogicalScroll(blink::WebScrollDirection direction,
- blink::WebScrollGranularity granularity);
+ ui::input_types::ScrollGranularity granularity);
void OnDidUpdateVisualProperties(const cc::RenderFrameMetadata& metadata);
void OnEnableAutoResize(const gfx::Size& min_size, const gfx::Size& max_size);
void OnDisableAutoResize();
void OnSetHasReceivedUserGestureBeforeNavigation(bool value);
void OnRenderFallbackContent() const;
-#if defined(USE_AURA)
- // MusEmbeddedFrameDelegate
- void OnMusEmbeddedFrameSinkIdAllocated(
- const viz::FrameSinkId& frame_sink_id) override;
-#endif
-
// ChildFrameCompositor:
cc::Layer* GetLayer() override;
void SetLayer(scoped_refptr<cc::Layer> layer,
@@ -347,10 +327,6 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
blink::FrameOcclusionState last_occlusion_state_ =
blink::FrameOcclusionState::kUnknown;
-#if defined(USE_AURA)
- std::unique_ptr<MusEmbeddedFrame> mus_embedded_frame_;
-#endif
-
// The layer used to embed the out-of-process content.
scoped_refptr<cc::Layer> embedded_layer_;
diff --git a/chromium/content/renderer/render_process.cc b/chromium/content/renderer/render_process.cc
index 81e49e2e03e..0fdf0956f40 100644
--- a/chromium/content/renderer/render_process.cc
+++ b/chromium/content/renderer/render_process.cc
@@ -10,7 +10,8 @@ namespace content {
RenderProcess::RenderProcess(
const std::string& thread_pool_name,
- std::unique_ptr<base::ThreadPool::InitParams> thread_pool_init_params)
+ std::unique_ptr<base::ThreadPoolInstance::InitParams>
+ thread_pool_init_params)
: ChildProcess(base::ThreadPriority::NORMAL,
thread_pool_name,
std::move(thread_pool_init_params)) {}
diff --git a/chromium/content/renderer/render_process.h b/chromium/content/renderer/render_process.h
index d5efd0ff0fe..a8604133720 100644
--- a/chromium/content/renderer/render_process.h
+++ b/chromium/content/renderer/render_process.h
@@ -25,9 +25,9 @@ namespace content {
class RenderProcess : public ChildProcess {
public:
RenderProcess() = default;
- RenderProcess(
- const std::string& thread_pool_name,
- std::unique_ptr<base::ThreadPool::InitParams> thread_pool_init_params);
+ RenderProcess(const std::string& thread_pool_name,
+ std::unique_ptr<base::ThreadPoolInstance::InitParams>
+ thread_pool_init_params);
~RenderProcess() override {}
// Keep track of the cumulative set of enabled bindings for this process,
diff --git a/chromium/content/renderer/render_process_impl.cc b/chromium/content/renderer/render_process_impl.cc
index 8a0fea0396b..90d280d4197 100644
--- a/chromium/content/renderer/render_process_impl.cc
+++ b/chromium/content/renderer/render_process_impl.cc
@@ -25,8 +25,10 @@
#include "base/debug/stack_trace.h"
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
+#include "base/strings/string_split.h"
#include "base/system/sys_info.h"
#include "base/task/thread_pool/initialization_util.h"
+#include "base/task/thread_pool/thread_pool.h"
#include "base/time/time.h"
#include "content/common/thread_pool_util.h"
#include "content/public/common/bindings_policy.h"
@@ -62,18 +64,12 @@ void SetV8FlagIfHasSwitch(const char* switch_name, const char* v8_flag) {
}
}
-std::unique_ptr<base::ThreadPool::InitParams> GetDefaultThreadPoolInitParams() {
- constexpr int kMaxNumThreadsInBackgroundPool = 2;
+std::unique_ptr<base::ThreadPoolInstance::InitParams>
+GetThreadPoolInitParams() {
constexpr int kMaxNumThreadsInForegroundPoolLowerBound = 3;
- constexpr auto kSuggestedReclaimTime = base::TimeDelta::FromSeconds(30);
-
- return std::make_unique<base::ThreadPool::InitParams>(
- base::SchedulerWorkerPoolParams(kMaxNumThreadsInBackgroundPool,
- kSuggestedReclaimTime),
- base::SchedulerWorkerPoolParams(
- std::max(kMaxNumThreadsInForegroundPoolLowerBound,
- content::GetMinForegroundThreadsInRendererThreadPool()),
- kSuggestedReclaimTime));
+ return std::make_unique<base::ThreadPoolInstance::InitParams>(
+ std::max(kMaxNumThreadsInForegroundPoolLowerBound,
+ content::GetMinForegroundThreadsInRendererThreadPool()));
}
#if defined(DCHECK_IS_CONFIGURABLE)
@@ -88,9 +84,8 @@ void V8DcheckCallbackHandler(const char* file, int line, const char* message) {
namespace content {
-RenderProcessImpl::RenderProcessImpl(
- std::unique_ptr<base::ThreadPool::InitParams> thread_pool_init_params)
- : RenderProcess("Renderer", std::move(thread_pool_init_params)),
+RenderProcessImpl::RenderProcessImpl()
+ : RenderProcess("Renderer", GetThreadPoolInitParams()),
enabled_bindings_(0) {
#if defined(DCHECK_IS_CONFIGURABLE)
// Some official builds ship with DCHECKs compiled in. Failing DCHECKs then
@@ -115,8 +110,7 @@ RenderProcessImpl::RenderProcessImpl(
if (base::SysInfo::IsLowEndDevice()) {
std::string optimize_flag("--optimize-for-size");
- v8::V8::SetFlagsFromString(optimize_flag.c_str(),
- static_cast<int>(optimize_flag.size()));
+ v8::V8::SetFlagsFromString(optimize_flag.c_str(), optimize_flag.size());
}
SetV8FlagIfHasSwitch(switches::kDisableJavaScriptHarmonyShipping,
@@ -127,9 +121,6 @@ RenderProcessImpl::RenderProcessImpl(
"--harmony-dynamic-import --harmony-import-meta";
v8::V8::SetFlagsFromString(kModuleFlags, sizeof(kModuleFlags));
- SetV8FlagIfFeature(features::kV8Orinoco, "--no-single-threaded-gc");
- SetV8FlagIfNotFeature(features::kV8Orinoco, "--single-threaded-gc");
-
SetV8FlagIfFeature(features::kV8VmFuture, "--future");
SetV8FlagIfNotFeature(features::kV8VmFuture, "--no-future");
@@ -138,6 +129,13 @@ RenderProcessImpl::RenderProcessImpl(
SetV8FlagIfNotFeature(features::kWebAssemblyBaseline,
"--no-liftoff --no-wasm-tier-up");
+ SetV8FlagIfFeature(features::kWebAssemblyCodeGC, "--wasm-code-gc");
+ SetV8FlagIfNotFeature(features::kWebAssemblyCodeGC, "--no-wasm-code-gc");
+
+ SetV8FlagIfFeature(features::kWebAssemblySimd, "--experimental-wasm-simd");
+ SetV8FlagIfNotFeature(features::kWebAssemblySimd,
+ "--no-experimental-wasm-simd");
+
if (base::FeatureList::IsEnabled(features::kWebAssemblyThreads)) {
constexpr char kFlags[] =
"--harmony-sharedarraybuffer "
@@ -154,20 +152,24 @@ RenderProcessImpl::RenderProcessImpl(
"--no-harmony-sharedarraybuffer");
}
- SetV8FlagIfFeature(features::kAwaitOptimization,
- "--harmony-await-optimization");
- SetV8FlagIfNotFeature(features::kAwaitOptimization,
- "--no-harmony-await-optimization");
+ SetV8FlagIfFeature(features::kBlinkHeapUnifiedGCScheduling,
+ "--global-gc-scheduling");
SetV8FlagIfNotFeature(features::kWebAssemblyTrapHandler,
"--no-wasm-trap-handler");
#if defined(OS_LINUX) && defined(ARCH_CPU_X86_64)
if (base::FeatureList::IsEnabled(features::kWebAssemblyTrapHandler)) {
- bool use_v8_signal_handler = false;
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(
service_manager::switches::kDisableInProcessStackTraces)) {
- base::debug::SetStackDumpFirstChanceCallback(v8::V8::TryHandleSignal);
+ // Only enable WebAssembly trap handler if we can set the callback.
+ if (base::debug::SetStackDumpFirstChanceCallback(
+ v8::V8::TryHandleSignal)) {
+ // We registered the WebAssembly trap handler callback with the stack
+ // dump signal handler successfully. We can tell V8 that it can enable
+ // WebAssembly trap handler without using the V8 signal handler.
+ v8::V8::EnableWebAssemblyTrapHandler(/*use_v8_signal_handler=*/false);
+ }
} else if (!command_line->HasSwitch(switches::kEnableCrashReporter) &&
!command_line->HasSwitch(
switches::kEnableCrashReporterForTesting)) {
@@ -175,10 +177,8 @@ RenderProcessImpl::RenderProcessImpl(
// in-process stack traces are disabled then there will be no signal
// handler. In this case, we fall back on V8's default handler
// (https://crbug.com/798150).
- use_v8_signal_handler = true;
+ v8::V8::EnableWebAssemblyTrapHandler(/*use_v8_signal_handler=*/true);
}
- // TODO(eholk): report UMA stat for how often this succeeds
- v8::V8::EnableWebAssemblyTrapHandler(use_v8_signal_handler);
}
#endif
#if defined(OS_WIN) && defined(ARCH_CPU_X86_64)
@@ -208,9 +208,13 @@ RenderProcessImpl::RenderProcessImpl(
}
if (command_line.HasSwitch(switches::kJavaScriptFlags)) {
- std::string flags(
- command_line.GetSwitchValueASCII(switches::kJavaScriptFlags));
- v8::V8::SetFlagsFromString(flags.c_str(), static_cast<int>(flags.size()));
+ std::string js_flags =
+ command_line.GetSwitchValueASCII(switches::kJavaScriptFlags);
+ std::vector<base::StringPiece> flag_list = base::SplitStringPiece(
+ js_flags, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ for (const auto& flag : flag_list) {
+ v8::V8::SetFlagsFromString(flag.as_string().c_str(), flag.size());
+ }
}
if (command_line.HasSwitch(switches::kDomAutomationController))
@@ -230,13 +234,7 @@ RenderProcessImpl::~RenderProcessImpl() {
}
std::unique_ptr<RenderProcess> RenderProcessImpl::Create() {
- auto thread_pool_init_params =
- content::GetContentClient()->renderer()->GetThreadPoolInitParams();
- if (!thread_pool_init_params)
- thread_pool_init_params = GetDefaultThreadPoolInitParams();
-
- return base::WrapUnique(
- new RenderProcessImpl(std::move(thread_pool_init_params)));
+ return base::WrapUnique(new RenderProcessImpl());
}
void RenderProcessImpl::AddBindings(int bindings) {
diff --git a/chromium/content/renderer/render_process_impl.h b/chromium/content/renderer/render_process_impl.h
index f38863a4765..b8f72956625 100644
--- a/chromium/content/renderer/render_process_impl.h
+++ b/chromium/content/renderer/render_process_impl.h
@@ -9,7 +9,6 @@
#include <vector>
#include "base/macros.h"
-#include "base/task/thread_pool/thread_pool.h"
#include "content/renderer/render_process.h"
namespace content {
@@ -41,8 +40,7 @@ class RenderProcessImpl : public RenderProcess {
void ReleaseProcess() override;
private:
- RenderProcessImpl(
- std::unique_ptr<base::ThreadPool::InitParams> thread_pool_init_params);
+ RenderProcessImpl();
// Bitwise-ORed set of extra bindings that have been enabled anywhere in this
// process. See BindingsPolicy for details.
diff --git a/chromium/content/renderer/render_thread_impl.cc b/chromium/content/renderer/render_thread_impl.cc
index e47b89dbbe1..a908f83034f 100644
--- a/chromium/content/renderer/render_thread_impl.cc
+++ b/chromium/content/renderer/render_thread_impl.cc
@@ -99,8 +99,6 @@
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/peer_connection_tracker.h"
#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h"
-#include "content/renderer/mus/render_widget_window_tree_client_factory.h"
-#include "content/renderer/mus/renderer_window_tree_client.h"
#include "content/renderer/net_info_helper.h"
#include "content/renderer/p2p/socket_dispatcher.h"
#include "content/renderer/render_frame_proxy.h"
@@ -143,7 +141,6 @@
#include "services/service_manager/public/cpp/interface_provider.h"
#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "services/ws/public/cpp/gpu/gpu.h"
-#include "services/ws/public/mojom/constants.mojom.h"
#include "skia/ext/skia_memory_dump_provider.h"
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_cache.h"
@@ -161,7 +158,6 @@
#include "third_party/boringssl/src/include/openssl/evp.h"
#include "third_party/skia/include/core/SkGraphics.h"
#include "ui/base/layout.h"
-#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/display/display_switches.h"
@@ -716,6 +712,7 @@ RenderThreadImpl::RenderThreadImpl(
void RenderThreadImpl::Init() {
TRACE_EVENT0("startup", "RenderThreadImpl::Init");
+ init_start_ = base::TimeTicks::Now();
GetContentClient()->renderer()->PostIOThreadCreated(GetIOTaskRunner().get());
@@ -738,10 +735,7 @@ void RenderThreadImpl::Init() {
base::BindRepeating(&CreateSingleSampleMetricsProvider,
main_thread_runner(), GetConnector()));
- gpu_ = ws::Gpu::Create(GetConnector(),
- features::IsMultiProcessMash()
- ? ws::mojom::kServiceName
- : mojom::kBrowserServiceName,
+ gpu_ = ws::Gpu::Create(GetConnector(), mojom::kBrowserServiceName,
GetIOTaskRunner());
resource_dispatcher_.reset(new ResourceDispatcher());
@@ -777,12 +771,7 @@ void RenderThreadImpl::Init() {
audio_output_ipc_factory_.emplace(GetIOTaskRunner());
-#if defined(USE_AURA)
- if (features::IsMultiProcessMash())
- CreateRenderWidgetWindowTreeClientFactory(GetServiceManagerConnection());
-#endif
-
- registry->AddInterface(base::Bind(&SharedWorkerFactoryImpl::Create),
+ registry->AddInterface(base::BindRepeating(&SharedWorkerFactoryImpl::Create),
base::ThreadTaskRunnerHandle::Get());
registry->AddInterface(base::BindRepeating(CreateResourceUsageReporter,
weak_factory_.GetWeakPtr()),
@@ -796,7 +785,8 @@ void RenderThreadImpl::Init() {
std::make_unique<service_manager::BinderRegistryWithArgs<
const service_manager::BindSourceInfo&>>();
registry_with_source_info->AddInterface(
- base::Bind(&CreateFrameFactory), base::ThreadTaskRunnerHandle::Get());
+ base::BindRepeating(&CreateFrameFactory),
+ base::ThreadTaskRunnerHandle::Get());
GetServiceManagerConnection()->AddConnectionFilter(
std::make_unique<SimpleConnectionFilterWithSourceInfo>(
std::move(registry_with_source_info)));
@@ -806,9 +796,8 @@ void RenderThreadImpl::Init() {
StartServiceManagerConnection();
- GetAssociatedInterfaceRegistry()->AddInterface(
- base::Bind(&RenderThreadImpl::OnRendererInterfaceRequest,
- base::Unretained(this)));
+ GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating(
+ &RenderThreadImpl::OnRendererInterfaceRequest, base::Unretained(this)));
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
@@ -904,10 +893,11 @@ void RenderThreadImpl::Init() {
}
#endif
- memory_pressure_listener_.reset(new base::MemoryPressureListener(
- base::Bind(&RenderThreadImpl::OnMemoryPressure, base::Unretained(this)),
- base::Bind(&RenderThreadImpl::OnSyncMemoryPressure,
- base::Unretained(this))));
+ memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
+ base::BindRepeating(&RenderThreadImpl::OnMemoryPressure,
+ base::Unretained(this)),
+ base::BindRepeating(&RenderThreadImpl::OnSyncMemoryPressure,
+ base::Unretained(this)));
int num_raster_threads = 0;
std::string string_value =
@@ -933,17 +923,8 @@ void RenderThreadImpl::Init() {
categorized_worker_pool_->Start(num_raster_threads);
discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr;
- if (features::IsMultiProcessMash()) {
-#if defined(USE_AURA)
- GetServiceManagerConnection()->GetConnector()->BindInterface(
- ws::mojom::kServiceName, &manager_ptr);
-#else
- NOTREACHED();
-#endif
- } else {
- ChildThread::Get()->GetConnector()->BindInterface(
- mojom::kBrowserServiceName, mojo::MakeRequest(&manager_ptr));
- }
+ ChildThread::Get()->GetConnector()->BindInterface(
+ mojom::kBrowserServiceName, mojo::MakeRequest(&manager_ptr));
discardable_shared_memory_manager_ = std::make_unique<
discardable_memory::ClientDiscardableSharedMemoryManager>(
@@ -982,6 +963,8 @@ void RenderThreadImpl::Init() {
compositing_mode_reporter_->AddCompositingModeWatcher(
std::move(watcher_ptr));
}
+
+ init_end_ = base::TimeTicks::Now();
}
RenderThreadImpl::~RenderThreadImpl() {
@@ -1090,6 +1073,10 @@ void RenderThreadImpl::AddRoute(int32_t routing_id, IPC::Listener* listener) {
if (!frame)
return;
+ GetChannel()->AddListenerTaskRunner(
+ routing_id,
+ frame->GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
+
scoped_refptr<PendingFrameCreate> create(it->second);
frame->BindFrame(it->second->browser_info(), it->second->TakeFrameRequest());
pending_frame_creates_.erase(it);
@@ -1097,6 +1084,7 @@ void RenderThreadImpl::AddRoute(int32_t routing_id, IPC::Listener* listener) {
void RenderThreadImpl::RemoveRoute(int32_t routing_id) {
ChildThreadImpl::GetRouter()->RemoveRoute(routing_id);
+ GetChannel()->RemoveListenerTaskRunner(routing_id);
}
void RenderThreadImpl::RegisterPendingFrameCreate(
@@ -1238,7 +1226,7 @@ void RenderThreadImpl::RegisterSchemes() {
WebSecurityPolicy::RegisterURLSchemeAsNotAllowingJavascriptURLs(
chrome_scheme);
- // chrome-devtools:
+ // devtools:
WebString devtools_scheme(WebString::FromASCII(kChromeDevToolsScheme));
WebSecurityPolicy::RegisterURLSchemeAsDisplayIsolated(devtools_scheme);
@@ -1270,7 +1258,8 @@ void RenderThreadImpl::RegisterExtension(
WebScriptController::RegisterExtension(std::move(extension));
}
-int RenderThreadImpl::PostTaskToAllWebWorkers(const base::Closure& closure) {
+int RenderThreadImpl::PostTaskToAllWebWorkers(
+ const base::RepeatingClosure& closure) {
return WorkerThreadRegistry::Instance()->PostTaskToAllThreads(closure);
}
@@ -1910,31 +1899,6 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink(
params.client_name = client_name;
-#if defined(USE_AURA)
- if (features::IsMultiProcessMash()) {
- if (!RendererWindowTreeClient::Get(widget_routing_id)) {
- std::move(callback).Run(nullptr);
- return;
- }
- scoped_refptr<gpu::GpuChannelHost> channel = EstablishGpuChannelSync();
- // If the channel could not be established correctly, then return null. This
- // would cause the compositor to wait and try again at a later time.
- if (!channel) {
- std::move(callback).Run(nullptr);
- return;
- }
- RendererWindowTreeClient::Get(widget_routing_id)
- ->RequestLayerTreeFrameSink(
- gpu_->CreateContextProvider(std::move(channel)),
- GetGpuMemoryBufferManager(), std::move(callback));
- frame_sink_provider_->RegisterRenderFrameMetadataObserver(
- widget_routing_id,
- std::move(render_frame_metadata_observer_client_request),
- std::move(render_frame_metadata_observer_ptr));
- return;
- }
-#endif
-
viz::mojom::CompositorFrameSinkRequest compositor_frame_sink_request =
mojo::MakeRequest(&params.pipes.compositor_frame_sink_info);
viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client;
@@ -2008,6 +1972,14 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink(
if (GetContentClient()->UsingSynchronousCompositing()) {
RenderWidget* widget = RenderWidget::FromRoutingID(widget_routing_id);
if (widget) {
+ // TODO(ericrk): Remove this check when SurfaceSynchronization is always
+ // enabled, and collapse with non-webview registration below.
+ if (features::IsSurfaceSynchronizationEnabled()) {
+ frame_sink_provider_->RegisterRenderFrameMetadataObserver(
+ widget_routing_id,
+ std::move(render_frame_metadata_observer_client_request),
+ std::move(render_frame_metadata_observer_ptr));
+ }
std::move(callback).Run(std::make_unique<SynchronousLayerTreeFrameSink>(
std::move(context_provider), std::move(worker_context_provider),
compositor_task_runner_, GetGpuMemoryBufferManager(),
@@ -2119,6 +2091,24 @@ void RenderThreadImpl::CreateFrameProxy(
void RenderThreadImpl::SetUpEmbeddedWorkerChannelForServiceWorker(
blink::mojom::EmbeddedWorkerInstanceClientRequest client_request) {
+ // This is a hack. Process creation and initialization occurs before tracing
+ // is setup, so trace events logged at that time get dropped. We want these
+ // trace events to analyze service worker performance, so log them here.
+ //
+ // TODO(crbug.com/968424): Remove this hack when trace events that happen
+ // early on are supported.
+ if (!init_start_.is_null()) {
+ TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(
+ "ServiceWorker", "RenderThreadImpl initialization", this,
+ 0 /* thread_id */, init_start_);
+ TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0(
+ "ServiceWorker", "RenderThreadImpl initialization", this,
+ 0 /* thread_id */, init_end_);
+ // Clear to avoid double logging.
+ init_start_ = base::TimeTicks();
+ init_end_ = base::TimeTicks();
+ }
+
EmbeddedWorkerInstanceClientImpl::Create(std::move(client_request));
}
diff --git a/chromium/content/renderer/render_thread_impl.h b/chromium/content/renderer/render_thread_impl.h
index ed033907704..87b476777ff 100644
--- a/chromium/content/renderer/render_thread_impl.h
+++ b/chromium/content/renderer/render_thread_impl.h
@@ -140,7 +140,7 @@ class StreamTextureFactory;
#pragma warning(disable: 4250)
#endif
-// The RenderThreadImpl class represents a background thread where RenderView
+// The RenderThreadImpl class represents the main thread, where RenderView
// instances live. The RenderThread supports an API that is used by its
// consumer to talk indirectly to the RenderViews and supporting objects.
// Likewise, it provides an API for the RenderViews to talk back to the main
@@ -200,7 +200,7 @@ class CONTENT_EXPORT RenderThreadImpl
std::unique_ptr<base::SharedMemory> HostAllocateSharedMemoryBuffer(
size_t buffer_size) override;
void RegisterExtension(std::unique_ptr<v8::Extension> extension) override;
- int PostTaskToAllWebWorkers(const base::Closure& closure) override;
+ int PostTaskToAllWebWorkers(const base::RepeatingClosure& closure) override;
bool ResolveProxy(const GURL& url, std::string* proxy_list) override;
base::WaitableEvent* GetShutdownEvent() override;
int32_t GetClientId() override;
@@ -728,6 +728,9 @@ class CONTENT_EXPORT RenderThreadImpl
mojo::Binding<viz::mojom::CompositingModeWatcher>
compositing_mode_watcher_binding_;
+ base::TimeTicks init_start_;
+ base::TimeTicks init_end_;
+
base::WeakPtrFactory<RenderThreadImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderThreadImpl);
diff --git a/chromium/content/renderer/render_thread_impl_browsertest.cc b/chromium/content/renderer/render_thread_impl_browsertest.cc
index 5eb40c85fb7..05b242e06eb 100644
--- a/chromium/content/renderer/render_thread_impl_browsertest.cc
+++ b/chromium/content/renderer/render_thread_impl_browsertest.cc
@@ -48,7 +48,6 @@
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/config/gpu_switches.h"
-#include "gpu/ipc/host/gpu_switches.h"
#include "ipc/ipc.mojom.h"
#include "ipc/ipc_channel_mojo.h"
#include "mojo/core/embedder/embedder.h"
@@ -62,6 +61,7 @@
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/buffer_format_util.h"
+#include "ui/gfx/switches.h"
// IPC messages for testing ----------------------------------------------------
@@ -448,19 +448,14 @@ class RenderThreadImplGpuMemoryBufferBrowserTest
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kSingleProcess);
NativeBufferFlag native_buffer_flag = ::testing::get<0>(GetParam());
- switch (native_buffer_flag) {
- case kEnableNativeBuffers:
- command_line->AppendSwitch(switches::kEnableNativeGpuMemoryBuffers);
- break;
- case kDisableNativeBuffers:
- command_line->AppendSwitch(switches::kDisableNativeGpuMemoryBuffers);
- break;
+ if (native_buffer_flag == kEnableNativeBuffers) {
+ command_line->AppendSwitch(switches::kEnableNativeGpuMemoryBuffers);
}
}
void SetUpOnMainThread() override {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&RenderThreadImplGpuMemoryBufferBrowserTest::SetUpOnRenderThread,
base::Unretained(this)));
}
diff --git a/chromium/content/renderer/render_thread_impl_discardable_memory_browsertest.cc b/chromium/content/renderer/render_thread_impl_discardable_memory_browsertest.cc
index 724cd90b673..c870be3df68 100644
--- a/chromium/content/renderer/render_thread_impl_discardable_memory_browsertest.cc
+++ b/chromium/content/renderer/render_thread_impl_discardable_memory_browsertest.cc
@@ -44,7 +44,7 @@ class RenderThreadImplDiscardableMemoryBrowserTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&RenderThreadImplDiscardableMemoryBrowserTest::SetUpOnRenderThread,
base::Unretained(this)));
}
diff --git a/chromium/content/renderer/render_view_browsertest.cc b/chromium/content/renderer/render_view_browsertest.cc
index bef772fb19a..bf2755a66ba 100644
--- a/chromium/content/renderer/render_view_browsertest.cc
+++ b/chromium/content/renderer/render_view_browsertest.cc
@@ -4,6 +4,7 @@
#include <stddef.h>
#include <stdint.h>
+
#include <tuple>
#include "base/bind.h"
@@ -17,10 +18,12 @@
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "cc/input/browser_controls_state.h"
#include "cc/trees/layer_tree_host.h"
#include "content/common/frame_messages.h"
#include "content/common/frame_owner_properties.h"
@@ -61,11 +64,11 @@
#include "net/cert/cert_status_flags.h"
#include "net/http/http_util.h"
#include "services/network/public/cpp/resource_request_body.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/dom_storage/session_storage_namespace_id.h"
#include "third_party/blink/public/common/origin_trials/origin_trial_policy.h"
#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_data.h"
@@ -95,6 +98,7 @@
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/range/range.h"
#include "ui/native_theme/native_theme_features.h"
+#include "url/url_constants.h"
#if defined(OS_ANDROID)
#include "third_party/blink/public/platform/web_coalesced_input_event.h"
@@ -575,7 +579,14 @@ TEST_F(RenderViewImplTest, IsPinchGestureActivePropagatesToProxies) {
EXPECT_FALSE(child_proxy_1->is_pinch_gesture_active_for_testing());
// Set the |is_pinch_gesture_active| flag.
- view()->PageScaleFactorChanged(1.f, true);
+ cc::ApplyViewportChangesArgs args;
+ args.page_scale_delta = 1.f;
+ args.is_pinch_gesture_active = true;
+ args.browser_controls_delta = 0.f;
+ args.browser_controls_constraint = cc::BrowserControlsState::kHidden;
+ args.scroll_gesture_did_end = false;
+
+ view()->webview()->MainFrameWidget()->ApplyViewportChanges(args);
EXPECT_TRUE(child_proxy_1->is_pinch_gesture_active_for_testing());
// Create a new remote child, and get its proxy. Swapping out will force
@@ -591,7 +602,8 @@ TEST_F(RenderViewImplTest, IsPinchGestureActivePropagatesToProxies) {
EXPECT_TRUE(child_proxy_2->is_pinch_gesture_active_for_testing());
// Reset the flag, make sure both children respond.
- view()->PageScaleFactorChanged(1.f, false);
+ args.is_pinch_gesture_active = false;
+ view()->webview()->MainFrameWidget()->ApplyViewportChanges(args);
EXPECT_FALSE(child_proxy_1->is_pinch_gesture_active_for_testing());
EXPECT_FALSE(child_proxy_2->is_pinch_gesture_active_for_testing());
}
@@ -719,8 +731,7 @@ TEST_F(RenderViewImplTest, BeginNavigation) {
// Verify that form posts to WebUI URLs will be sent to the browser process.
auto form_navigation_info = std::make_unique<blink::WebNavigationInfo>();
- form_navigation_info->url_request =
- blink::WebURLRequest(GURL("chrome://foo"));
+ form_navigation_info->url_request = blink::WebURLRequest(GetWebUIURL("foo"));
form_navigation_info->url_request.SetHttpMethod("POST");
form_navigation_info->url_request.SetRequestorOrigin(requestor_origin);
form_navigation_info->frame_type =
@@ -735,10 +746,9 @@ TEST_F(RenderViewImplTest, BeginNavigation) {
FrameHostMsg_OpenURL::ID));
// Verify that popup links to WebUI URLs also are sent to browser.
- blink::WebURLRequest popup_request(GURL("chrome://foo"));
+ blink::WebURLRequest popup_request(GetWebUIURL("foo"));
auto popup_navigation_info = std::make_unique<blink::WebNavigationInfo>();
- popup_navigation_info->url_request =
- blink::WebURLRequest(GURL("chrome://foo"));
+ popup_navigation_info->url_request = blink::WebURLRequest(GetWebUIURL("foo"));
popup_navigation_info->url_request.SetRequestorOrigin(requestor_origin);
popup_navigation_info->frame_type =
network::mojom::RequestContextFrameType::kAuxiliary;
@@ -805,8 +815,7 @@ TEST_F(RenderViewImplTest, BeginNavigationForWebUI) {
// Navigations to WebUI URLs will also be sent to browser process.
auto webui_navigation_info = std::make_unique<blink::WebNavigationInfo>();
- webui_navigation_info->url_request =
- blink::WebURLRequest(GURL("chrome://foo"));
+ webui_navigation_info->url_request = blink::WebURLRequest(GetWebUIURL("foo"));
webui_navigation_info->url_request.SetRequestorOrigin(requestor_origin);
webui_navigation_info->frame_type =
network::mojom::RequestContextFrameType::kTopLevel;
@@ -885,15 +894,19 @@ class AlwaysForkingRenderViewTest : public RenderViewImplTest {
TEST_F(AlwaysForkingRenderViewTest, BeginNavigationDoesNotForkEmptyUrl) {
GURL example_url("http://example.com");
GURL empty_url("");
- GURL blank_url("about:blank");
LoadHTMLWithUrlOverride("<body></body", example_url.spec().c_str());
EXPECT_EQ(example_url,
GURL(frame()->GetWebFrame()->GetDocumentLoader()->GetUrl()));
// Empty url should never fork.
+ blink::WebURLRequest request(empty_url);
+ request.SetFetchRequestMode(network::mojom::FetchRequestMode::kNavigate);
+ request.SetFetchRedirectMode(network::mojom::FetchRedirectMode::kManual);
+ request.SetRequestContext(blink::mojom::RequestContextType::INTERNAL);
+ request.SetRequestorOrigin(blink::WebSecurityOrigin::Create(example_url));
auto navigation_info = std::make_unique<blink::WebNavigationInfo>();
- navigation_info->url_request = blink::WebURLRequest(empty_url);
+ navigation_info->url_request = request;
navigation_info->frame_type =
network::mojom::RequestContextFrameType::kTopLevel;
navigation_info->navigation_policy = blink::kWebNavigationPolicyCurrentTab;
@@ -904,15 +917,20 @@ TEST_F(AlwaysForkingRenderViewTest, BeginNavigationDoesNotForkEmptyUrl) {
TEST_F(AlwaysForkingRenderViewTest, BeginNavigationDoesNotForkAboutBlank) {
GURL example_url("http://example.com");
- GURL blank_url("about:blank");
+ GURL blank_url(url::kAboutBlankURL);
LoadHTMLWithUrlOverride("<body></body", example_url.spec().c_str());
EXPECT_EQ(example_url,
GURL(frame()->GetWebFrame()->GetDocumentLoader()->GetUrl()));
- // About blank should never fork.
+ // about:blank should never fork.
+ blink::WebURLRequest request(blank_url);
+ request.SetFetchRequestMode(network::mojom::FetchRequestMode::kNavigate);
+ request.SetFetchRedirectMode(network::mojom::FetchRedirectMode::kManual);
+ request.SetRequestContext(blink::mojom::RequestContextType::INTERNAL);
+ request.SetRequestorOrigin(blink::WebSecurityOrigin::Create(example_url));
auto navigation_info = std::make_unique<blink::WebNavigationInfo>();
- navigation_info->url_request = blink::WebURLRequest(blank_url);
+ navigation_info->url_request = request;
navigation_info->frame_type =
network::mojom::RequestContextFrameType::kTopLevel;
navigation_info->navigation_policy = blink::kWebNavigationPolicyCurrentTab;
@@ -1155,110 +1173,6 @@ TEST_F(RenderViewImplEnableZoomForDSFTest,
EXPECT_TRUE(view()->webview()->MainFrame()->IsWebRemoteFrame());
}
-// Test that we get the correct UpdateState message when we go back twice
-// quickly without committing. Regression test for http://crbug.com/58082.
-// Disabled: http://crbug.com/157357 .
-TEST_F(RenderViewImplTest, DISABLED_LastCommittedUpdateState) {
- // Load page A.
- LoadHTML("<div>Page A</div>");
-
- // Load page B, which will trigger an UpdateState message for page A.
- LoadHTML("<div>Page B</div>");
-
- // Check for a valid UpdateState message for page A.
- base::RunLoop().RunUntilIdle();
- const IPC::Message* msg_A = render_thread_->sink().GetUniqueMessageMatching(
- FrameHostMsg_UpdateState::ID);
- ASSERT_TRUE(msg_A);
- FrameHostMsg_UpdateState::Param param;
- FrameHostMsg_UpdateState::Read(msg_A, &param);
- PageState state_A = std::get<0>(param);
- render_thread_->sink().ClearMessages();
-
- // Load page C, which will trigger an UpdateState message for page B.
- LoadHTML("<div>Page C</div>");
-
- // Check for a valid UpdateState for page B.
- base::RunLoop().RunUntilIdle();
- const IPC::Message* msg_B = render_thread_->sink().GetUniqueMessageMatching(
- FrameHostMsg_UpdateState::ID);
- ASSERT_TRUE(msg_B);
- FrameHostMsg_UpdateState::Read(msg_B, &param);
- PageState state_B = std::get<0>(param);
- EXPECT_NE(state_A, state_B);
- render_thread_->sink().ClearMessages();
-
- // Load page D, which will trigger an UpdateState message for page C.
- LoadHTML("<div>Page D</div>");
-
- // Check for a valid UpdateState for page C.
- base::RunLoop().RunUntilIdle();
- const IPC::Message* msg_C = render_thread_->sink().GetUniqueMessageMatching(
- FrameHostMsg_UpdateState::ID);
- ASSERT_TRUE(msg_C);
- FrameHostMsg_UpdateState::Read(msg_C, &param);
- PageState state_C = std::get<0>(param);
- EXPECT_NE(state_B, state_C);
- render_thread_->sink().ClearMessages();
-
- // Go back to C and commit, preparing for our real test.
- CommonNavigationParams common_params_C;
- CommitNavigationParams commit_params_C;
- common_params_C.navigation_type =
- FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT;
- common_params_C.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
- commit_params_C.current_history_list_length = 4;
- commit_params_C.current_history_list_offset = 3;
- commit_params_C.pending_history_list_offset = 2;
- commit_params_C.nav_entry_id = 3;
- commit_params_C.page_state = state_C;
- frame()->Navigate(common_params_C, commit_params_C);
- base::RunLoop().RunUntilIdle();
- render_thread_->sink().ClearMessages();
-
- // Go back twice quickly, such that page B does not have a chance to commit.
- // This leads to two changes to the back/forward list but only one change to
- // the RenderView's page ID.
-
- // Back to page B without committing.
- CommonNavigationParams common_params_B;
- CommitNavigationParams commit_params_B;
- common_params_B.navigation_type =
- FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT;
- common_params_B.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
- commit_params_B.current_history_list_length = 4;
- commit_params_B.current_history_list_offset = 2;
- commit_params_B.pending_history_list_offset = 1;
- commit_params_B.nav_entry_id = 2;
- commit_params_B.page_state = state_B;
- frame()->Navigate(common_params_B, commit_params_B);
-
- // Back to page A and commit.
- CommonNavigationParams common_params;
- CommitNavigationParams commit_params;
- common_params.navigation_type =
- FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT;
- common_params.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
- commit_params.current_history_list_length = 4;
- commit_params.current_history_list_offset = 2;
- commit_params.pending_history_list_offset = 0;
- commit_params.nav_entry_id = 1;
- commit_params.page_state = state_A;
- frame()->Navigate(common_params, commit_params);
- base::RunLoop().RunUntilIdle();
-
- // Now ensure that the UpdateState message we receive is consistent
- // and represents page C in state.
- const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
- FrameHostMsg_UpdateState::ID);
- ASSERT_TRUE(msg);
- FrameHostMsg_UpdateState::Read(msg, &param);
- PageState state = std::get<0>(param);
- EXPECT_NE(state_A, state);
- EXPECT_NE(state_B, state);
- EXPECT_EQ(state_C, state);
-}
-
// Test that our IME backend sends a notification message when the input focus
// changes.
TEST_F(RenderViewImplTest, OnImeTypeChanged) {
@@ -1560,26 +1474,6 @@ TEST_F(RenderViewImplTest, OnSetTextDirection) {
}
}
-// Crashy, http://crbug.com/53247.
-TEST_F(RenderViewImplTest, DISABLED_DidFailProvisionalLoadWithErrorForError) {
- GetMainFrame()->EnableViewSourceMode(true);
- WebURLError error(net::ERR_FILE_NOT_FOUND, GURL("http://foo"));
- WebLocalFrame* web_frame = GetMainFrame();
-
- // Start a load that will reach provisional state synchronously,
- // but won't complete synchronously.
- CommonNavigationParams common_params;
- common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
- common_params.url = GURL("data:text/html,test data");
- frame()->Navigate(common_params, CommitNavigationParams());
-
- // An error occurred.
- view()->GetMainRenderFrame()->DidFailProvisionalLoad(
- error, blink::kWebStandardCommit);
- // Frame should exit view-source mode.
- EXPECT_FALSE(web_frame->IsViewSourceModeEnabled());
-}
-
TEST_F(RenderViewImplTest, DidFailProvisionalLoadWithErrorForCancellation) {
GetMainFrame()->EnableViewSourceMode(true);
WebURLError error(net::ERR_ABORTED, GURL("http://foo"));
@@ -1593,8 +1487,7 @@ TEST_F(RenderViewImplTest, DidFailProvisionalLoadWithErrorForCancellation) {
frame()->Navigate(common_params, CommitNavigationParams());
// A cancellation occurred.
- view()->GetMainRenderFrame()->DidFailProvisionalLoad(
- error, blink::kWebStandardCommit);
+ view()->GetMainRenderFrame()->DidFailProvisionalLoad(error, "GET");
// Frame should stay in view-source mode.
EXPECT_TRUE(web_frame->IsViewSourceModeEnabled());
}
@@ -2139,8 +2032,8 @@ TEST_F(RendererErrorPageTest, MAYBE_HttpStatusCodeErrorWithEmptyBody) {
network::ResourceResponseHead head;
std::string headers(
"HTTP/1.1 503 SERVICE UNAVAILABLE\nContent-type: text/html\n\n");
- head.headers = new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size()));
+ head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(headers));
TestRenderFrame* main_frame = static_cast<TestRenderFrame*>(frame());
main_frame->Navigate(head, common_params, CommitNavigationParams());
@@ -2486,35 +2379,6 @@ TEST_F(RenderViewImplTest, HistoryIsProperlyUpdatedOnShouldClearHistoryList) {
view()->HistoryForwardListCount() + 1);
}
-// IPC Listener that runs a callback when a console.log() is executed from
-// javascript.
-class ConsoleCallbackFilter : public IPC::Listener {
- public:
- explicit ConsoleCallbackFilter(
- base::Callback<void(const base::string16&)> callback)
- : callback_(callback) {}
-
- bool OnMessageReceived(const IPC::Message& msg) override {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(ConsoleCallbackFilter, msg)
- IPC_MESSAGE_HANDLER(FrameHostMsg_DidAddMessageToConsole,
- OnDidAddMessageToConsole)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
- }
-
- void OnDidAddMessageToConsole(int32_t,
- const base::string16& message,
- int32_t,
- const base::string16&) {
- callback_.Run(message);
- }
-
- private:
- base::Callback<void(const base::string16&)> callback_;
-};
-
// Tests that there's no UaF after dispatchBeforeUnloadEvent.
// See https://crbug.com/666714.
TEST_F(RenderViewImplTest, DispatchBeforeUnloadCanDetachFrame) {
@@ -2522,26 +2386,29 @@ TEST_F(RenderViewImplTest, DispatchBeforeUnloadCanDetachFrame) {
"<script>window.onbeforeunload = function() { "
"window.console.log('OnBeforeUnload called'); }</script>");
- // Creates a callback that swaps the frame when the 'OnBeforeUnload called'
+ // Create a callback that swaps the frame when the 'OnBeforeUnload called'
// log is printed from the beforeunload handler.
- std::unique_ptr<ConsoleCallbackFilter> callback_filter(
- new ConsoleCallbackFilter(base::Bind(
- [](RenderFrameImpl* frame, const base::string16& msg) {
- // Makes sure this happens during the beforeunload handler.
- EXPECT_EQ(base::UTF8ToUTF16("OnBeforeUnload called"), msg);
-
- // Swaps the main frame.
- frame->OnMessageReceived(FrameMsg_SwapOut(
- frame->GetRoutingID(), 1, false, FrameReplicationState()));
- },
- base::Unretained(frame()))));
- render_thread_->sink().AddFilter(callback_filter.get());
+ base::RunLoop run_loop;
+ bool was_callback_run = false;
+ frame()->SetDidAddMessageToConsoleCallback(
+ base::BindOnce(base::BindLambdaForTesting([&](const base::string16& msg) {
+ // Makes sure this happens during the beforeunload handler.
+ EXPECT_EQ(base::UTF8ToUTF16("OnBeforeUnload called"), msg);
+
+ // Swaps the main frame.
+ frame()->OnMessageReceived(FrameMsg_SwapOut(
+ frame()->GetRoutingID(), 1, false, FrameReplicationState()));
+
+ was_callback_run = true;
+ run_loop.Quit();
+ })));
- // Simulates a BeforeUnload IPC received from the browser.
+ // Simulate a BeforeUnload IPC received from the browser.
frame()->OnMessageReceived(
FrameMsg_BeforeUnload(frame()->GetRoutingID(), false));
- render_thread_->sink().RemoveFilter(callback_filter.get());
+ run_loop.Run();
+ ASSERT_TRUE(was_callback_run);
}
// IPC Listener that runs a callback when a javascript modal dialog is
@@ -2730,7 +2597,7 @@ TEST_F(RenderViewImplEnableZoomForDSFTest,
SetDeviceScaleFactor(1.f);
#if defined(OS_WIN)
// http://crbug.com/508747
- if (base::win::GetVersion() >= base::win::VERSION_WIN10)
+ if (base::win::GetVersion() >= base::win::Version::WIN10)
return;
#endif
diff --git a/chromium/content/renderer/render_view_impl.cc b/chromium/content/renderer/render_view_impl.cc
index 83e40b6568d..1aa52af9027 100644
--- a/chromium/content/renderer/render_view_impl.cc
+++ b/chromium/content/renderer/render_view_impl.cc
@@ -68,7 +68,6 @@
#include "content/public/renderer/render_view_observer.h"
#include "content/public/renderer/render_view_visitor.h"
#include "content/public/renderer/window_features_converter.h"
-#include "content/renderer/appcache/web_application_cache_host_impl.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
#include "content/renderer/compositor/layer_tree_view.h"
@@ -88,7 +87,6 @@
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_widget_fullscreen_pepper.h"
#include "content/renderer/renderer_blink_platform_impl.h"
-#include "content/renderer/renderer_webapplicationcachehost_impl.h"
#include "content/renderer/savable_resources.h"
#include "content/renderer/v8_value_converter_impl.h"
#include "content/renderer/web_ui_extension_data.h"
@@ -130,8 +128,6 @@
#include "third_party/blink/public/public_buildflags.h"
#include "third_party/blink/public/web/web_autofill_client.h"
#include "third_party/blink/public/web/web_ax_object.h"
-#include "third_party/blink/public/web/web_date_time_chooser_completion.h"
-#include "third_party/blink/public/web/web_date_time_chooser_params.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_dom_event.h"
#include "third_party/blink/public/web/web_dom_message_event.h"
@@ -588,12 +584,6 @@ RenderViewImpl::~RenderViewImpl() {
DCHECK(!frame_widget_);
RenderThread::Get()->RemoveRoute(routing_id_);
-#if defined(OS_ANDROID)
- // The date/time picker client is both a std::unique_ptr member of this class
- // and a RenderViewObserver. Reset it to prevent double deletion.
- date_time_picker_client_.reset();
-#endif
-
#ifndef NDEBUG
// Make sure we are no longer referenced by the ViewMap or RoutingIDViewMap.
ViewMap* views = g_view_map.Pointer();
@@ -696,8 +686,6 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
WebRuntimeFeatures::EnableDatabase(prefs.databases_enabled);
settings->SetOfflineWebApplicationCacheEnabled(
prefs.application_cache_enabled);
- settings->SetHistoryEntryRequiresUserGesture(
- prefs.history_entry_requires_user_gesture);
settings->SetShouldProtectAgainstIpcFlooding(
!prefs.disable_ipc_flooding_protection);
settings->SetHyperlinkAuditingEnabled(prefs.hyperlink_auditing_enabled);
@@ -836,6 +824,7 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
web_view->SetDefaultPageScaleLimits(prefs.default_minimum_page_scale_factor,
prefs.default_maximum_page_scale_factor);
+ settings->SetFullscreenSupported(prefs.fullscreen_supported);
settings->SetTextAutosizingEnabled(prefs.text_autosizing_enabled);
settings->SetDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled);
blink::WebNetworkStateNotifier::SetNetworkQualityWebHoldback(
@@ -850,7 +839,6 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->SetAllowCustomScrollbarInMainFrame(false);
settings->SetAccessibilityFontScaleFactor(prefs.font_scale_factor);
settings->SetDeviceScaleAdjustment(prefs.device_scale_adjustment);
- settings->SetFullscreenSupported(prefs.fullscreen_supported);
web_view->SetIgnoreViewportTagScaleLimits(prefs.force_enable_zoom);
settings->SetAutoZoomFocusedNodeToLegibleScale(true);
settings->SetDefaultVideoPosterURL(
@@ -862,8 +850,6 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->SetWideViewportQuirkEnabled(prefs.wide_viewport_quirk);
settings->SetUseWideViewport(prefs.use_wide_viewport);
settings->SetForceZeroLayoutHeight(prefs.force_zero_layout_height);
- settings->SetViewportMetaLayoutSizeQuirk(
- prefs.viewport_meta_layout_size_quirk);
settings->SetViewportMetaMergeContentQuirk(
prefs.viewport_meta_merge_content_quirk);
settings->SetViewportMetaNonUserScalableQuirk(
@@ -1700,25 +1686,25 @@ void RenderViewImpl::FocusPrevious() {
Send(new ViewHostMsg_TakeFocus(GetRoutingID(), true));
}
-// TODO(esprehn): Blink only ever passes Elements, this should take WebElement.
-void RenderViewImpl::FocusedNodeChanged(const WebNode& fromNode,
- const WebNode& toNode) {
+void RenderViewImpl::FocusedElementChanged(const WebElement& from_element,
+ const WebElement& to_element) {
RenderFrameImpl* previous_frame = nullptr;
- if (!fromNode.IsNull())
+ if (!from_element.IsNull())
previous_frame =
- RenderFrameImpl::FromWebFrame(fromNode.GetDocument().GetFrame());
+ RenderFrameImpl::FromWebFrame(from_element.GetDocument().GetFrame());
RenderFrameImpl* new_frame = nullptr;
- if (!toNode.IsNull())
- new_frame = RenderFrameImpl::FromWebFrame(toNode.GetDocument().GetFrame());
+ if (!to_element.IsNull())
+ new_frame =
+ RenderFrameImpl::FromWebFrame(to_element.GetDocument().GetFrame());
if (previous_frame && previous_frame != new_frame)
- previous_frame->FocusedNodeChanged(WebNode());
+ previous_frame->FocusedElementChanged(WebElement());
if (new_frame)
- new_frame->FocusedNodeChanged(toNode);
+ new_frame->FocusedElementChanged(to_element);
// TODO(dmazzoni): remove once there's a separate a11y tree per frame.
if (main_render_frame_)
- main_render_frame_->FocusedNodeChangedForAccessibility(toNode);
+ main_render_frame_->FocusedElementChangedForAccessibility(to_element);
}
void RenderViewImpl::DidUpdateMainFrameLayout() {
@@ -1914,10 +1900,6 @@ blink::WebView* RenderViewImpl::GetWebView() {
return webview();
}
-blink::WebFrameWidget* RenderViewImpl::GetWebFrameWidget() {
- return frame_widget_;
-}
-
bool RenderViewImpl::GetContentStateImmediately() {
return send_content_state_immediately_;
}
@@ -1985,19 +1967,17 @@ void RenderViewImpl::OnSetRendererPrefs(
: base::TimeDelta::FromMilliseconds(
blink::mojom::kDefaultCaretBlinkIntervalInMilliseconds));
-#if BUILDFLAG(USE_DEFAULT_RENDER_THEME)
+#if defined(USE_AURA)
if (renderer_prefs.use_custom_colors) {
blink::SetFocusRingColor(renderer_prefs.focus_ring_color);
-
- if (webview()) {
- webview()->SetSelectionColors(renderer_prefs.active_selection_bg_color,
- renderer_prefs.active_selection_fg_color,
- renderer_prefs.inactive_selection_bg_color,
- renderer_prefs.inactive_selection_fg_color);
+ blink::SetSelectionColors(renderer_prefs.active_selection_bg_color,
+ renderer_prefs.active_selection_fg_color,
+ renderer_prefs.inactive_selection_bg_color,
+ renderer_prefs.inactive_selection_fg_color);
+ if (webview())
webview()->MainFrameWidget()->ThemeChanged();
- }
}
-#endif // BUILDFLAG(USE_DEFAULT_RENDER_THEME)
+#endif
if (webview() &&
old_accept_languages != renderer_preferences_.accept_languages) {
@@ -2081,17 +2061,12 @@ void RenderViewImpl::ZoomLimitsChanged(double minimum_level,
maximum_percent));
}
-void RenderViewImpl::PageScaleFactorChanged(float page_scale_factor,
- bool is_pinch_gesture_active) {
+void RenderViewImpl::PageScaleFactorChanged(float page_scale_factor) {
if (!webview())
return;
Send(new ViewHostMsg_PageScaleFactorChanged(GetRoutingID(),
page_scale_factor));
- // TODO(wjmaclean): Merge this into RenderWidget's
- // SetPageScaleFactorAndLimits().
- GetWidget()->PageScaleFactorChanged(page_scale_factor,
- is_pinch_gesture_active);
}
void RenderViewImpl::PageImportanceSignalsChanged() {
@@ -2165,22 +2140,6 @@ blink::WebScreenInfo RenderViewImpl::GetScreenInfo() {
}
#if defined(OS_ANDROID)
-bool RenderViewImpl::OpenDateTimeChooser(
- const blink::WebDateTimeChooserParams& params,
- blink::WebDateTimeChooserCompletion* completion) {
- // JavaScript may try to open a date time chooser while one is already open.
- if (date_time_picker_client_)
- return false;
- date_time_picker_client_.reset(
- new RendererDateTimePicker(this, params, completion));
- return date_time_picker_client_->Open();
-}
-
-void RenderViewImpl::DismissDateTimeDialog() {
- DCHECK(date_time_picker_client_);
- date_time_picker_client_.reset();
-}
-
void RenderViewImpl::SuspendVideoCaptureDevices(bool suspend) {
if (!main_render_frame_)
return;
diff --git a/chromium/content/renderer/render_view_impl.h b/chromium/content/renderer/render_view_impl.h
index ddb93ca74b4..f8edd186fb8 100644
--- a/chromium/content/renderer/render_view_impl.h
+++ b/chromium/content/renderer/render_view_impl.h
@@ -42,8 +42,8 @@
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/public/platform/web_input_event.h"
-#include "third_party/blink/public/platform/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/web/web_ax_object.h"
#include "third_party/blink/public/web/web_console_message.h"
@@ -59,22 +59,15 @@
#include "ui/gfx/geometry/rect_f.h"
#include "ui/surface/transport_dib.h"
-#if defined(OS_ANDROID)
-#include "content/renderer/android/renderer_date_time_picker.h"
-#endif
-
namespace blink {
-class WebDateTimeChooserCompletion;
class WebGestureEvent;
class WebMouseEvent;
class WebURLRequest;
-struct WebDateTimeChooserParams;
struct WebPluginAction;
struct WebWindowFeatures;
} // namespace blink
namespace content {
-class RendererDateTimePicker;
class RenderViewImplTest;
class RenderViewObserver;
class RenderViewTest;
@@ -162,10 +155,6 @@ class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient,
void AddObserver(RenderViewObserver* observer);
void RemoveObserver(RenderViewObserver* observer);
-#if defined(OS_ANDROID)
- void DismissDateTimeDialog();
-#endif
-
// Sets the zoom level and notifies observers.
void SetZoomLevel(double zoom_level);
@@ -246,16 +235,15 @@ class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient,
bool AcceptsLoadDrops() override;
void FocusNext() override;
void FocusPrevious() override;
- void FocusedNodeChanged(const blink::WebNode& fromNode,
- const blink::WebNode& toNode) override;
+ void FocusedElementChanged(const blink::WebElement& from_element,
+ const blink::WebElement& to_element) override;
bool CanUpdateLayout() override;
void DidUpdateMainFrameLayout() override;
blink::WebString AcceptLanguages() override;
int HistoryBackListCount() override;
int HistoryForwardListCount() override;
void ZoomLimitsChanged(double minimum_level, double maximum_level) override;
- void PageScaleFactorChanged(float page_scale_factor,
- bool is_pinch_gesture_active) override;
+ void PageScaleFactorChanged(float page_scale_factor) override;
void PageImportanceSignalsChanged() override;
void DidAutoResize(const blink::WebSize& newSize) override;
void DidFocus(blink::WebLocalFrame* calling_frame) override;
@@ -263,13 +251,6 @@ class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient,
bool CanHandleGestureEvent() override;
bool AllowPopupsDuringPageUnload() override;
-#if defined(OS_ANDROID)
- // Only used on Android since all other platforms implement
- // date and time input fields using MULTIPLE_FIELDS_UI
- bool OpenDateTimeChooser(const blink::WebDateTimeChooserParams&,
- blink::WebDateTimeChooserCompletion*) override;
-#endif
-
// RenderView implementation -------------------------------------------------
bool Send(IPC::Message* message) override;
@@ -281,7 +262,6 @@ class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient,
const WebPreferences& GetWebkitPreferences() override;
void SetWebkitPreferences(const WebPreferences& preferences) override;
blink::WebView* GetWebView() override;
- blink::WebFrameWidget* GetWebFrameWidget() override;
bool GetContentStateImmediately() override;
void SetEditCommandForNextKeyEvent(const std::string& name,
const std::string& value) override;
@@ -651,10 +631,7 @@ class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient,
blink::WebFrameWidget* frame_widget_ = nullptr;
#if defined(OS_ANDROID)
- // Android Specific ---------------------------------------------------------
-
- // A date/time picker object for date and time related input elements.
- std::unique_ptr<RendererDateTimePicker> date_time_picker_client_;
+ // Android Specific ----------------------------------------------------------
// Whether this was a renderer-created or browser-created RenderView.
bool was_created_by_renderer_ = false;
diff --git a/chromium/content/renderer/render_view_win.cc b/chromium/content/renderer/render_view_win.cc
index 5fe672aaf0a..40bf7a6d785 100644
--- a/chromium/content/renderer/render_view_win.cc
+++ b/chromium/content/renderer/render_view_win.cc
@@ -42,7 +42,7 @@ void RenderViewImpl::UpdateFontRenderingFromRendererPrefs() {
}
void RenderViewImpl::UpdateThemePrefs() {
- WebThemeEngineImpl::cacheScrollBarMetrics(
+ WebThemeEngineDefault::cacheScrollBarMetrics(
renderer_preferences_.vertical_scroll_bar_width_in_dips,
renderer_preferences_.horizontal_scroll_bar_height_in_dips,
renderer_preferences_.arrow_bitmap_height_vertical_scroll_bar_in_dips,
diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc
index 24449d77790..a450561913e 100644
--- a/chromium/content/renderer/render_widget.cc
+++ b/chromium/content/renderer/render_widget.cc
@@ -109,6 +109,7 @@
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/events/base_event_utils.h"
+#include "ui/events/types/scroll_types.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
@@ -129,10 +130,6 @@
#include "third_party/skia/include/core/SkPixelRef.h"
#endif // defined(OS_POSIX)
-#if defined(USE_AURA)
-#include "content/renderer/mus/renderer_window_tree_client.h"
-#endif
-
#if defined(OS_MACOSX)
#include "content/renderer/text_input_client_observer.h"
#endif
@@ -323,31 +320,29 @@ WebDragData DropDataToWebDragData(const DropData& drop_data) {
item_list.push_back(item);
}
- for (auto it = drop_data.filenames.begin(); it != drop_data.filenames.end();
- ++it) {
+ for (const ui::FileInfo& filename : drop_data.filenames) {
WebDragData::Item item;
item.storage_type = WebDragData::Item::kStorageTypeFilename;
- item.filename_data = blink::FilePathToWebString(it->path);
+ item.filename_data = blink::FilePathToWebString(filename.path);
item.display_name_data =
- blink::FilePathToWebString(base::FilePath(it->display_name));
+ blink::FilePathToWebString(base::FilePath(filename.display_name));
item_list.push_back(item);
}
- for (auto it = drop_data.file_system_files.begin();
- it != drop_data.file_system_files.end(); ++it) {
+ for (const DropData::FileSystemFileInfo& file : drop_data.file_system_files) {
WebDragData::Item item;
item.storage_type = WebDragData::Item::kStorageTypeFileSystemFile;
- item.file_system_url = it->url;
- item.file_system_file_size = it->size;
- item.file_system_id = blink::WebString::FromASCII(it->filesystem_id);
+ item.file_system_url = file.url;
+ item.file_system_file_size = file.size;
+ item.file_system_id = blink::WebString::FromASCII(file.filesystem_id);
item_list.push_back(item);
}
- for (const auto& it : drop_data.custom_data) {
+ for (const auto& data : drop_data.custom_data) {
WebDragData::Item item;
item.storage_type = WebDragData::Item::kStorageTypeString;
- item.string_type = WebString::FromUTF16(it.first);
- item.string_data = WebString::FromUTF16(it.second);
+ item.string_type = WebString::FromUTF16(data.first);
+ item.string_data = WebString::FromUTF16(data.second);
item_list.push_back(item);
}
@@ -492,11 +487,6 @@ RenderWidget::RenderWidget(int32_t widget_routing_id,
->NewRenderWidgetSchedulingState();
render_widget_scheduling_state_->SetHidden(is_hidden_);
}
-#if defined(USE_AURA)
- RendererWindowTreeClient::CreateIfNecessary(routing_id_);
- if (features::IsMultiProcessMash())
- RendererWindowTreeClient::Get(routing_id_)->SetVisible(!is_hidden_);
-#endif
if (routing_id_ != MSG_ROUTING_NONE)
g_routing_id_widget_map.Get().emplace(routing_id_, this);
@@ -510,13 +500,6 @@ RenderWidget::~RenderWidget() {
// and RenderViewImpl are rationalized. Currently, too many unit and
// browser tests delete a RenderWidget without correclty going through
// the shutdown. https://crbug.com/545684
-
-#if defined(USE_AURA)
- // It is possible for a RenderWidget to be destroyed before it was embedded
- // in a mus window. The RendererWindowTreeClient will leak in such cases. So
- // explicitly delete it here.
- RendererWindowTreeClient::Destroy(routing_id_);
-#endif
}
// static
@@ -948,13 +931,17 @@ void RenderWidget::OnWasHidden() {
SetHidden(true);
+ tab_switch_time_recorder_.TabWasHidden();
+
for (auto& observer : render_frames_)
observer.WasHidden();
}
-void RenderWidget::OnWasShown(base::TimeTicks show_request_timestamp,
- bool was_evicted,
- base::TimeTicks tab_switch_start_time) {
+void RenderWidget::OnWasShown(
+ base::TimeTicks show_request_timestamp,
+ bool was_evicted,
+ const base::Optional<content::RecordTabSwitchTimeRequest>&
+ record_tab_switch_time_request) {
// A frozen main frame widget does not become shown, since it has no frame
// associated with it. It must be thawed before changing visibility.
DCHECK(!is_frozen_);
@@ -965,11 +952,11 @@ void RenderWidget::OnWasShown(base::TimeTicks show_request_timestamp,
was_shown_time_ = base::TimeTicks::Now();
SetHidden(false);
- if (!show_request_timestamp.is_null()) {
+ if (record_tab_switch_time_request) {
layer_tree_view_->layer_tree_host()->RequestPresentationTimeForNextFrame(
- tab_switch_time_recorder_.BeginTimeRecording(
- tab_switch_start_time, false /* has_saved_frames */,
- show_request_timestamp));
+ tab_switch_time_recorder_.TabWasShown(
+ false /* has_saved_frames */,
+ record_tab_switch_time_request.value(), show_request_timestamp));
}
for (auto& observer : render_frames_)
@@ -1492,6 +1479,7 @@ void RenderWidget::UpdateTextInputStateInternal(bool show_virtual_keyboard,
TextInputState params;
params.type = new_type;
params.mode = new_mode;
+ params.action = new_info.action;
params.flags = new_info.flags;
#if defined(OS_ANDROID)
if (next_previous_flags_ == kInvalidNextPreviousFlagsValue) {
@@ -2530,14 +2518,8 @@ void RenderWidget::SetHidden(bool hidden) {
// throttled acks are released in case frame production ceases.
is_hidden_ = hidden;
-#if defined(USE_AURA)
- if (features::IsMultiProcessMash())
- RendererWindowTreeClient::Get(routing_id_)->SetVisible(!hidden);
-#endif
-
- if (is_hidden_) {
+ if (is_hidden_)
first_update_visual_state_after_hidden_ = true;
- }
if (render_widget_scheduling_state_)
render_widget_scheduling_state_->SetHidden(hidden);
@@ -2796,6 +2778,16 @@ void RenderWidget::DidOverscroll(
layer_tree_view_->layer_tree_host()->overscroll_behavior());
}
+void RenderWidget::InjectGestureScrollEvent(
+ blink::WebGestureDevice device,
+ const blink::WebFloatSize& delta,
+ ui::input_types::ScrollGranularity granularity,
+ cc::ElementId scrollable_area_element_id,
+ blink::WebInputEvent::Type injected_type) {
+ input_handler_->InjectGestureScrollEvent(
+ device, delta, granularity, scrollable_area_element_id, injected_type);
+}
+
void RenderWidget::SetOverscrollBehavior(
const cc::OverscrollBehavior& behavior) {
layer_tree_view_->layer_tree_host()->SetOverscrollBehavior(behavior);
@@ -2980,6 +2972,8 @@ cc::LayerTreeSettings RenderWidget::GenerateLayerTreeSettings(
cmd.HasSwitch(cc::switches::kShowLayerAnimationBounds);
settings.initial_debug_state.show_paint_rects =
cmd.HasSwitch(switches::kShowPaintRects);
+ settings.initial_debug_state.show_layout_shift_regions =
+ cmd.HasSwitch(switches::kShowLayoutShiftRegions);
settings.initial_debug_state.show_property_changed_rects =
cmd.HasSwitch(cc::switches::kShowPropertyChangedRects);
settings.initial_debug_state.show_surface_damage_rects =
@@ -3262,9 +3256,9 @@ cc::ManagedMemoryPolicy RenderWidget::GetGpuMemoryPolicy(
return actual;
}
-void RenderWidget::HasPointerRawMoveEventHandlers(bool has_handlers) {
+void RenderWidget::HasPointerRawUpdateEventHandlers(bool has_handlers) {
if (input_event_queue_)
- input_event_queue_->HasPointerRawMoveEventHandlers(has_handlers);
+ input_event_queue_->HasPointerRawUpdateEventHandlers(has_handlers);
}
void RenderWidget::HasTouchEventHandlers(bool has_handlers) {
@@ -3329,11 +3323,35 @@ void RenderWidget::SetAllowGpuRasterization(bool allow_gpu_raster) {
allow_gpu_raster);
}
-void RenderWidget::SetPageScaleFactorAndLimits(float page_scale_factor,
- float minimum,
- float maximum) {
+void RenderWidget::SetPageScaleStateAndLimits(float page_scale_factor,
+ bool is_pinch_gesture_active,
+ float minimum,
+ float maximum) {
layer_tree_view_->layer_tree_host()->SetPageScaleFactorAndLimits(
page_scale_factor, minimum, maximum);
+
+ // Only continue if this is a mainframe, or something's actually changed.
+ if (!delegate() ||
+ (page_scale_factor == page_scale_factor_from_mainframe_ &&
+ is_pinch_gesture_active == is_pinch_gesture_active_from_mainframe_)) {
+ return;
+ }
+
+ // The page scale is controlled by the WebView for the local main frame of
+ // the Page. So this is called from blink by for the RenderWidget of that
+ // local main frame. We forward the value on to each child RenderWidget (each
+ // of which will be via proxy child frame). These will each in turn forward
+ // the message to their child RenderWidgets (through their proxy child
+ // frames).
+ DCHECK(!is_frozen_);
+
+ for (auto& observer : render_frame_proxies_) {
+ observer.OnPageScaleFactorChanged(page_scale_factor,
+ is_pinch_gesture_active);
+ }
+ // Store the value to give to any new RenderFrameProxy that is registered.
+ page_scale_factor_from_mainframe_ = page_scale_factor;
+ is_pinch_gesture_active_from_mainframe_ = is_pinch_gesture_active;
}
void RenderWidget::StartPageScaleAnimation(const gfx::Vector2d& target_offset,
@@ -3393,7 +3411,8 @@ class ReportTimeSwapPromise : public cc::SwapPromise {
frame_token_));
}
- void DidNotSwap(DidNotSwapReason reason) override {
+ cc::SwapPromise::DidNotSwapAction DidNotSwap(
+ DidNotSwapReason reason) override {
blink::WebWidgetClient::SwapResult result;
switch (reason) {
case cc::SwapPromise::DidNotSwapReason::SWAP_FAILS:
@@ -3414,6 +3433,7 @@ class ReportTimeSwapPromise : public cc::SwapPromise {
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback_), result, base::TimeTicks::Now()));
+ return DidNotSwapAction::BREAK_PROMISE;
}
int64_t TraceId() const override { return 0; }
@@ -3611,26 +3631,6 @@ bool RenderWidget::IsSurfaceSynchronizationEnabled() const {
layer_tree_view_->IsSurfaceSynchronizationEnabled();
}
-void RenderWidget::PageScaleFactorChanged(float page_scale_factor,
- bool is_pinch_gesture_active) {
- // The page scale is controlled by the WebView for the local main frame of
- // the Page. So this is called from blink by for the RenderWidget of that
- // local main frame. We forward the value on to each child RenderWidget (each
- // of which will be via proxy child frame). These will each in turn forward
- // the message to their child RenderWidgets (through their proxy child
- // frames).
- DCHECK(!is_frozen_);
- DCHECK(delegate());
-
- for (auto& observer : render_frame_proxies_) {
- observer.OnPageScaleFactorChanged(page_scale_factor,
- is_pinch_gesture_active);
- }
- // Store the value to give to any new RenderFrameProxy that is registered.
- page_scale_factor_from_mainframe_ = page_scale_factor;
- is_pinch_gesture_active_from_mainframe_ = is_pinch_gesture_active;
-}
-
void RenderWidget::UseSynchronousResizeModeForTesting(bool enable) {
synchronous_resize_mode_for_testing_ = enable;
}
diff --git a/chromium/content/renderer/render_widget.h b/chromium/content/renderer/render_widget.h
index 2ff45a000ae..1115b02bc66 100644
--- a/chromium/content/renderer/render_widget.h
+++ b/chromium/content/renderer/render_widget.h
@@ -82,7 +82,6 @@ class WebRenderWidgetSchedulingState;
struct WebDeviceEmulationParams;
class WebDragData;
class WebFrameWidget;
-class WebGestureEvent;
class WebInputMethodController;
class WebLocalFrame;
class WebMouseEvent;
@@ -102,6 +101,9 @@ class Range;
namespace ui {
struct DidOverscrollParams;
+namespace input_types {
+enum class ScrollGranularity;
+}
}
namespace content {
@@ -409,6 +411,12 @@ class CONTENT_EXPORT RenderWidget
const blink::WebFloatSize& accumulated_overscroll,
const blink::WebFloatPoint& position,
const blink::WebFloatSize& velocity) override;
+ void InjectGestureScrollEvent(
+ blink::WebGestureDevice device,
+ const blink::WebFloatSize& delta,
+ ui::input_types::ScrollGranularity granularity,
+ cc::ElementId scrollable_area_element_id,
+ blink::WebInputEvent::Type injected_type) override;
void SetOverscrollBehavior(const cc::OverscrollBehavior&) override;
void ShowVirtualKeyboardOnElementFocus() override;
void ConvertViewportToWindow(blink::WebRect* rect) override;
@@ -423,7 +431,7 @@ class CONTENT_EXPORT RenderWidget
const gfx::Point& image_offset) override;
void SetTouchAction(cc::TouchAction touch_action) override;
void RequestUnbufferedInputEvents() override;
- void HasPointerRawMoveEventHandlers(bool has_handlers) override;
+ void HasPointerRawUpdateEventHandlers(bool has_handlers) override;
void HasTouchEventHandlers(bool has_handlers) override;
void SetNeedsLowLatencyInput(bool) override;
void SetNeedsUnbufferedInputForDebugger(bool) override;
@@ -440,9 +448,10 @@ class CONTENT_EXPORT RenderWidget
bool down) override;
void FallbackCursorModeSetCursorVisibility(bool visible) override;
void SetAllowGpuRasterization(bool allow_gpu_raster) override;
- void SetPageScaleFactorAndLimits(float page_scale_factor,
- float minimum,
- float maximum) override;
+ void SetPageScaleStateAndLimits(float page_scale_factor,
+ bool is_pinch_gesture_active,
+ float minimum,
+ float maximum) override;
void StartPageScaleAnimation(const gfx::Vector2d& destination,
bool use_anchor,
float new_page_scale,
@@ -619,9 +628,6 @@ class CONTENT_EXPORT RenderWidget
bool IsSurfaceSynchronizationEnabled() const;
- void PageScaleFactorChanged(float page_scale_factor,
- bool is_pinch_gesture_active);
-
void UseSynchronousResizeModeForTesting(bool enable);
void SetDeviceScaleFactorForTesting(float factor);
void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space);
@@ -739,7 +745,8 @@ class CONTENT_EXPORT RenderWidget
void OnWasHidden();
void OnWasShown(base::TimeTicks show_request_timestamp,
bool was_evicted,
- base::TimeTicks tab_switch_start_time);
+ const base::Optional<content::RecordTabSwitchTimeRequest>&
+ record_tab_switch_time_request);
void OnCreateVideoAck(int32_t video_id);
void OnUpdateVideoAck(int32_t video_id);
void OnRequestSetBoundsAck();
@@ -826,11 +833,6 @@ class CONTENT_EXPORT RenderWidget
// GetWindowRect() we'll use this pending window rect as the size.
void SetPendingWindowRect(const blink::WebRect& r);
- // TODO(ekaramad): This method should not be confused with its RenderView
- // variant, GetWebFrameWidget(). Currently Cast and AndroidWebview's
- // ContentRendererClients are the only users of the public variant. The public
- // method will eventually be removed from RenderView and uses of the method
- // will obtain WebFrameWidget from WebLocalFrame.
// Returns the WebFrameWidget associated with this RenderWidget if any.
// Returns nullptr if GetWebWidget() returns nullptr or returns a WebWidget
// that is not a WebFrameWidget. A WebFrameWidget only makes sense when there
diff --git a/chromium/content/renderer/render_widget_unittest.cc b/chromium/content/renderer/render_widget_unittest.cc
index eeb5d9b431b..1b7cf5d0e55 100644
--- a/chromium/content/renderer/render_widget_unittest.cc
+++ b/chromium/content/renderer/render_widget_unittest.cc
@@ -161,6 +161,7 @@ class StubWebPagePopup : public blink::WebPagePopup {
// WebPagePopup implementation.
blink::WebPoint PositionRelativeToOwner() override { return {}; }
+ blink::WebDocument GetDocument() override { return {}; }
blink::WebPagePopupClient* GetClientForTesting() const override {
return nullptr;
}
diff --git a/chromium/content/renderer/renderer_blink_platform_impl.cc b/chromium/content/renderer/renderer_blink_platform_impl.cc
index 30273211857..32f5e253cee 100644
--- a/chromium/content/renderer/renderer_blink_platform_impl.cc
+++ b/chromium/content/renderer/renderer_blink_platform_impl.cc
@@ -39,30 +39,24 @@
#include "content/public/common/service_names.mojom.h"
#include "content/public/common/webplugininfo.h"
#include "content/public/renderer/content_renderer_client.h"
-#include "content/public/renderer/media_stream_utils.h"
#include "content/public/renderer/render_frame.h"
#include "content/renderer/blob_storage/webblobregistry_impl.h"
#include "content/renderer/dom_storage/local_storage_cached_areas.h"
#include "content/renderer/dom_storage/local_storage_namespace.h"
#include "content/renderer/dom_storage/session_web_storage_namespace_impl.h"
#include "content/renderer/dom_storage/webstoragenamespace_impl.h"
-#include "content/renderer/image_capture/image_capture_frame_grabber.h"
#include "content/renderer/loader/child_url_loader_factory_bundle.h"
#include "content/renderer/loader/code_cache_loader_impl.h"
#include "content/renderer/loader/resource_dispatcher.h"
-#include "content/renderer/loader/web_data_consumer_handle_impl.h"
#include "content/renderer/loader/web_url_loader_impl.h"
#include "content/renderer/media/audio/audio_device_factory.h"
#include "content/renderer/media/audio_decoder.h"
#include "content/renderer/media/renderer_webaudiodevice_impl.h"
#include "content/renderer/media/webrtc/transmission_encoding_info_handler.h"
-#include "content/renderer/media_capture_from_element/canvas_capture_handler.h"
#include "content/renderer/media_capture_from_element/html_audio_element_capturer_source.h"
-#include "content/renderer/media_capture_from_element/html_video_element_capturer_source.h"
#include "content/renderer/media_recorder/media_recorder_handler.h"
#include "content/renderer/mojo/blink_interface_provider_impl.h"
#include "content/renderer/p2p/port_allocator.h"
-#include "content/renderer/push_messaging/push_provider.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/storage_util.h"
#include "content/renderer/web_database_observer_impl.h"
@@ -76,6 +70,7 @@
#include "media/audio/audio_output_device.h"
#include "media/blink/webcontentdecryptionmodule_impl.h"
#include "media/filters/stream_parser_factory.h"
+#include "mojo/public/cpp/base/big_buffer.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/platform_handle.h"
@@ -129,9 +124,7 @@ using blink::Platform;
using blink::WebAudioDevice;
using blink::WebAudioLatencyHint;
using blink::WebBlobRegistry;
-using blink::WebCanvasCaptureHandler;
using blink::WebDatabaseObserver;
-using blink::WebImageCaptureFrameGrabber;
using blink::WebMediaPlayer;
using blink::WebMediaRecorderHandler;
using blink::WebMediaStream;
@@ -290,12 +283,6 @@ RendererBlinkPlatformImpl::WrapSharedURLLoaderFactory(
std::move(factory));
}
-std::unique_ptr<blink::WebDataConsumerHandle>
-RendererBlinkPlatformImpl::CreateDataConsumerHandle(
- mojo::ScopedDataPipeConsumerHandle handle) {
- return std::make_unique<WebDataConsumerHandleImpl>(std::move(handle));
-}
-
scoped_refptr<ChildURLLoaderFactoryBundle>
RendererBlinkPlatformImpl::CreateDefaultURLLoaderFactoryBundle() {
return base::MakeRefCounted<ChildURLLoaderFactoryBundle>(
@@ -345,11 +332,6 @@ blink::WebSandboxSupport* RendererBlinkPlatformImpl::GetSandboxSupport() {
#endif
}
-blink::WebCookieJar* RendererBlinkPlatformImpl::CookieJar() {
- NOTREACHED() << "Use WebLocalFrameClient::cookieJar() instead!";
- return nullptr;
-}
-
blink::WebThemeEngine* RendererBlinkPlatformImpl::ThemeEngine() {
blink::WebThemeEngine* theme_engine =
GetContentClient()->renderer()->OverrideThemeEngine();
@@ -413,18 +395,24 @@ void RendererBlinkPlatformImpl::CacheMetadata(
// Let the browser know we generated cacheable metadata for this resource.
// The browser may cache it and return it on subsequent responses to speed
// the processing of this resource.
- std::vector<uint8_t> copy(data, data + size);
- GetCodeCacheHost().DidGenerateCacheableMetadata(cache_type, url,
- response_time, copy);
+ GetCodeCacheHost().DidGenerateCacheableMetadata(
+ cache_type, url, response_time,
+ mojo_base::BigBuffer(base::make_span(data, size)));
}
}
void RendererBlinkPlatformImpl::FetchCachedCode(
blink::mojom::CodeCacheType cache_type,
const GURL& url,
- base::OnceCallback<void(base::Time, const std::vector<uint8_t>&)>
- callback) {
- GetCodeCacheHost().FetchCachedCode(cache_type, url, std::move(callback));
+ FetchCachedCodeCallback callback) {
+ GetCodeCacheHost().FetchCachedCode(
+ cache_type, url,
+ base::BindOnce(
+ [](FetchCachedCodeCallback callback, base::Time time,
+ mojo_base::BigBuffer data) {
+ std::move(callback).Run(time, data);
+ },
+ std::move(callback)));
}
void RendererBlinkPlatformImpl::ClearCodeCacheEntry(
@@ -443,10 +431,9 @@ void RendererBlinkPlatformImpl::CacheMetadataInCacheStorage(
// Let the browser know we generated cacheable metadata for this resource in
// CacheStorage. The browser may cache it and return it on subsequent
// responses to speed the processing of this resource.
- std::vector<uint8_t> copy(data, data + size);
GetCodeCacheHost().DidGenerateCacheableMetadataInCacheStorage(
- url, response_time, copy, cacheStorageOrigin,
- cacheStorageCacheName.Utf8());
+ url, response_time, mojo_base::BigBuffer(base::make_span(data, size)),
+ cacheStorageOrigin, cacheStorageCacheName.Utf8());
}
WebString RendererBlinkPlatformImpl::DefaultLocale() {
@@ -755,31 +742,6 @@ RendererBlinkPlatformImpl::CreateWebRtcAsyncResolverFactory() {
//------------------------------------------------------------------------------
-std::unique_ptr<WebCanvasCaptureHandler>
-RendererBlinkPlatformImpl::CreateCanvasCaptureHandler(
- const WebSize& size,
- double frame_rate,
- WebMediaStreamTrack* track) {
- return CanvasCaptureHandler::CreateCanvasCaptureHandler(
- size, frame_rate, RenderThread::Get()->GetIOTaskRunner(), track);
-}
-
-//------------------------------------------------------------------------------
-
-void RendererBlinkPlatformImpl::CreateHTMLVideoElementCapturer(
- WebMediaStream* web_media_stream,
- WebMediaPlayer* web_media_player,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- DCHECK(web_media_stream);
- DCHECK(web_media_player);
- AddVideoTrackToMediaStream(
- HtmlVideoElementCapturerSource::CreateFromWebMediaPlayerImpl(
- web_media_player, content::RenderThread::Get()->GetIOTaskRunner(),
- std::move(task_runner)),
- false, // is_remote
- web_media_stream);
-}
-
void RendererBlinkPlatformImpl::CreateHTMLAudioElementCapturer(
WebMediaStream* web_media_stream,
WebMediaPlayer* web_media_player,
@@ -821,13 +783,6 @@ void RendererBlinkPlatformImpl::CreateHTMLAudioElementCapturer(
//------------------------------------------------------------------------------
-std::unique_ptr<WebImageCaptureFrameGrabber>
-RendererBlinkPlatformImpl::CreateImageCaptureFrameGrabber() {
- return std::make_unique<ImageCaptureFrameGrabber>();
-}
-
-//------------------------------------------------------------------------------
-
std::unique_ptr<webrtc::RtpCapabilities>
RendererBlinkPlatformImpl::GetRtpSenderCapabilities(
const blink::WebString& kind) {
@@ -932,9 +887,9 @@ RendererBlinkPlatformImpl::CreateOffscreenGraphicsContext3DProvider(
attributes.bind_generates_resource = false;
attributes.enable_raster_interface = web_attributes.enable_raster_interface;
- attributes.gpu_preference = web_attributes.prefer_integrated_gpu
- ? gl::PreferIntegratedGpu
- : gl::PreferDiscreteGpu;
+ attributes.gpu_preference = web_attributes.prefer_low_power_gpu
+ ? gl::GpuPreference::kLowPower
+ : gl::GpuPreference::kHighPerformance;
attributes.fail_if_major_perf_caveat =
web_attributes.fail_if_major_performance_caveat;
@@ -1003,7 +958,7 @@ RendererBlinkPlatformImpl::CreateWebGPUGraphicsContext3DProvider(
gpu::ContextCreationAttribs attributes;
// TODO(kainino): It's not clear yet how GPU preferences work for WebGPU.
- attributes.gpu_preference = gl::PreferDiscreteGpu;
+ attributes.gpu_preference = gl::GpuPreference::kHighPerformance;
attributes.enable_gles2_interface = false;
attributes.context_type = gpu::CONTEXT_TYPE_WEBGPU;
@@ -1062,12 +1017,6 @@ blink::InterfaceProvider* RendererBlinkPlatformImpl::GetInterfaceProvider() {
//------------------------------------------------------------------------------
-blink::WebPushProvider* RendererBlinkPlatformImpl::PushProvider() {
- return PushProvider::ThreadSpecificInstance(default_task_runner_);
-}
-
-//------------------------------------------------------------------------------
-
blink::WebTransmissionEncodingInfoHandler*
RendererBlinkPlatformImpl::TransmissionEncodingInfoHandler() {
if (!web_transmission_encoding_info_handler_) {
@@ -1101,6 +1050,13 @@ void RendererBlinkPlatformImpl::WorkerContextCreated(
worker);
}
+bool RendererBlinkPlatformImpl::IsExcludedHeaderForServiceWorkerFetchEvent(
+ const blink::WebString& header_name) {
+ return GetContentClient()
+ ->renderer()
+ ->IsExcludedHeaderForServiceWorkerFetchEvent(header_name.Ascii());
+}
+
//------------------------------------------------------------------------------
void RendererBlinkPlatformImpl::RecordMetricsForBackgroundedRendererPurge() {
diff --git a/chromium/content/renderer/renderer_blink_platform_impl.h b/chromium/content/renderer/renderer_blink_platform_impl.h
index 629362d2f99..ba77a976729 100644
--- a/chromium/content/renderer/renderer_blink_platform_impl.h
+++ b/chromium/content/renderer/renderer_blink_platform_impl.h
@@ -39,7 +39,6 @@ namespace blink {
namespace scheduler {
class WebThreadScheduler;
}
-class WebCanvasCaptureHandler;
class WebGraphicsContext3DProvider;
class WebMediaPlayer;
class WebMediaRecorderHandler;
@@ -73,7 +72,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
// Platform methods:
blink::WebSandboxSupport* GetSandboxSupport() override;
- blink::WebCookieJar* CookieJar() override;
blink::WebThemeEngine* ThemeEngine() override;
std::unique_ptr<blink::WebSpeechSynthesizer> CreateSpeechSynthesizer(
blink::WebSpeechSynthesizerClient* client) override;
@@ -88,11 +86,9 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
base::Time,
const uint8_t*,
size_t) override;
- void FetchCachedCode(
- blink::mojom::CodeCacheType cache_type,
- const GURL&,
- base::OnceCallback<void(base::Time, const std::vector<uint8_t>&)>)
- override;
+ void FetchCachedCode(blink::mojom::CodeCacheType cache_type,
+ const GURL&,
+ FetchCachedCodeCallback) override;
void ClearCodeCacheEntry(blink::mojom::CodeCacheType cache_type,
const GURL&) override;
void CacheMetadataInCacheStorage(
@@ -162,20 +158,10 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
blink::WebLocalFrame* frame) override;
std::unique_ptr<webrtc::AsyncResolverFactory>
CreateWebRtcAsyncResolverFactory() override;
- std::unique_ptr<blink::WebCanvasCaptureHandler> CreateCanvasCaptureHandler(
- const blink::WebSize& size,
- double frame_rate,
- blink::WebMediaStreamTrack* track) override;
- void CreateHTMLVideoElementCapturer(
- blink::WebMediaStream* web_media_stream,
- blink::WebMediaPlayer* web_media_player,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
void CreateHTMLAudioElementCapturer(
blink::WebMediaStream* web_media_stream,
blink::WebMediaPlayer* web_media_player,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
- std::unique_ptr<blink::WebImageCaptureFrameGrabber>
- CreateImageCaptureFrameGrabber() override;
std::unique_ptr<webrtc::RtpCapabilities> GetRtpSenderCapabilities(
const blink::WebString& kind) override;
std::unique_ptr<webrtc::RtpCapabilities> GetRtpReceiverCapabilities(
@@ -203,7 +189,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
void RecordRappor(const char* metric,
const blink::WebString& sample) override;
void RecordRapporURL(const char* metric, const blink::WebURL& url) override;
- blink::WebPushProvider* PushProvider() override;
blink::WebTransmissionEncodingInfoHandler* TransmissionEncodingInfoHandler()
override;
@@ -214,6 +199,8 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
void DidStartWorkerThread() override;
void WillStopWorkerThread() override;
void WorkerContextCreated(const v8::Local<v8::Context>& worker) override;
+ bool IsExcludedHeaderForServiceWorkerFetchEvent(
+ const blink::WebString& header_name) override;
void RecordMetricsForBackgroundedRendererPurge() override;
@@ -238,8 +225,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
mojo::ScopedMessagePipeHandle url_loader_factory_handle) override;
std::unique_ptr<blink::WebURLLoaderFactory> WrapSharedURLLoaderFactory(
scoped_refptr<network::SharedURLLoaderFactory> factory) override;
- std::unique_ptr<blink::WebDataConsumerHandle> CreateDataConsumerHandle(
- mojo::ScopedDataPipeConsumerHandle handle) override;
// Returns non-null.
// It is invalid to call this in an incomplete env where
diff --git a/chromium/content/renderer/renderer_main.cc b/chromium/content/renderer/renderer_main.cc
index 83814a41ccd..3ac5e999368 100644
--- a/chromium/content/renderer/renderer_main.cc
+++ b/chromium/content/renderer/renderer_main.cc
@@ -13,9 +13,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/pending_task.h"
#include "base/run_loop.h"
-#include "base/sampling_heap_profiler/sampling_heap_profiler.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
#include "base/system/sys_info.h"
#include "base/task/sequence_manager/sequence_manager.h"
#include "base/threading/platform_thread.h"
@@ -83,10 +81,9 @@ std::unique_ptr<base::MessagePump> CreateMainThreadMessagePump() {
// As long as scrollbars on Mac are painted with Cocoa, the message pump
// needs to be backed by a Foundation-level loop to process NSTimers. See
// http://crbug.com/306348#c24 for details.
- return std::make_unique<base::MessagePumpNSRunLoop>();
+ return base::MessagePump::Create(base::MessagePump::Type::NS_RUNLOOP);
#else
- return base::MessageLoop::CreateMessagePumpForType(
- base::MessageLoop::TYPE_DEFAULT);
+ return base::MessagePump::Create(base::MessagePump::Type::DEFAULT);
#endif
}
@@ -104,18 +101,6 @@ int RendererMain(const MainFunctionParams& parameters) {
const base::CommandLine& command_line = parameters.command_line;
- base::SamplingHeapProfiler::Init();
- if (command_line.HasSwitch(switches::kSamplingHeapProfiler)) {
- base::SamplingHeapProfiler* profiler = base::SamplingHeapProfiler::Get();
- unsigned sampling_interval = 0;
- bool parsed = base::StringToUint(
- command_line.GetSwitchValueASCII(switches::kSamplingHeapProfiler),
- &sampling_interval);
- if (parsed && sampling_interval > 0)
- profiler->SetSamplingInterval(sampling_interval * 1024);
- profiler->Start();
- }
-
#if defined(OS_MACOSX)
base::mac::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool;
#endif // OS_MACOSX
diff --git a/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc b/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc
deleted file mode 100644
index db213c080a1..00000000000
--- a/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/renderer_webapplicationcachehost_impl.h"
-
-#include <string>
-
-#include "content/renderer/render_frame_impl.h"
-#include "content/renderer/render_thread_impl.h"
-#include "content/renderer/render_view_impl.h"
-#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-#include "third_party/blink/public/web/web_frame.h"
-#include "third_party/blink/public/web/web_local_frame.h"
-#include "third_party/blink/public/web/web_view.h"
-
-using blink::WebApplicationCacheHostClient;
-using blink::WebConsoleMessage;
-
-namespace content {
-
-RendererWebApplicationCacheHostImpl::RendererWebApplicationCacheHostImpl(
- RenderViewImpl* render_view,
- WebApplicationCacheHostClient* client,
- int appcache_host_id,
- int frame_routing_id,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : WebApplicationCacheHostImpl(client,
- appcache_host_id,
- frame_routing_id,
- std::move(task_runner)),
- routing_id_(render_view->GetRoutingID()),
- frame_routing_id_(frame_routing_id) {}
-
-void RendererWebApplicationCacheHostImpl::LogMessage(
- blink::mojom::ConsoleMessageLevel log_level,
- const std::string& message) {
- if (RenderThreadImpl::current()->web_test_mode())
- return;
-
- RenderViewImpl* render_view = GetRenderView();
- if (!render_view || !render_view->webview() ||
- !render_view->webview()->MainFrame())
- return;
-
- blink::WebFrame* frame = render_view->webview()->MainFrame();
- if (!frame->IsWebLocalFrame())
- return;
- // TODO(michaeln): Make app cache host per-frame and correctly report to the
- // involved frame.
- frame->ToWebLocalFrame()->AddMessageToConsole(WebConsoleMessage(
- static_cast<blink::mojom::ConsoleMessageLevel>(log_level),
- blink::WebString::FromUTF8(message.c_str())));
-}
-
-void RendererWebApplicationCacheHostImpl::SetSubresourceFactory(
- network::mojom::URLLoaderFactoryPtr url_loader_factory) {
- RenderFrameImpl* render_frame =
- RenderFrameImpl::FromRoutingID(frame_routing_id_);
- if (render_frame) {
- auto info = std::make_unique<ChildURLLoaderFactoryBundleInfo>();
- info->appcache_factory_info() = url_loader_factory.PassInterface();
- render_frame->GetLoaderFactoryBundle()->Update(std::move(info));
- }
-}
-
-RenderViewImpl* RendererWebApplicationCacheHostImpl::GetRenderView() {
- return RenderViewImpl::FromRoutingID(routing_id_);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/renderer_webapplicationcachehost_impl.h b/chromium/content/renderer/renderer_webapplicationcachehost_impl.h
deleted file mode 100644
index b0dc037e71e..00000000000
--- a/chromium/content/renderer/renderer_webapplicationcachehost_impl.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_RENDERER_WEBAPPLICATIONCACHEHOST_IMPL_H_
-#define CONTENT_RENDERER_RENDERER_WEBAPPLICATIONCACHEHOST_IMPL_H_
-
-#include "content/renderer/appcache/web_application_cache_host_impl.h"
-
-#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
-
-namespace content {
-class RenderViewImpl;
-
-class RendererWebApplicationCacheHostImpl : public WebApplicationCacheHostImpl {
- public:
- RendererWebApplicationCacheHostImpl(
- RenderViewImpl* render_view,
- blink::WebApplicationCacheHostClient* client,
- int appcache_host_id,
- int frame_routing_id,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
-
- // blink::mojom::AppCacheHostFrontend:
- void LogMessage(blink::mojom::ConsoleMessageLevel log_level,
- const std::string& message) override;
-
- void SetSubresourceFactory(
- network::mojom::URLLoaderFactoryPtr url_loader_factory) override;
-
- private:
- RenderViewImpl* GetRenderView();
-
- int routing_id_;
- int frame_routing_id_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_RENDERER_WEBAPPLICATIONCACHEHOST_IMPL_H_
diff --git a/chromium/content/renderer/savable_resources_browsertest.cc b/chromium/content/renderer/savable_resources_browsertest.cc
index 98757ceafc5..08c18e33258 100644
--- a/chromium/content/renderer/savable_resources_browsertest.cc
+++ b/chromium/content/renderer/savable_resources_browsertest.cc
@@ -46,7 +46,7 @@ class SavableResourcesTest : public ContentBrowserTest {
// Load the test file.
NavigateToURL(shell(), file_url);
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&SavableResourcesTest::CheckResources, base::Unretained(this),
page_file_path, expected_resources_matcher,
expected_subframe_urls_matcher, file_url,
diff --git a/chromium/content/renderer/service_worker/controller_service_worker_impl.cc b/chromium/content/renderer/service_worker/controller_service_worker_impl.cc
deleted file mode 100644
index fdbc3161bfb..00000000000
--- a/chromium/content/renderer/service_worker/controller_service_worker_impl.cc
+++ /dev/null
@@ -1,39 +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/renderer/service_worker/controller_service_worker_impl.h"
-
-#include "base/sequenced_task_runner.h"
-#include "content/renderer/service_worker/service_worker_context_client.h"
-
-namespace content {
-
-ControllerServiceWorkerImpl::ControllerServiceWorkerImpl(
- blink::mojom::ControllerServiceWorkerRequest request,
- base::WeakPtr<ServiceWorkerContextClient> context_client,
- scoped_refptr<base::SequencedTaskRunner> task_runner)
- : context_client_(std::move(context_client)),
- task_runner_(std::move(task_runner)) {
- bindings_.AddBinding(this, std::move(request), task_runner_);
-}
-
-ControllerServiceWorkerImpl::~ControllerServiceWorkerImpl() = default;
-
-void ControllerServiceWorkerImpl::Clone(
- blink::mojom::ControllerServiceWorkerRequest request) {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- bindings_.AddBinding(this, std::move(request), task_runner_);
-}
-
-void ControllerServiceWorkerImpl::DispatchFetchEvent(
- blink::mojom::DispatchFetchEventParamsPtr params,
- blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- DispatchFetchEventCallback callback) {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- DCHECK(context_client_);
- context_client_->DispatchOrQueueFetchEvent(
- std::move(params), std::move(response_callback), std::move(callback));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/service_worker/controller_service_worker_impl.h b/chromium/content/renderer/service_worker/controller_service_worker_impl.h
deleted file mode 100644
index d2e56d84d65..00000000000
--- a/chromium/content/renderer/service_worker/controller_service_worker_impl.h
+++ /dev/null
@@ -1,68 +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_RENDERER_SERVICE_WORKER_CONTROLLER_SERVICE_WORKER_IMPL_H_
-#define CONTENT_RENDERER_SERVICE_WORKER_CONTROLLER_SERVICE_WORKER_IMPL_H_
-
-#include <utility>
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
-
-namespace base {
-class SequencedTaskRunner;
-}
-
-namespace content {
-
-class ServiceWorkerContextClient;
-
-// An instance of this class is created on the service worker thread
-// when ServiceWorkerContextClient's WorkerContextData is created.
-// This implements blink::mojom::ControllerServiceWorker and its Mojo endpoint
-// is connected by each controllee and also by the ServiceWorkerProviderHost
-// in the browser process.
-// Subresource requests made by the controllees are sent to this class as
-// Fetch events via the Mojo endpoints.
-//
-// TODO(kinuko): Implement self-killing timer, that does something similar to
-// what ServiceWorkerVersion::StopWorkerIfIdle did in the browser process in
-// the non-S13n codepath.
-class ControllerServiceWorkerImpl
- : public blink::mojom::ControllerServiceWorker {
- public:
- // |context_client|'s weak pointer is the one that is bound to the worker
- // thread. (It should actually outlive this instance, but allow us to make
- // sure the thread safety)
- ControllerServiceWorkerImpl(
- blink::mojom::ControllerServiceWorkerRequest request,
- base::WeakPtr<ServiceWorkerContextClient> context_client,
- scoped_refptr<base::SequencedTaskRunner> task_runner);
- ~ControllerServiceWorkerImpl() override;
-
- // blink::mojom::ControllerServiceWorker:
- void DispatchFetchEvent(
- blink::mojom::DispatchFetchEventParamsPtr params,
- blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- DispatchFetchEventCallback callback) override;
- void Clone(blink::mojom::ControllerServiceWorkerRequest request) override;
-
- private:
- // Connected by the ServiceWorkerProviderHost in the browser process
- // and by the controllees.
- mojo::BindingSet<blink::mojom::ControllerServiceWorker> bindings_;
-
- // This should never be null because |context_client_| owns |this|.
- // TODO(falken): Make this a raw pointer.
- base::WeakPtr<ServiceWorkerContextClient> context_client_;
-
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(ControllerServiceWorkerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_SERVICE_WORKER_CONTROLLER_SERVICE_WORKER_IMPL_H_
diff --git a/chromium/content/renderer/service_worker/navigation_preload_request.cc b/chromium/content/renderer/service_worker/navigation_preload_request.cc
index 141e99ba5ee..5f9af11e641 100644
--- a/chromium/content/renderer/service_worker/navigation_preload_request.cc
+++ b/chromium/content/renderer/service_worker/navigation_preload_request.cc
@@ -15,11 +15,11 @@
namespace content {
NavigationPreloadRequest::NavigationPreloadRequest(
- base::WeakPtr<ServiceWorkerContextClient> owner,
+ ServiceWorkerContextClient* owner,
int fetch_event_id,
const GURL& url,
blink::mojom::FetchEventPreloadHandlePtr preload_handle)
- : owner_(std::move(owner)),
+ : owner_(owner),
fetch_event_id_(fetch_event_id),
url_(url),
url_loader_(std::move(preload_handle->url_loader)),
@@ -46,7 +46,6 @@ void NavigationPreloadRequest::OnReceiveRedirect(
DCHECK(net::HttpResponseHeaders::IsRedirectResponseCode(
response_head.headers->response_code()));
- DCHECK(owner_);
response_ = std::make_unique<blink::WebURLResponse>();
WebURLLoaderImpl::PopulateURLResponse(url_, response_head, response_.get(),
false /* report_security_info */,
@@ -68,7 +67,7 @@ void NavigationPreloadRequest::OnUploadProgress(
}
void NavigationPreloadRequest::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {}
+ mojo_base::BigBuffer data) {}
void NavigationPreloadRequest::OnTransferSizeUpdated(
int32_t transfer_size_diff) {}
@@ -106,7 +105,6 @@ void NavigationPreloadRequest::OnComplete(
return;
}
- DCHECK(owner_);
if (response_) {
// When the response body from the server is empty, OnComplete() is called
// without OnStartLoadingResponseBody().
@@ -123,7 +121,6 @@ void NavigationPreloadRequest::OnComplete(
void NavigationPreloadRequest::MaybeReportResponseToOwner() {
if (!response_ || !body_.is_valid())
return;
- DCHECK(owner_);
owner_->OnNavigationPreloadResponse(fetch_event_id_, std::move(response_),
std::move(body_));
}
@@ -131,7 +128,6 @@ void NavigationPreloadRequest::MaybeReportResponseToOwner() {
void NavigationPreloadRequest::ReportErrorToOwner(
const std::string& message,
const std::string& unsanitized_message) {
- DCHECK(owner_);
// This will delete |this|.
owner_->OnNavigationPreloadError(
fetch_event_id_, std::make_unique<blink::WebServiceWorkerError>(
diff --git a/chromium/content/renderer/service_worker/navigation_preload_request.h b/chromium/content/renderer/service_worker/navigation_preload_request.h
index 98dd5c64a33..44ab5483593 100644
--- a/chromium/content/renderer/service_worker/navigation_preload_request.h
+++ b/chromium/content/renderer/service_worker/navigation_preload_request.h
@@ -9,7 +9,6 @@
#include <string>
#include <vector>
-#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "services/network/public/mojom/url_loader.mojom.h"
@@ -19,6 +18,8 @@
namespace content {
+class ServiceWorkerContextClient;
+
// The URLLoaderClient for receiving a navigation preload response. It reports
// the response back to ServiceWorkerContextClient.
//
@@ -28,7 +29,7 @@ class NavigationPreloadRequest final : public network::mojom::URLLoaderClient {
public:
// |owner| must outlive |this|.
NavigationPreloadRequest(
- base::WeakPtr<ServiceWorkerContextClient> owner,
+ ServiceWorkerContextClient* owner,
int fetch_event_id,
const GURL& url,
blink::mojom::FetchEventPreloadHandlePtr preload_handle);
@@ -43,7 +44,7 @@ class NavigationPreloadRequest final : public network::mojom::URLLoaderClient {
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
@@ -54,10 +55,7 @@ class NavigationPreloadRequest final : public network::mojom::URLLoaderClient {
void ReportErrorToOwner(const std::string& message,
const std::string& unsanitized_message);
- // TODO(crbug.com/907311): This is just a WeakPtr to do a CHECK that the owner
- // really outlives this, as we've been getting related crashes. Change this to
- // a raw pointer when the bug is fixed.
- base::WeakPtr<ServiceWorkerContextClient> owner_;
+ ServiceWorkerContextClient* owner_;
const int fetch_event_id_;
const GURL url_;
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.cc b/chromium/content/renderer/service_worker/service_worker_context_client.cc
index 97573079e2b..a090c5bfdcb 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client.cc
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.cc
@@ -31,43 +31,31 @@
#include "content/public/renderer/worker_thread.h"
#include "content/renderer/loader/child_url_loader_factory_bundle.h"
#include "content/renderer/loader/tracked_child_url_loader_factory_bundle.h"
-#include "content/renderer/loader/web_data_consumer_handle_impl.h"
#include "content/renderer/loader/web_url_loader_impl.h"
#include "content/renderer/loader/web_url_request_util.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/renderer_blink_platform_impl.h"
-#include "content/renderer/service_worker/controller_service_worker_impl.h"
#include "content/renderer/service_worker/embedded_worker_instance_client_impl.h"
#include "content/renderer/service_worker/navigation_preload_request.h"
#include "content/renderer/service_worker/service_worker_fetch_context_impl.h"
#include "content/renderer/service_worker/service_worker_network_provider_for_service_worker.h"
-#include "content/renderer/service_worker/service_worker_timeout_timer.h"
#include "content/renderer/service_worker/service_worker_type_converters.h"
-#include "content/renderer/service_worker/service_worker_type_util.h"
#include "net/base/net_errors.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "storage/common/blob_storage/blob_handle.h"
#include "third_party/blink/public/common/messaging/message_port_channel.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"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"
+#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom.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_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
#include "third_party/blink/public/platform/interface_provider.h"
-#include "third_party/blink/public/platform/modules/background_fetch/web_background_fetch_registration.h"
-#include "third_party/blink/public/platform/modules/notifications/web_notification_data.h"
-#include "third_party/blink/public/platform/modules/payments/web_payment_handler_response.h"
-#include "third_party/blink/public/platform/modules/payments/web_payment_request_event_data.h"
-#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_clients_info.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h"
-#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
-#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
-#include "third_party/blink/public/platform/notification_data_conversions.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_blob_registry.h"
@@ -89,191 +77,19 @@ namespace {
constexpr char kServiceWorkerContextClientScope[] =
"ServiceWorkerContextClient";
-class StreamHandleListener
- : public blink::WebServiceWorkerStreamHandle::Listener {
- public:
- StreamHandleListener(
- blink::mojom::ServiceWorkerStreamCallbackPtr callback_ptr,
- std::unique_ptr<ServiceWorkerTimeoutTimer::StayAwakeToken> token)
- : callback_ptr_(std::move(callback_ptr)), token_(std::move(token)) {}
-
- ~StreamHandleListener() override {}
-
- void OnAborted() override {
- callback_ptr_->OnAborted();
- token_.reset();
- }
-
- void OnCompleted() override {
- callback_ptr_->OnCompleted();
- token_.reset();
- }
-
- private:
- blink::mojom::ServiceWorkerStreamCallbackPtr callback_ptr_;
- std::unique_ptr<ServiceWorkerTimeoutTimer::StayAwakeToken> token_;
-};
-
-blink::WebServiceWorkerClientInfo ToWebServiceWorkerClientInfo(
- blink::mojom::ServiceWorkerClientInfoPtr client_info) {
- DCHECK(!client_info->client_uuid.empty());
-
- blink::WebServiceWorkerClientInfo web_client_info;
-
- web_client_info.uuid = blink::WebString::FromASCII(client_info->client_uuid);
- web_client_info.page_hidden = client_info->page_hidden;
- web_client_info.is_focused = client_info->is_focused;
- web_client_info.url = client_info->url;
- web_client_info.frame_type = client_info->frame_type;
- web_client_info.client_type = client_info->client_type;
-
- return web_client_info;
-}
-
-// Converts a blink::mojom::BackgroundFetchRegistrationPtr object to
-// a blink::WebBackgroundFetchRegistration object.
-blink::WebBackgroundFetchRegistration ToWebBackgroundFetchRegistration(
- blink::mojom::BackgroundFetchRegistrationPtr registration) {
- return blink::WebBackgroundFetchRegistration(
- blink::WebString::FromUTF8(registration->registration_data->developer_id),
- registration->registration_data->upload_total,
- registration->registration_data->uploaded,
- registration->registration_data->download_total,
- registration->registration_data->downloaded,
- registration->registration_data->result,
- registration->registration_data->failure_reason,
- mojo::ScopedMessagePipeHandle(
- registration->registration_interface.PassHandle()),
- registration->registration_interface.version());
-}
-
-// This is complementary to ConvertWebKitPriorityToNetPriority, defined in
-// web_url_loader_impl.cc.
-WebURLRequest::Priority ConvertNetPriorityToWebKitPriority(
- const net::RequestPriority priority) {
- switch (priority) {
- case net::HIGHEST:
- return WebURLRequest::Priority::kVeryHigh;
- case net::MEDIUM:
- return WebURLRequest::Priority::kHigh;
- case net::LOW:
- return WebURLRequest::Priority::kMedium;
- case net::LOWEST:
- return WebURLRequest::Priority::kLow;
- case net::IDLE:
- return WebURLRequest::Priority::kVeryLow;
- case net::THROTTLED:
- NOTREACHED();
- return WebURLRequest::Priority::kVeryLow;
- }
-
- NOTREACHED();
- return WebURLRequest::Priority::kVeryLow;
-}
-
-// Finds an event callback keyed by |event_id| from |map|, and runs the callback
-// with |args|. Returns true if the callback was found and called, otherwise
-// returns false.
-template <typename MapType, class... Args>
-bool RunEventCallback(MapType* map,
- ServiceWorkerTimeoutTimer* timer,
- int event_id,
- Args... args) {
- auto iter = map->find(event_id);
- // The event may have been aborted.
- if (iter == map->end())
- return false;
- std::move(iter->second).Run(args...);
- map->erase(iter);
- timer->EndEvent(event_id);
- return true;
-}
-
-// Creates a callback which takes an |event_id| and |status|, which calls the
-// given event's callback with the given status and removes it from |map|.
-template <typename MapType, typename... Args>
-ServiceWorkerTimeoutTimer::AbortCallback CreateAbortCallback(MapType* map,
- Args... args) {
- return base::BindOnce(
- [](MapType* map, Args... args, int event_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- auto iter = map->find(event_id);
- DCHECK(iter != map->end());
- std::move(iter->second).Run(status, std::forward<Args>(args)...);
- map->erase(iter);
- },
- map, std::forward<Args>(args)...);
-}
-
} // namespace
// Holds data that needs to be bound to the worker context on the
// worker thread.
struct ServiceWorkerContextClient::WorkerContextData {
explicit WorkerContextData(ServiceWorkerContextClient* owner)
- : service_worker_binding(owner),
- weak_factory(owner),
- proxy_weak_factory(owner->proxy_) {}
+ : weak_factory(owner), proxy_weak_factory(owner->proxy_) {}
~WorkerContextData() { DCHECK(thread_checker.CalledOnValidThread()); }
- mojo::Binding<blink::mojom::ServiceWorker> service_worker_binding;
-
- // Maps for inflight event callbacks.
- // These are mapped from an event id issued from ServiceWorkerTimeoutTimer to
- // the Mojo callback to notify the end of the event.
- std::map<int, DispatchInstallEventCallback> install_event_callbacks;
- std::map<int, DispatchActivateEventCallback> activate_event_callbacks;
- std::map<int, DispatchBackgroundFetchAbortEventCallback>
- background_fetch_abort_event_callbacks;
- std::map<int, DispatchBackgroundFetchClickEventCallback>
- background_fetch_click_event_callbacks;
- std::map<int, DispatchBackgroundFetchFailEventCallback>
- background_fetch_fail_event_callbacks;
- std::map<int, DispatchBackgroundFetchSuccessEventCallback>
- background_fetched_event_callbacks;
- std::map<int, DispatchSyncEventCallback> sync_event_callbacks;
- std::map<int, payments::mojom::PaymentHandlerResponseCallbackPtr>
- abort_payment_result_callbacks;
- std::map<int, DispatchCanMakePaymentEventCallback>
- abort_payment_event_callbacks;
- std::map<int, DispatchCanMakePaymentEventCallback>
- can_make_payment_event_callbacks;
- std::map<int, DispatchPaymentRequestEventCallback>
- payment_request_event_callbacks;
- std::map<int, DispatchNotificationClickEventCallback>
- notification_click_event_callbacks;
- std::map<int, DispatchNotificationCloseEventCallback>
- notification_close_event_callbacks;
- std::map<int, DispatchPushEventCallback> push_event_callbacks;
- std::map<int, DispatchFetchEventCallback> fetch_event_callbacks;
- std::map<int, DispatchCookieChangeEventCallback>
- cookie_change_event_callbacks;
- std::map<int, DispatchExtendableMessageEventCallback> message_event_callbacks;
-
- // Maps for response callbacks.
- // These are mapped from an event id to the Mojo interface pointer which is
- // passed from the relevant DispatchSomeEvent() method.
- std::map<int, payments::mojom::PaymentHandlerResponseCallbackPtr>
- can_make_payment_result_callbacks;
- std::map<int, payments::mojom::PaymentHandlerResponseCallbackPtr>
- payment_response_callbacks;
- std::map<int, blink::mojom::ServiceWorkerFetchResponseCallbackPtr>
- fetch_response_callbacks;
-
// Inflight navigation preload requests.
base::IDMap<std::unique_ptr<NavigationPreloadRequest>> preload_requests;
- // Timer triggered when the service worker considers it should be stopped or
- // an event should be aborted.
- std::unique_ptr<ServiceWorkerTimeoutTimer> timeout_timer;
-
- // |controller_impl| should be destroyed before |timeout_timer| since the
- // pipe needs to be disconnected before callbacks passed by
- // DispatchSomeEvent() get destructed, which may be stored in |timeout_timer|
- // as parameters of pending tasks added after a termination request.
- std::unique_ptr<ControllerServiceWorkerImpl> controller_impl;
-
base::ThreadChecker thread_checker;
base::WeakPtrFactory<ServiceWorkerContextClient> weak_factory;
base::WeakPtrFactory<blink::WebServiceWorkerContextProxy> proxy_weak_factory;
@@ -443,25 +259,11 @@ void ServiceWorkerContextClient::WorkerContextStarted(
context_ = std::make_unique<WorkerContextData>(this);
DCHECK(pending_service_worker_request_.is_pending());
+ proxy_->BindServiceWorker(pending_service_worker_request_.PassMessagePipe());
+
DCHECK(pending_controller_request_.is_pending());
- DCHECK(!context_->service_worker_binding.is_bound());
- DCHECK(!context_->controller_impl);
- context_->service_worker_binding.Bind(
- std::move(pending_service_worker_request_), worker_task_runner_);
-
- auto weak_ptr = GetWeakPtr();
- // Intentionally dereferences the weak ptr in order to
- // ensure the WeakPtrFactory is bound to this thread (the worker thread).
- weak_ptr = weak_ptr->GetWeakPtr();
- context_->controller_impl = std::make_unique<ControllerServiceWorkerImpl>(
- std::move(pending_controller_request_), std::move(weak_ptr),
- worker_task_runner_);
-
- // Create the idle timer. At this point the timer is not started. It will be
- // started after the WorkerStarted message is sent.
- context_->timeout_timer =
- std::make_unique<ServiceWorkerTimeoutTimer>(base::BindRepeating(
- &ServiceWorkerContextClient::OnIdleTimeout, base::Unretained(this)));
+ proxy_->BindControllerServiceWorker(
+ pending_controller_request_.PassMessagePipe());
}
void ServiceWorkerContextClient::WillEvaluateScript() {
@@ -508,6 +310,12 @@ void ServiceWorkerContextClient::DidEvaluateScript(bool success) {
GetWeakPtr(), status));
}
+void ServiceWorkerContextClient::WillInitializeWorkerContext() {
+ GetContentClient()
+ ->renderer()
+ ->WillInitializeServiceWorkerContextOnWorkerThread();
+}
+
void ServiceWorkerContextClient::DidInitializeWorkerContext(
v8::Local<v8::Context> context) {
DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
@@ -576,447 +384,6 @@ void ServiceWorkerContextClient::ReportConsoleMessage(
blink::WebStringToGURL(source_url));
}
-void ServiceWorkerContextClient::DidHandleActivateEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleActivateEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- RunEventCallback(&context_->activate_event_callbacks,
- context_->timeout_timer.get(), request_id, status);
-}
-
-void ServiceWorkerContextClient::DidHandleBackgroundFetchAbortEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1(
- "ServiceWorker",
- "ServiceWorkerContextClient::DidHandleBackgroundFetchAbortEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- RunEventCallback(&context_->background_fetch_abort_event_callbacks,
- context_->timeout_timer.get(), request_id, status);
-}
-
-void ServiceWorkerContextClient::DidHandleBackgroundFetchClickEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1(
- "ServiceWorker",
- "ServiceWorkerContextClient::DidHandleBackgroundFetchClickEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- RunEventCallback(&context_->background_fetch_click_event_callbacks,
- context_->timeout_timer.get(), request_id, status);
-}
-
-void ServiceWorkerContextClient::DidHandleBackgroundFetchFailEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1(
- "ServiceWorker",
- "ServiceWorkerContextClient::DidHandleBackgroundFetchFailEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- RunEventCallback(&context_->background_fetch_fail_event_callbacks,
- context_->timeout_timer.get(), request_id, status);
-}
-
-void ServiceWorkerContextClient::DidHandleBackgroundFetchSuccessEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1(
- "ServiceWorker",
- "ServiceWorkerContextClient::DidHandleBackgroundFetchSuccessEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- RunEventCallback(&context_->background_fetched_event_callbacks,
- context_->timeout_timer.get(), request_id, status);
-}
-
-void ServiceWorkerContextClient::DidHandleCookieChangeEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1(
- "ServiceWorker", "ServiceWorkerContextClient::DidHandleCookieChangeEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- RunEventCallback(&context_->cookie_change_event_callbacks,
- context_->timeout_timer.get(), request_id, status);
-}
-
-void ServiceWorkerContextClient::DidHandleExtendableMessageEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1(
- "ServiceWorker",
- "ServiceWorkerContextClient::DidHandleExtendableMessageEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- RunEventCallback(&context_->message_event_callbacks,
- context_->timeout_timer.get(), request_id, status);
-}
-
-void ServiceWorkerContextClient::DidHandleInstallEvent(
- int event_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- proxy_->SetFetchHandlerExistence(proxy_->HasFetchEventHandler()
- ? FetchHandlerExistence::EXISTS
- : FetchHandlerExistence::DOES_NOT_EXIST);
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleInstallEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(event_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- RunEventCallback(&context_->install_event_callbacks,
- context_->timeout_timer.get(), event_id, status,
- proxy_->HasFetchEventHandler());
-}
-
-void ServiceWorkerContextClient::RespondToFetchEventWithNoResponse(
- int fetch_event_id,
- base::TimeTicks event_dispatch_time,
- base::TimeTicks respond_with_settled_time) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::RespondToFetchEventWithNoResponse",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(fetch_event_id)),
- TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
- DCHECK(base::ContainsKey(context_->fetch_response_callbacks, fetch_event_id));
- const blink::mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback =
- context_->fetch_response_callbacks[fetch_event_id];
-
- auto timing = blink::mojom::ServiceWorkerFetchEventTiming::New();
- timing->dispatch_event_time = event_dispatch_time;
- timing->respond_with_settled_time = respond_with_settled_time;
-
- response_callback->OnFallback(std::move(timing));
- context_->fetch_response_callbacks.erase(fetch_event_id);
-}
-
-void ServiceWorkerContextClient::RespondToFetchEvent(
- int fetch_event_id,
- const blink::WebServiceWorkerResponse& web_response,
- base::TimeTicks event_dispatch_time,
- base::TimeTicks respond_with_settled_time) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker", "ServiceWorkerContextClient::RespondToFetchEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(fetch_event_id)),
- TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
- DCHECK(base::ContainsKey(context_->fetch_response_callbacks, fetch_event_id));
-
- blink::mojom::FetchAPIResponsePtr response(
- GetFetchAPIResponseFromWebResponse(web_response));
- const blink::mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback =
- context_->fetch_response_callbacks[fetch_event_id];
-
- auto timing = blink::mojom::ServiceWorkerFetchEventTiming::New();
- timing->dispatch_event_time = event_dispatch_time;
- timing->respond_with_settled_time = respond_with_settled_time;
-
- response_callback->OnResponse(std::move(response), std::move(timing));
- context_->fetch_response_callbacks.erase(fetch_event_id);
-}
-
-void ServiceWorkerContextClient::RespondToFetchEventWithResponseStream(
- int fetch_event_id,
- const blink::WebServiceWorkerResponse& web_response,
- blink::WebServiceWorkerStreamHandle* web_body_as_stream,
- base::TimeTicks event_dispatch_time,
- base::TimeTicks respond_with_settled_time) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::RespondToFetchEventWithResponseStream",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(fetch_event_id)),
- TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
- DCHECK(base::ContainsKey(context_->fetch_response_callbacks, fetch_event_id));
- blink::mojom::FetchAPIResponsePtr response(
- GetFetchAPIResponseFromWebResponse(web_response));
- const blink::mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback =
- context_->fetch_response_callbacks[fetch_event_id];
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream =
- blink::mojom::ServiceWorkerStreamHandle::New();
- blink::mojom::ServiceWorkerStreamCallbackPtr callback_ptr;
- body_as_stream->callback_request = mojo::MakeRequest(&callback_ptr);
- body_as_stream->stream = web_body_as_stream->DrainStreamDataPipe();
- DCHECK(body_as_stream->stream.is_valid());
-
- web_body_as_stream->SetListener(std::make_unique<StreamHandleListener>(
- std::move(callback_ptr),
- context_->timeout_timer->CreateStayAwakeToken()));
-
- auto timing = blink::mojom::ServiceWorkerFetchEventTiming::New();
- timing->dispatch_event_time = event_dispatch_time;
- timing->respond_with_settled_time = respond_with_settled_time;
-
- response_callback->OnResponseStream(
- std::move(response), std::move(body_as_stream), std::move(timing));
- context_->fetch_response_callbacks.erase(fetch_event_id);
-}
-
-void ServiceWorkerContextClient::DidHandleFetchEvent(
- int event_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- // This TRACE_EVENT is used for perf benchmark to confirm if all of fetch
- // events have completed. (crbug.com/736697)
- TRACE_EVENT_WITH_FLOW1("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleFetchEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(event_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- if (!RunEventCallback(&context_->fetch_event_callbacks,
- context_->timeout_timer.get(), event_id, status)) {
- // The event may have been aborted. Its response callback also needs to be
- // deleted.
- context_->fetch_response_callbacks.erase(event_id);
- } else {
- // |fetch_response_callback| should be used before settling a promise for
- // waitUntil().
- DCHECK(!base::ContainsKey(context_->fetch_response_callbacks, event_id));
- }
-}
-
-void ServiceWorkerContextClient::DidHandleNotificationClickEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1(
- "ServiceWorker",
- "ServiceWorkerContextClient::DidHandleNotificationClickEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- RunEventCallback(&context_->notification_click_event_callbacks,
- context_->timeout_timer.get(), request_id, status);
-}
-
-void ServiceWorkerContextClient::DidHandleNotificationCloseEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1(
- "ServiceWorker",
- "ServiceWorkerContextClient::DidHandleNotificationCloseEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- RunEventCallback(&context_->notification_close_event_callbacks,
- context_->timeout_timer.get(), request_id, status);
-}
-
-void ServiceWorkerContextClient::DidHandlePushEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1("ServiceWorker",
- "ServiceWorkerContextClient::DidHandlePushEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- RunEventCallback(&context_->push_event_callbacks,
- context_->timeout_timer.get(), request_id, status);
-}
-
-void ServiceWorkerContextClient::DidHandleSyncEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleSyncEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- RunEventCallback(&context_->sync_event_callbacks,
- context_->timeout_timer.get(), request_id, status);
-}
-
-void ServiceWorkerContextClient::RespondToAbortPaymentEvent(
- int event_id,
- bool payment_aborted) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker", "ServiceWorkerContextClient::RespondToAbortPaymentEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(event_id)),
- TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
- DCHECK(base::ContainsKey(context_->abort_payment_result_callbacks, event_id));
- const payments::mojom::PaymentHandlerResponseCallbackPtr& result_callback =
- context_->abort_payment_result_callbacks[event_id];
- result_callback->OnResponseForAbortPayment(payment_aborted);
- context_->abort_payment_result_callbacks.erase(event_id);
-}
-
-void ServiceWorkerContextClient::DidHandleAbortPaymentEvent(
- int event_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1(
- "ServiceWorker", "ServiceWorkerContextClient::DidHandleAbortPaymentEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(event_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- if (RunEventCallback(&context_->abort_payment_event_callbacks,
- context_->timeout_timer.get(), event_id, status)) {
- context_->abort_payment_result_callbacks.erase(event_id);
- }
-}
-
-void ServiceWorkerContextClient::RespondToCanMakePaymentEvent(
- int event_id,
- bool can_make_payment) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::RespondToCanMakePaymentEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(event_id)),
- TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
- DCHECK(
- base::ContainsKey(context_->can_make_payment_result_callbacks, event_id));
- const payments::mojom::PaymentHandlerResponseCallbackPtr& result_callback =
- context_->can_make_payment_result_callbacks[event_id];
- result_callback->OnResponseForCanMakePayment(can_make_payment);
- context_->can_make_payment_result_callbacks.erase(event_id);
-}
-
-void ServiceWorkerContextClient::DidHandleCanMakePaymentEvent(
- int event_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1(
- "ServiceWorker",
- "ServiceWorkerContextClient::DidHandleCanMakePaymentEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(event_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- if (RunEventCallback(&context_->can_make_payment_event_callbacks,
- context_->timeout_timer.get(), event_id, status)) {
- context_->can_make_payment_result_callbacks.erase(event_id);
- }
-}
-
-void ServiceWorkerContextClient::RespondToPaymentRequestEvent(
- int payment_request_id,
- const blink::WebPaymentHandlerResponse& web_response) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::RespondToPaymentRequestEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(payment_request_id)),
- TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
- DCHECK(base::ContainsKey(context_->payment_response_callbacks,
- payment_request_id));
- const payments::mojom::PaymentHandlerResponseCallbackPtr& response_callback =
- context_->payment_response_callbacks[payment_request_id];
- payments::mojom::PaymentHandlerResponsePtr response =
- payments::mojom::PaymentHandlerResponse::New();
- response->method_name = web_response.method_name.Utf8();
- response->stringified_details = web_response.stringified_details.Utf8();
- response_callback->OnResponseForPaymentRequest(std::move(response));
- context_->payment_response_callbacks.erase(payment_request_id);
-}
-
-void ServiceWorkerContextClient::DidHandlePaymentRequestEvent(
- int payment_request_id,
- blink::mojom::ServiceWorkerEventStatus status) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- if (!context_)
- return;
- TRACE_EVENT_WITH_FLOW1(
- "ServiceWorker",
- "ServiceWorkerContextClient::DidHandlePaymentRequestEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(payment_request_id)),
- TRACE_EVENT_FLAG_FLOW_IN, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
- if (RunEventCallback(&context_->payment_request_event_callbacks,
- context_->timeout_timer.get(), payment_request_id,
- status)) {
- context_->payment_response_callbacks.erase(payment_request_id);
- }
-}
-
std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
ServiceWorkerContextClient::CreateServiceWorkerNetworkProviderOnMainThread() {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
@@ -1061,143 +428,6 @@ ServiceWorkerContextClient::CreateServiceWorkerFetchContextOnMainThread(
std::move(preference_watcher_request_));
}
-int ServiceWorkerContextClient::WillStartTask() {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // This is called from the Blink's code running in the worker thread and we
- // expect |context_| to still be alive.
- DCHECK(context_);
- DCHECK(context_->timeout_timer);
- return context_->timeout_timer->StartEvent(base::DoNothing());
-}
-
-void ServiceWorkerContextClient::DidEndTask(int task_id) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // This is called from the Blink's code running in the worker thread and we
- // expect |context_| to still be alive.
- DCHECK(context_);
- DCHECK(context_->timeout_timer);
- // Check if the task is still alive, since the timeout timer might have
- // already timed it out (which calls the abort callback passed to StartEvent()
- // but that does nothing, since we just check HasEvent() here instead of
- // maintaining our own set of started events).
- if (context_->timeout_timer->HasEvent(task_id))
- context_->timeout_timer->EndEvent(task_id);
-}
-
-void ServiceWorkerContextClient::DispatchOrQueueFetchEvent(
- blink::mojom::DispatchFetchEventParamsPtr params,
- blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- DispatchFetchEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DispatchOrQueueFetchEvent", "url",
- params->request->url.spec(), "queued",
- RequestedTermination() ? "true" : "false");
- if (RequestedTermination()) {
- context_->timeout_timer->PushPendingTask(base::BindOnce(
- &ServiceWorkerContextClient::DispatchFetchEvent, GetWeakPtr(),
- std::move(params), std::move(response_callback), std::move(callback)));
- return;
- }
- DispatchFetchEvent(std::move(params), std::move(response_callback),
- std::move(callback));
-}
-
-void ServiceWorkerContextClient::DispatchSyncEvent(
- const std::string& tag,
- bool last_chance,
- base::TimeDelta timeout,
- DispatchSyncEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int request_id = context_->timeout_timer->StartEventWithCustomTimeout(
- CreateAbortCallback(&context_->sync_event_callbacks), timeout);
- context_->sync_event_callbacks.emplace(request_id, std::move(callback));
- TRACE_EVENT_WITH_FLOW0("ServiceWorker",
- "ServiceWorkerContextClient::DispatchSyncEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
-
- // TODO(jkarlin): Make this blink::WebString::FromUTF8Lenient once
- // https://crrev.com/1768063002/ lands.
- proxy_->DispatchSyncEvent(request_id, blink::WebString::FromUTF8(tag),
- last_chance);
-}
-
-void ServiceWorkerContextClient::DispatchAbortPaymentEvent(
- payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- DispatchAbortPaymentEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // Valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int event_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->abort_payment_event_callbacks));
- context_->abort_payment_event_callbacks.emplace(event_id,
- std::move(callback));
- context_->abort_payment_result_callbacks.emplace(
- event_id, std::move(response_callback));
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker", "ServiceWorkerContextClient::DispatchAbortPaymentEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(event_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
- proxy_->DispatchAbortPaymentEvent(event_id);
-}
-
-void ServiceWorkerContextClient::DispatchCanMakePaymentEvent(
- payments::mojom::CanMakePaymentEventDataPtr eventData,
- payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- DispatchCanMakePaymentEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // Valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int event_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->can_make_payment_event_callbacks));
- context_->can_make_payment_event_callbacks.emplace(event_id,
- std::move(callback));
- context_->can_make_payment_result_callbacks.emplace(
- event_id, std::move(response_callback));
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::DispatchCanMakePaymentEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(event_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
-
- blink::WebCanMakePaymentEventData webEventData =
- mojo::ConvertTo<blink::WebCanMakePaymentEventData>(std::move(eventData));
- proxy_->DispatchCanMakePaymentEvent(event_id, webEventData);
-}
-
-void ServiceWorkerContextClient::DispatchPaymentRequestEvent(
- payments::mojom::PaymentRequestEventDataPtr eventData,
- payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- DispatchPaymentRequestEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // Valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int event_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->payment_request_event_callbacks));
- context_->payment_request_event_callbacks.emplace(event_id,
- std::move(callback));
- context_->payment_response_callbacks.emplace(event_id,
- std::move(response_callback));
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::DispatchPaymentRequestEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(event_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
-
- blink::WebPaymentRequestEventData webEventData =
- mojo::ConvertTo<blink::WebPaymentRequestEventData>(std::move(eventData));
- proxy_->DispatchPaymentRequestEvent(event_id, webEventData);
-}
-
void ServiceWorkerContextClient::OnNavigationPreloadResponse(
int fetch_event_id,
std::unique_ptr<blink::WebURLResponse> response,
@@ -1249,64 +479,6 @@ void ServiceWorkerContextClient::OnNavigationPreloadComplete(
context_->preload_requests.Remove(fetch_event_id);
}
-void ServiceWorkerContextClient::ToWebServiceWorkerRequestForFetchEvent(
- blink::mojom::FetchAPIRequestPtr request,
- const std::string& client_id,
- blink::WebServiceWorkerRequest* web_request) {
- DCHECK(web_request);
- web_request->SetURL(blink::WebURL(request->url));
- web_request->SetMethod(blink::WebString::FromUTF8(request->method));
- for (const auto& pair : request->headers) {
- if (!GetContentClient()
- ->renderer()
- ->IsExcludedHeaderForServiceWorkerFetchEvent(pair.first)) {
- web_request->SetHeader(blink::WebString::FromUTF8(pair.first),
- blink::WebString::FromUTF8(pair.second));
- }
- }
-
- // The body is provided in |request->body|.
- DCHECK(!request->blob);
- if (request->body) {
- std::vector<blink::mojom::BlobPtrInfo> blob_ptrs;
- if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- // We need this as GetBlobFromUUID is a sync IPC.
- // TODO(kinuko): Remove the friend for ScopedAllowBaseSyncPrimitives
- // in //base as well when we remove this code.
- base::ScopedAllowBaseSyncPrimitives allow_sync_primitives;
- blob_ptrs = GetBlobPtrsForRequestBody(*request->body);
- }
- blink::WebHTTPBody body = GetWebHTTPBodyForRequestBodyWithBlobPtrs(
- *request->body, std::move(blob_ptrs));
- body.SetUniqueBoundary();
- web_request->SetBody(body);
- }
-
- if (request->referrer) {
- web_request->SetReferrer(
- blink::WebString::FromUTF8(request->referrer->url.spec()),
- request->referrer->policy);
- }
- web_request->SetMode(request->mode);
- web_request->SetIsMainResourceLoad(request->is_main_resource_load);
- web_request->SetCredentialsMode(request->credentials_mode);
- web_request->SetCacheMode(request->cache_mode);
- web_request->SetRedirectMode(request->redirect_mode);
- web_request->SetRequestContext(request->request_context_type);
- web_request->SetFrameType(request->frame_type);
- web_request->SetClientId(blink::WebString::FromUTF8(client_id));
- web_request->SetIsReload(request->is_reload);
- if (request->integrity) {
- web_request->SetIntegrity(blink::WebString::FromUTF8(*request->integrity));
- }
- web_request->SetPriority(
- ConvertNetPriorityToWebKitPriority(request->priority));
- web_request->SetKeepalive(request->keepalive);
- web_request->SetIsHistoryNavigation(request->is_history_navigation);
- if (request->fetch_window_id)
- web_request->SetWindowId(*request->fetch_window_id);
-}
-
void ServiceWorkerContextClient::SendWorkerStarted(
blink::mojom::ServiceWorkerStartStatus status) {
DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
@@ -1337,415 +509,32 @@ void ServiceWorkerContextClient::SendWorkerStarted(
->OnStarted(status, WorkerThread::GetCurrentId(),
std::move(start_timing_));
- context_->timeout_timer->Start();
TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "ServiceWorkerContextClient",
this);
}
-void ServiceWorkerContextClient::DispatchActivateEvent(
- DispatchActivateEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int request_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->activate_event_callbacks));
- context_->activate_event_callbacks.emplace(request_id, std::move(callback));
- TRACE_EVENT_WITH_FLOW0("ServiceWorker",
- "ServiceWorkerContextClient::DispatchActivateEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
- proxy_->DispatchActivateEvent(request_id);
-}
-
-void ServiceWorkerContextClient::DispatchBackgroundFetchAbortEvent(
- blink::mojom::BackgroundFetchRegistrationPtr registration,
- DispatchBackgroundFetchAbortEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int request_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->background_fetch_abort_event_callbacks));
- context_->background_fetch_abort_event_callbacks.emplace(request_id,
- std::move(callback));
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::DispatchBackgroundFetchAbortEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
-
- proxy_->DispatchBackgroundFetchAbortEvent(
- request_id, ToWebBackgroundFetchRegistration(std::move(registration)));
-}
-
-void ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent(
- blink::mojom::BackgroundFetchRegistrationPtr registration,
- DispatchBackgroundFetchClickEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int request_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->background_fetch_click_event_callbacks));
- context_->background_fetch_click_event_callbacks.emplace(request_id,
- std::move(callback));
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
-
- proxy_->DispatchBackgroundFetchClickEvent(
- request_id, ToWebBackgroundFetchRegistration(std::move(registration)));
-}
-
-void ServiceWorkerContextClient::DispatchBackgroundFetchFailEvent(
- blink::mojom::BackgroundFetchRegistrationPtr registration,
- DispatchBackgroundFetchFailEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int request_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->background_fetch_fail_event_callbacks));
- context_->background_fetch_fail_event_callbacks.emplace(request_id,
- std::move(callback));
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::DispatchBackgroundFetchFailEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
-
- proxy_->DispatchBackgroundFetchFailEvent(
- request_id, ToWebBackgroundFetchRegistration(std::move(registration)));
-}
-
-void ServiceWorkerContextClient::DispatchBackgroundFetchSuccessEvent(
- blink::mojom::BackgroundFetchRegistrationPtr registration,
- DispatchBackgroundFetchSuccessEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int request_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->background_fetched_event_callbacks));
- context_->background_fetched_event_callbacks.emplace(request_id,
- std::move(callback));
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::DispatchBackgroundFetchSuccessEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
-
- proxy_->DispatchBackgroundFetchSuccessEvent(
- request_id, ToWebBackgroundFetchRegistration(std::move(registration)));
-}
-
-void ServiceWorkerContextClient::InitializeGlobalScope(
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
- blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info,
- FetchHandlerExistence fetch_handler_existence) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // Connect to the blink::mojom::ServiceWorkerHost.
- proxy_->BindServiceWorkerHost(service_worker_host.PassHandle());
- // Set ServiceWorkerGlobalScope#registration.
- DCHECK_NE(registration_info->registration_id,
- blink::mojom::kInvalidServiceWorkerRegistrationId);
- DCHECK(registration_info->host_ptr_info.is_valid());
- DCHECK(registration_info->request.is_pending());
- proxy_->SetRegistration(
- registration_info.To<blink::WebServiceWorkerRegistrationObjectInfo>());
- proxy_->SetFetchHandlerExistence(fetch_handler_existence);
-
- proxy_->ReadyToEvaluateScript();
-}
-
-void ServiceWorkerContextClient::DispatchInstallEvent(
- DispatchInstallEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int event_id = context_->timeout_timer->StartEvent(CreateAbortCallback(
- &context_->install_event_callbacks, false /* has_fetch_handler */));
- context_->install_event_callbacks.emplace(event_id, std::move(callback));
- TRACE_EVENT_WITH_FLOW0("ServiceWorker",
- "ServiceWorkerContextClient::DispatchInstallEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(event_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
-
- proxy_->DispatchInstallEvent(event_id);
-}
-
-void ServiceWorkerContextClient::DispatchExtendableMessageEvent(
- blink::mojom::ExtendableMessageEventPtr event,
- DispatchExtendableMessageEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int request_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->message_event_callbacks));
- context_->message_event_callbacks.emplace(request_id, std::move(callback));
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::DispatchExtendableMessageEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
-
- if (event->source_info_for_client) {
- blink::WebServiceWorkerClientInfo web_client =
- ToWebServiceWorkerClientInfo(std::move(event->source_info_for_client));
- proxy_->DispatchExtendableMessageEvent(request_id,
- std::move(event->message),
- event->source_origin, web_client);
- return;
- }
-
- DCHECK_NE(event->source_info_for_service_worker->version_id,
- blink::mojom::kInvalidServiceWorkerVersionId);
- proxy_->DispatchExtendableMessageEvent(
- request_id, std::move(event->message), event->source_origin,
- event->source_info_for_service_worker
- .To<blink::WebServiceWorkerObjectInfo>());
-}
-
-void ServiceWorkerContextClient::
- DispatchExtendableMessageEventWithCustomTimeout(
- blink::mojom::ExtendableMessageEventPtr event,
- base::TimeDelta timeout,
- DispatchExtendableMessageEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int request_id = context_->timeout_timer->StartEventWithCustomTimeout(
- CreateAbortCallback(&context_->message_event_callbacks), timeout);
-
- context_->message_event_callbacks.emplace(request_id, std::move(callback));
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::"
- "DispatchExtendableMessageEventWithCustomTimeout",
- "request_id", request_id);
-
- if (event->source_info_for_client) {
- blink::WebServiceWorkerClientInfo web_client =
- ToWebServiceWorkerClientInfo(std::move(event->source_info_for_client));
- proxy_->DispatchExtendableMessageEvent(request_id,
- std::move(event->message),
- event->source_origin, web_client);
- return;
- }
-
- DCHECK_NE(event->source_info_for_service_worker->version_id,
- blink::mojom::kInvalidServiceWorkerVersionId);
- proxy_->DispatchExtendableMessageEvent(
- request_id, std::move(event->message), event->source_origin,
- event->source_info_for_service_worker
- .To<blink::WebServiceWorkerObjectInfo>());
-}
-
-void ServiceWorkerContextClient::DispatchFetchEvent(
- blink::mojom::DispatchFetchEventParamsPtr params,
- blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- DispatchFetchEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(context_);
- int event_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->fetch_event_callbacks));
- context_->fetch_event_callbacks.emplace(event_id, std::move(callback));
- context_->fetch_response_callbacks.emplace(event_id,
- std::move(response_callback));
-
- // This TRACE_EVENT is used for perf benchmark to confirm if all of fetch
- // events have completed. (crbug.com/736697)
- TRACE_EVENT_WITH_FLOW1(
- "ServiceWorker", "ServiceWorkerContextClient::DispatchFetchEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(event_id)),
- TRACE_EVENT_FLAG_FLOW_OUT, "url", params->request->url.spec());
-
- // Set up for navigation preload (FetchEvent#preloadResponse) if needed.
- const bool navigation_preload_sent = !!params->preload_handle;
- if (navigation_preload_sent) {
- SetupNavigationPreload(event_id, params->request->url,
- std::move(params->preload_handle));
- }
-
- // Dispatch the event to the service worker execution context.
- blink::WebServiceWorkerRequest web_request;
- ToWebServiceWorkerRequestForFetchEvent(std::move(params->request),
- params->client_id, &web_request);
- proxy_->DispatchFetchEvent(event_id, web_request, navigation_preload_sent);
-}
-
-void ServiceWorkerContextClient::DispatchNotificationClickEvent(
- const std::string& notification_id,
- const blink::PlatformNotificationData& notification_data,
- int action_index,
- const base::Optional<base::string16>& reply,
- DispatchNotificationClickEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(context_);
- int request_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->notification_click_event_callbacks));
- context_->notification_click_event_callbacks.emplace(request_id,
- std::move(callback));
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::DispatchNotificationClickEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
-
- blink::WebString web_reply;
- if (reply)
- web_reply = blink::WebString::FromUTF16(reply.value());
-
- proxy_->DispatchNotificationClickEvent(
- request_id, blink::WebString::FromUTF8(notification_id),
- ToWebNotificationData(notification_data), action_index, web_reply);
-}
-
-void ServiceWorkerContextClient::DispatchNotificationCloseEvent(
- const std::string& notification_id,
- const blink::PlatformNotificationData& notification_data,
- DispatchNotificationCloseEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(context_);
- int request_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->notification_close_event_callbacks));
- context_->notification_close_event_callbacks.emplace(request_id,
- std::move(callback));
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerContextClient::DispatchNotificationCloseEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
- proxy_->DispatchNotificationCloseEvent(
- request_id, blink::WebString::FromUTF8(notification_id),
- ToWebNotificationData(notification_data));
-}
-
-void ServiceWorkerContextClient::DispatchPushEvent(
- const base::Optional<std::string>& payload,
- DispatchPushEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int request_id = context_->timeout_timer->StartEventWithCustomTimeout(
- CreateAbortCallback(&context_->push_event_callbacks),
- base::TimeDelta::FromSeconds(blink::mojom::kPushEventTimeoutSeconds));
- context_->push_event_callbacks.emplace(request_id, std::move(callback));
- TRACE_EVENT_WITH_FLOW0("ServiceWorker",
- "ServiceWorkerContextClient::DispatchPushEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
-
- // Only set data to be a valid string if the payload had decrypted data.
- blink::WebString data;
- if (payload)
- data = blink::WebString::FromUTF8(*payload);
- proxy_->DispatchPushEvent(request_id, data);
-}
-
-void ServiceWorkerContextClient::DispatchCookieChangeEvent(
- const net::CanonicalCookie& cookie,
- ::network::mojom::CookieChangeCause cause,
- DispatchCookieChangeEventCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- int request_id = context_->timeout_timer->StartEvent(
- CreateAbortCallback(&context_->cookie_change_event_callbacks));
- context_->cookie_change_event_callbacks.emplace(request_id,
- std::move(callback));
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker", "ServiceWorkerContextClient::DispatchCookieChangeEvent",
- TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
- TRACE_ID_LOCAL(request_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
-
- // After onion-souping, the conversion below will be done by mojo directly.
- DCHECK(!cookie.IsHttpOnly());
- base::Optional<blink::WebCanonicalCookie> web_cookie_opt =
- blink::WebCanonicalCookie::Create(
- blink::WebString::FromUTF8(cookie.Name()),
- blink::WebString::FromUTF8(cookie.Value()),
- blink::WebString::FromUTF8(cookie.Domain()),
- blink::WebString::FromUTF8(cookie.Path()), cookie.CreationDate(),
- cookie.ExpiryDate(), cookie.LastAccessDate(), cookie.IsSecure(),
- false /* cookie.IsHttpOnly() */,
- static_cast<network::mojom::CookieSameSite>(cookie.SameSite()),
- static_cast<network::mojom::CookiePriority>(cookie.Priority()));
- DCHECK(web_cookie_opt.has_value());
-
- proxy_->DispatchCookieChangeEvent(request_id, web_cookie_opt.value(), cause);
-}
-
-void ServiceWorkerContextClient::Ping(PingCallback callback) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- std::move(callback).Run();
-}
-
-void ServiceWorkerContextClient::SetIdleTimerDelayToZero() {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- DCHECK(context_->timeout_timer);
- context_->timeout_timer->SetIdleTimerDelayToZero();
-}
-
void ServiceWorkerContextClient::SetupNavigationPreload(
int fetch_event_id,
- const GURL& url,
- blink::mojom::FetchEventPreloadHandlePtr preload_handle) {
+ const blink::WebURL& url,
+ std::unique_ptr<blink::WebFetchEventPreloadHandle> preload_handle) {
DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because it's valid in our callsite.
DCHECK(context_);
auto preload_request = std::make_unique<NavigationPreloadRequest>(
- GetWeakPtr(), fetch_event_id, url, std::move(preload_handle));
+ this, fetch_event_id, GURL(url),
+ blink::mojom::FetchEventPreloadHandle::New(
+ network::mojom::URLLoaderPtrInfo(
+ std::move(preload_handle->url_loader),
+ network::mojom::URLLoader::Version_),
+ network::mojom::URLLoaderClientRequest(
+ std::move(preload_handle->url_loader_client_request))));
context_->preload_requests.AddWithID(std::move(preload_request),
fetch_event_id);
}
-void ServiceWorkerContextClient::OnIdleTimeout() {
+void ServiceWorkerContextClient::RequestTermination(
+ RequestTerminationCallback callback) {
DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because this is called by a timer owned by |context_|.
- DCHECK(context_);
- // RequestedTermination() returns true if ServiceWorkerTimeoutTimer agrees
- // we should request the host to terminate this worker now.
- DCHECK(RequestedTermination());
- (*instance_host_)
- ->RequestTermination(base::BindOnce(
- &ServiceWorkerContextClient::OnRequestedTermination, GetWeakPtr()));
-}
-
-void ServiceWorkerContextClient::OnRequestedTermination(
- bool will_be_terminated) {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because the Mojo binding is on |worker_task_runner_|.
- DCHECK(context_);
- DCHECK(context_->timeout_timer);
-
- // This worker will be terminated soon. Ignore the message.
- if (will_be_terminated)
- return;
-
- // Dispatch a dummy event to run all of queued tasks. This updates the
- // idle timer too.
- const int event_id = context_->timeout_timer->StartEvent(base::DoNothing());
- context_->timeout_timer->EndEvent(event_id);
-}
-
-bool ServiceWorkerContextClient::RequestedTermination() const {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- // |context_| is valid because it's valid at our callsites.
- DCHECK(context_);
- DCHECK(context_->timeout_timer);
- return context_->timeout_timer->did_idle_timeout();
+ (*instance_host_)->RequestTermination(std::move(callback));
}
void ServiceWorkerContextClient::StopWorkerOnMainThread() {
@@ -1760,17 +549,4 @@ ServiceWorkerContextClient::GetWeakPtr() {
return context_->weak_factory.GetWeakPtr();
}
-void ServiceWorkerContextClient::SetTimeoutTimerForTesting(
- std::unique_ptr<ServiceWorkerTimeoutTimer> timeout_timer) {
- DCHECK(context_);
- context_->timeout_timer = std::move(timeout_timer);
-}
-
-ServiceWorkerTimeoutTimer*
-ServiceWorkerContextClient::GetTimeoutTimerForTesting() {
- DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(context_);
- return context_->timeout_timer.get();
-}
-
} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.h b/chromium/content/renderer/service_worker/service_worker_context_client.h
index ddf79ccb60c..2f72219b676 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client.h
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.h
@@ -44,9 +44,7 @@ class SingleThreadTaskRunner;
}
namespace blink {
-struct PlatformNotificationData;
class WebServiceWorkerContextProxy;
-class WebServiceWorkerResponse;
class WebURLResponse;
}
@@ -54,7 +52,6 @@ namespace content {
class EmbeddedWorkerInstanceClientImpl;
class HostChildURLLoaderFactoryBundle;
-class ServiceWorkerTimeoutTimer;
class WebWorkerFetchContext;
// ServiceWorkerContextClient is a "client" of a service worker execution
@@ -67,8 +64,7 @@ class WebWorkerFetchContext;
// noted (here or in base class documentation), all methods are called on the
// worker thread.
class CONTENT_EXPORT ServiceWorkerContextClient
- : public blink::WebServiceWorkerContextClient,
- public blink::mojom::ServiceWorker {
+ : public blink::WebServiceWorkerContextClient {
public:
// Called on the main thread.
// - |is_starting_installed_worker| is true if the script is already installed
@@ -117,6 +113,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient
scoped_refptr<base::SequencedTaskRunner> worker_task_runner) override;
void WillEvaluateScript() override;
void DidEvaluateScript(bool success) override;
+ void WillInitializeWorkerContext() override;
void DidInitializeWorkerContext(v8::Local<v8::Context> context) override;
void WillDestroyWorkerContext(v8::Local<v8::Context> context) override;
void WorkerContextDestroyed() override;
@@ -130,94 +127,16 @@ class CONTENT_EXPORT ServiceWorkerContextClient
const blink::WebString& message,
int line_number,
const blink::WebString& source_url) override;
- void DidHandleActivateEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void DidHandleBackgroundFetchAbortEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void DidHandleBackgroundFetchClickEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void DidHandleBackgroundFetchFailEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void DidHandleBackgroundFetchSuccessEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void DidHandleCookieChangeEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void DidHandleExtendableMessageEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void DidHandleInstallEvent(
- int event_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void RespondToFetchEventWithNoResponse(
- int fetch_event_id,
- base::TimeTicks event_dispatch_time,
- base::TimeTicks respond_with_settled_time) override;
- void RespondToFetchEvent(int fetch_event_id,
- const blink::WebServiceWorkerResponse& response,
- base::TimeTicks event_dispatch_time,
- base::TimeTicks respond_with_settled_time) override;
- void RespondToFetchEventWithResponseStream(
- int fetch_event_id,
- const blink::WebServiceWorkerResponse& response,
- blink::WebServiceWorkerStreamHandle* web_body_as_stream,
- base::TimeTicks event_dispatch_time,
- base::TimeTicks respond_with_settled_time) override;
- void DidHandleFetchEvent(
- int fetch_event_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void DidHandleNotificationClickEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void DidHandleNotificationCloseEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void DidHandlePushEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void DidHandleSyncEvent(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void RespondToAbortPaymentEvent(int event_id, bool payment_aborted) override;
- void DidHandleAbortPaymentEvent(
- int event_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void RespondToCanMakePaymentEvent(int event_id,
- bool can_make_payment) override;
- void DidHandleCanMakePaymentEvent(
- int event_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
- void RespondToPaymentRequestEvent(
- int payment_request_id,
- const blink::WebPaymentHandlerResponse& response) override;
- void DidHandlePaymentRequestEvent(
- int payment_request_id,
- blink::mojom::ServiceWorkerEventStatus status) override;
+ void SetupNavigationPreload(int fetch_event_id,
+ const blink::WebURL& url,
+ std::unique_ptr<blink::WebFetchEventPreloadHandle>
+ preload_handle) override;
+ void RequestTermination(RequestTerminationCallback callback) override;
std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
CreateServiceWorkerNetworkProviderOnMainThread() override;
scoped_refptr<blink::WebWorkerFetchContext>
CreateServiceWorkerFetchContextOnMainThread(
blink::WebServiceWorkerNetworkProvider*) override;
- int WillStartTask() override;
- void DidEndTask(int task_id) override;
-
- // Dispatches the fetch event if the worker is running normally, and queues it
- // instead if the worker has already requested to be terminated by the
- // browser. If queued, the event will be dispatched once the worker resumes
- // normal operation (if the browser decides not to terminate it, and instead
- // starts another event), or else is dropped if the worker is terminated.
- //
- // This method needs to be used only if the event comes directly from a
- // client, which means it is coming through the ControllerServiceWorkerImpl.
- void DispatchOrQueueFetchEvent(
- blink::mojom::DispatchFetchEventParamsPtr params,
- blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- DispatchFetchEventCallback callback);
/////////////////////////////////////////////////////////////////////////////
// The following are for use by NavigationPreloadRequest.
@@ -258,123 +177,13 @@ class CONTENT_EXPORT ServiceWorkerContextClient
DispatchOrQueueFetchEvent_NotRequestedTermination);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextClientTest, TaskInServiceWorker);
- using FetchHandlerExistence = blink::mojom::FetchHandlerExistence;
-
- static void ToWebServiceWorkerRequestForFetchEvent(
- blink::mojom::FetchAPIRequestPtr request,
- const std::string& client_id,
- blink::WebServiceWorkerRequest* web_request);
-
void SendWorkerStarted(blink::mojom::ServiceWorkerStartStatus status);
- // Implements blink::mojom::ServiceWorker.
- void InitializeGlobalScope(
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
- blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info,
- FetchHandlerExistence fetch_hander_existence) override;
- void DispatchInstallEvent(
- DispatchInstallEventCallback callback) override;
- void DispatchActivateEvent(DispatchActivateEventCallback callback) override;
- void DispatchBackgroundFetchAbortEvent(
- blink::mojom::BackgroundFetchRegistrationPtr registration,
- DispatchBackgroundFetchAbortEventCallback callback) override;
- void DispatchBackgroundFetchClickEvent(
- blink::mojom::BackgroundFetchRegistrationPtr registration,
- DispatchBackgroundFetchClickEventCallback callback) override;
- void DispatchBackgroundFetchFailEvent(
- blink::mojom::BackgroundFetchRegistrationPtr registration,
- DispatchBackgroundFetchFailEventCallback callback) override;
- void DispatchBackgroundFetchSuccessEvent(
- blink::mojom::BackgroundFetchRegistrationPtr registration,
- DispatchBackgroundFetchSuccessEventCallback callback) override;
- void DispatchExtendableMessageEvent(
- blink::mojom::ExtendableMessageEventPtr event,
- DispatchExtendableMessageEventCallback callback) override;
- void DispatchExtendableMessageEventWithCustomTimeout(
- blink::mojom::ExtendableMessageEventPtr event,
- base::TimeDelta timeout,
- DispatchExtendableMessageEventCallback callback) override;
- void DispatchFetchEvent(
- blink::mojom::DispatchFetchEventParamsPtr params,
- blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- DispatchFetchEventCallback callback) override;
- void DispatchNotificationClickEvent(
- const std::string& notification_id,
- const blink::PlatformNotificationData& notification_data,
- int action_index,
- const base::Optional<base::string16>& reply,
- DispatchNotificationClickEventCallback callback) override;
- void DispatchNotificationCloseEvent(
- const std::string& notification_id,
- const blink::PlatformNotificationData& notification_data,
- DispatchNotificationCloseEventCallback callback) override;
- void DispatchPushEvent(const base::Optional<std::string>& payload,
- DispatchPushEventCallback callback) override;
- void DispatchSyncEvent(const std::string& tag,
- bool last_chance,
- base::TimeDelta timeout,
- DispatchSyncEventCallback callback) override;
- void DispatchAbortPaymentEvent(
- payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- DispatchAbortPaymentEventCallback callback) override;
- void DispatchCanMakePaymentEvent(
- payments::mojom::CanMakePaymentEventDataPtr event_data,
- payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- DispatchCanMakePaymentEventCallback callback) override;
- void DispatchPaymentRequestEvent(
- payments::mojom::PaymentRequestEventDataPtr event_data,
- payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- DispatchPaymentRequestEventCallback callback) override;
- void DispatchCookieChangeEvent(
- const net::CanonicalCookie& cookie,
- ::network::mojom::CookieChangeCause cause,
- DispatchCookieChangeEventCallback callback) override;
- void Ping(PingCallback callback) override;
- void SetIdleTimerDelayToZero() override;
-
- void OnNotificationClickEvent(
- int request_id,
- const std::string& notification_id,
- const blink::PlatformNotificationData& notification_data,
- int action_index,
- const base::NullableString16& reply);
- void OnNotificationCloseEvent(
- int request_id,
- const std::string& notification_id,
- const blink::PlatformNotificationData& notification_data);
-
- void OnFocusClientResponse(
- int request_id,
- const blink::mojom::ServiceWorkerClientInfo& client);
- void OnNavigateClientResponse(
- int request_id,
- const blink::mojom::ServiceWorkerClientInfo& client);
- void OnNavigateClientError(int request_id, const GURL& url);
-
- void SetupNavigationPreload(
- int fetch_event_id,
- const GURL& url,
- blink::mojom::FetchEventPreloadHandlePtr preload_handle);
-
- // Called by ServiceWorkerTimeoutTimer when a certain time has passed since
- // the last task finished.
- void OnIdleTimeout();
-
- void OnRequestedTermination(bool will_be_terminated);
-
- // Returns true if the worker has requested to be terminated by the browser
- // process. It does this due to idle timeout.
- bool RequestedTermination() const;
-
// Stops the worker context. Called on the main thread.
void StopWorkerOnMainThread();
base::WeakPtr<ServiceWorkerContextClient> GetWeakPtr();
- void SetTimeoutTimerForTesting(
- std::unique_ptr<ServiceWorkerTimeoutTimer> timeout_timer);
- ServiceWorkerTimeoutTimer* GetTimeoutTimerForTesting();
-
const int64_t service_worker_version_id_;
const GURL service_worker_scope_;
const GURL script_url_;
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client_unittest.cc b/chromium/content/renderer/service_worker/service_worker_context_client_unittest.cc
deleted file mode 100644
index 848c68b692f..00000000000
--- a/chromium/content/renderer/service_worker/service_worker_context_client_unittest.cc
+++ /dev/null
@@ -1,667 +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/renderer/service_worker/service_worker_context_client.h"
-
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/test_mock_time_task_runner.h"
-#include "base/time/tick_clock.h"
-#include "base/time/time.h"
-#include "content/child/thread_safe_sender.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/common/content_client.h"
-#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/service_worker/embedded_worker_instance_client_impl.h"
-#include "content/renderer/service_worker/service_worker_timeout_timer.h"
-#include "content/renderer/service_worker/service_worker_type_util.h"
-#include "content/renderer/worker/worker_thread_registry.h"
-#include "mojo/public/cpp/bindings/associated_binding_set.h"
-#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
-#include "services/network/public/cpp/features.h"
-#include "services/network/public/cpp/resource_request.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/fetch/fetch_api_request_headers_map.h"
-#include "third_party/blink/public/common/messaging/message_port_channel.h"
-#include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom.h"
-#include "third_party/blink/public/mojom/service_worker/embedded_worker.mojom.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
-#include "third_party/blink/public/platform/modules/notifications/web_notification_data.h"
-#include "third_party/blink/public/platform/modules/payments/web_payment_request_event_data.h"
-#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_clients_info.h"
-#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h"
-#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration_object_info.h"
-#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/web_data_consumer_handle.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_url_response.h"
-#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h"
-#include "third_party/blink/public/web/web_embedded_worker.h"
-
-namespace content {
-
-namespace {
-
-// Pipes connected to the context client.
-struct ContextClientPipes {
- // From the browser to EmbeddedWorkerInstanceClientImpl.
- blink::mojom::EmbeddedWorkerInstanceClientPtr embedded_worker_instance_client;
-
- // From the browser to ServiceWorkerContextClient.
- blink::mojom::ServiceWorkerPtr service_worker;
- blink::mojom::ControllerServiceWorkerPtr controller;
- blink::mojom::ServiceWorkerRegistrationObjectAssociatedPtr registration;
-
- // From ServiceWorkerContextClient to the browser.
- blink::mojom::ServiceWorkerHostAssociatedRequest service_worker_host_request;
- blink::mojom::EmbeddedWorkerInstanceHostAssociatedRequest
- embedded_worker_host_request;
- blink::mojom::ServiceWorkerRegistrationObjectHostAssociatedRequest
- registration_host_request;
-};
-
-// A fake WebEmbeddedWorker. This is needed to ensure WorkerContextDestroyed()
-// is called on EmbeddedWorkerInstanceClientImpl so it can self-destruct.
-class FakeWebEmbeddedWorker : public blink::WebEmbeddedWorker {
- public:
- explicit FakeWebEmbeddedWorker(ServiceWorkerContextClient* context_client)
- : context_client_(context_client) {}
-
- void StartWorkerContext(const blink::WebEmbeddedWorkerStartData&) override {}
- void TerminateWorkerContext() override {
- v8::Local<v8::Context> local;
- context_client_->WillDestroyWorkerContext(local);
- context_client_->WorkerContextDestroyed();
- }
- void ResumeAfterDownload() override {}
- void AddMessageToConsole(const blink::WebConsoleMessage&) override {}
- void BindDevToolsAgent(mojo::ScopedInterfaceEndpointHandle,
- mojo::ScopedInterfaceEndpointHandle) override {}
-
- private:
- ServiceWorkerContextClient* context_client_;
-};
-
-class MockWebServiceWorkerContextProxy
- : public blink::WebServiceWorkerContextProxy {
- public:
- ~MockWebServiceWorkerContextProxy() override = default;
-
- void BindServiceWorkerHost(
- mojo::ScopedInterfaceEndpointHandle service_worker_host) override {}
- void SetRegistration(
- blink::WebServiceWorkerRegistrationObjectInfo info) override {
- DCHECK(!registration_object_info_);
- registration_object_info_ =
- std::make_unique<blink::WebServiceWorkerRegistrationObjectInfo>(
- std::move(info));
- }
- void SetFetchHandlerExistence(
- FetchHandlerExistence fetch_handler_existence) override {
- fetch_handler_existence_ = fetch_handler_existence;
- }
- void ReadyToEvaluateScript() override {}
- bool HasFetchEventHandler() override { return false; }
- void DispatchFetchEvent(int fetch_event_id,
- const blink::WebServiceWorkerRequest& web_request,
- bool navigation_preload_sent) override {
- fetch_events_.emplace_back(fetch_event_id, web_request);
- }
-
- void DispatchActivateEvent(int event_id) override { NOTREACHED(); }
- void DispatchBackgroundFetchAbortEvent(
- int event_id,
- blink::WebBackgroundFetchRegistration registration) override {
- NOTREACHED();
- }
- void DispatchBackgroundFetchClickEvent(
- int event_id,
- blink::WebBackgroundFetchRegistration registration) override {
- NOTREACHED();
- }
- void DispatchBackgroundFetchFailEvent(
- int event_id,
- blink::WebBackgroundFetchRegistration registration) override {
- NOTREACHED();
- }
- void DispatchBackgroundFetchSuccessEvent(
- int event_id,
- blink::WebBackgroundFetchRegistration registration) override {
- NOTREACHED();
- }
- void DispatchCookieChangeEvent(
- int event_id,
- const blink::WebCanonicalCookie& cookie,
- ::network::mojom::CookieChangeCause change_cause) override {
- NOTREACHED();
- }
- void DispatchExtendableMessageEvent(
- int event_id,
- blink::TransferableMessage message,
- const blink::WebSecurityOrigin& source_origin,
- const blink::WebServiceWorkerClientInfo&) override {
- NOTREACHED();
- }
- void DispatchExtendableMessageEvent(
- int event_id,
- blink::TransferableMessage message,
- const blink::WebSecurityOrigin& source_origin,
- blink::WebServiceWorkerObjectInfo) override {
- NOTREACHED();
- }
- void DispatchInstallEvent(int event_id) override { NOTREACHED(); }
- void DispatchNotificationClickEvent(int event_id,
- const blink::WebString& notification_id,
- const blink::WebNotificationData&,
- int action_index,
- const blink::WebString& reply) override {
- NOTREACHED();
- }
- void DispatchNotificationCloseEvent(
- int event_id,
- const blink::WebString& notification_id,
- const blink::WebNotificationData&) override {
- NOTREACHED();
- }
- void DispatchPushEvent(int event_id, const blink::WebString& data) override {
- NOTREACHED();
- }
- void DispatchSyncEvent(int sync_event_id,
- const blink::WebString& tag,
- bool last_chance) override {
- NOTREACHED();
- }
- void DispatchAbortPaymentEvent(int event_id) override { NOTREACHED(); }
- void DispatchCanMakePaymentEvent(
- int event_id,
- const blink::WebCanMakePaymentEventData&) override {
- NOTREACHED();
- }
- void DispatchPaymentRequestEvent(
- int event_id,
- const blink::WebPaymentRequestEventData&) override {
- NOTREACHED();
- }
- void OnNavigationPreloadResponse(
- int fetch_event_id,
- std::unique_ptr<blink::WebURLResponse>,
- mojo::ScopedDataPipeConsumerHandle) override {
- NOTREACHED();
- }
- void OnNavigationPreloadError(
- int fetch_event_id,
- std::unique_ptr<blink::WebServiceWorkerError>) override {
- NOTREACHED();
- }
- void OnNavigationPreloadComplete(int fetch_event_id,
- base::TimeTicks completion_time,
- int64_t encoded_data_length,
- int64_t encoded_body_length,
- int64_t decoded_body_length) override {
- NOTREACHED();
- }
-
- const std::vector<
- std::pair<int /* event_id */, blink::WebServiceWorkerRequest>>&
- fetch_events() const {
- return fetch_events_;
- }
-
- FetchHandlerExistence fetch_handler_existence() const {
- return fetch_handler_existence_;
- }
-
- private:
- std::unique_ptr<blink::WebServiceWorkerRegistrationObjectInfo>
- registration_object_info_;
- std::vector<std::pair<int /* event_id */, blink::WebServiceWorkerRequest>>
- fetch_events_;
- FetchHandlerExistence fetch_handler_existence_ =
- FetchHandlerExistence::UNKNOWN;
-};
-
-base::RepeatingClosure CreateCallbackWithCalledFlag(bool* out_is_called) {
- return base::BindRepeating([](bool* out_is_called) { *out_is_called = true; },
- out_is_called);
-}
-
-class MockServiceWorkerObjectHost
- : public blink::mojom::ServiceWorkerObjectHost {
- public:
- explicit MockServiceWorkerObjectHost(int64_t version_id)
- : version_id_(version_id) {}
- ~MockServiceWorkerObjectHost() override = default;
-
- blink::mojom::ServiceWorkerObjectInfoPtr CreateObjectInfo() {
- auto info = blink::mojom::ServiceWorkerObjectInfo::New();
- info->version_id = version_id_;
- bindings_.AddBinding(this, mojo::MakeRequest(&info->host_ptr_info));
- info->request = mojo::MakeRequest(&remote_object_);
- return info;
- }
-
- int GetBindingCount() const { return bindings_.size(); }
-
- private:
- // Implements blink::mojom::ServiceWorkerObjectHost.
- void PostMessageToServiceWorker(
- ::blink::TransferableMessage message) override {
- NOTREACHED();
- }
- void TerminateForTesting(TerminateForTestingCallback callback) override {
- NOTREACHED();
- }
-
- const int64_t version_id_;
- mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerObjectHost> bindings_;
- blink::mojom::ServiceWorkerObjectAssociatedPtr remote_object_;
-};
-
-} // namespace
-
-class ServiceWorkerContextClientTest : public testing::Test {
- public:
- ServiceWorkerContextClientTest() = default;
-
- protected:
- using FetchHandlerExistence = blink::mojom::FetchHandlerExistence;
-
- void SetUp() override {
- task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
- message_loop_.SetTaskRunner(task_runner_);
- // Use this thread as the worker thread.
- WorkerThreadRegistry::Instance()->DidStartCurrentWorkerThread();
- old_client_ = SetRendererClientForTesting(&renderer_client_);
- }
-
- void TearDown() override {
- // Unregister this thread from worker threads.
- WorkerThreadRegistry::Instance()->WillStopCurrentWorkerThread();
- task_runner_->RunUntilIdle();
- SetRendererClientForTesting(old_client_);
- }
-
- void EnableServicification() {
- feature_list_.InitAndEnableFeature(network::features::kNetworkService);
- }
-
- // Creates an ContextClient, whose pipes are connected to |out_pipes|, then
- // simulates that the service worker thread has started with |proxy|.
- //
- // The client's lifetime is tied to
- // |out_pipes->embedded_worker_instance_client|.
- ServiceWorkerContextClient* CreateContextClient(
- ContextClientPipes* out_pipes,
- blink::WebServiceWorkerContextProxy* proxy,
- FetchHandlerExistence fetch_handler_existence =
- FetchHandlerExistence::DOES_NOT_EXIST) {
- EmbeddedWorkerInstanceClientImpl* embedded_worker_instance_client =
- new EmbeddedWorkerInstanceClientImpl(
- mojo::MakeRequest(&out_pipes->embedded_worker_instance_client));
-
- auto service_worker_request = mojo::MakeRequest(&out_pipes->service_worker);
- auto controller_request = mojo::MakeRequest(&out_pipes->controller);
- blink::mojom::EmbeddedWorkerInstanceHostAssociatedPtr
- embedded_worker_host_ptr;
- out_pipes->embedded_worker_host_request =
- mojo::MakeRequestAssociatedWithDedicatedPipe(&embedded_worker_host_ptr);
- const GURL kScope("https://example.com");
- const GURL kScript("https://example.com/SW.js");
- auto context_client = std::make_unique<ServiceWorkerContextClient>(
- 1 /* service_worker_version_id */, kScope, kScript,
- false /* is_script_streaming */,
- blink::mojom::RendererPreferences::New(),
- std::move(service_worker_request), std::move(controller_request),
- embedded_worker_host_ptr.PassInterface(),
- blink::mojom::ServiceWorkerProviderInfoForStartWorker::New(),
- embedded_worker_instance_client,
- blink::mojom::EmbeddedWorkerStartTiming::New(),
- nullptr /* preference_watcher_request */,
- nullptr /* subresource_loaders */,
- blink::scheduler::GetSingleThreadTaskRunnerForTesting());
-
- auto* context_client_raw = context_client.get();
-
- embedded_worker_instance_client->service_worker_context_client_ =
- std::move(context_client);
- context_client_raw->StartWorkerContext(
- std::make_unique<FakeWebEmbeddedWorker>(context_client_raw),
- blink::WebEmbeddedWorkerStartData());
-
- // TODO(falken): We should mock a worker thread task runner instead of
- // using GetSingleThreadTaskRunnerForTesting() again, since that's the
- // runner we used to mock the main thread when constructing the context
- // client above.
- context_client_raw->WorkerContextStarted(
- proxy, blink::scheduler::GetSingleThreadTaskRunnerForTesting());
-
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host;
- out_pipes->service_worker_host_request =
- mojo::MakeRequest(&service_worker_host);
- auto registration_info =
- blink::mojom::ServiceWorkerRegistrationObjectInfo::New();
- registration_info->registration_id = 100; // dummy
- registration_info->scope = kScope;
- registration_info->update_via_cache =
- blink::mojom::ServiceWorkerUpdateViaCache::kAll;
- out_pipes->registration_host_request =
- mojo::MakeRequest(&registration_info->host_ptr_info);
- registration_info->request = mojo::MakeRequest(&out_pipes->registration);
- out_pipes->service_worker->InitializeGlobalScope(
- std::move(service_worker_host), std::move(registration_info),
- fetch_handler_existence);
- task_runner()->RunUntilIdle();
- return context_client_raw;
- }
-
- ServiceWorkerContextClient* CreateIdleContextClient(
- ContextClientPipes* pipes,
- MockWebServiceWorkerContextProxy* mock_proxy) {
- ServiceWorkerContextClient* context_client =
- CreateContextClient(pipes, mock_proxy);
- context_client->DidEvaluateScript(true /* success */);
- task_runner()->RunUntilIdle();
- EXPECT_TRUE(mock_proxy->fetch_events().empty());
- is_idle_ = false;
- auto timer = std::make_unique<ServiceWorkerTimeoutTimer>(
- CreateCallbackWithCalledFlag(&is_idle_),
- task_runner()->GetMockTickClock());
- timer->Start();
- context_client->SetTimeoutTimerForTesting(std::move(timer));
-
- // Ensure the idle state.
- EXPECT_FALSE(context_client->RequestedTermination());
- task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kIdleDelay +
- ServiceWorkerTimeoutTimer::kUpdateInterval +
- base::TimeDelta::FromSeconds(1));
- EXPECT_TRUE(context_client->RequestedTermination());
-
- return context_client;
- }
-
- ServiceWorkerTimeoutTimer* GetTimeoutTimer(
- ServiceWorkerContextClient* context_client) {
- return context_client->GetTimeoutTimerForTesting();
- }
-
- scoped_refptr<base::TestMockTimeTaskRunner> task_runner() const {
- return task_runner_;
- }
-
- private:
- base::MessageLoop message_loop_;
- scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
- base::test::ScopedFeatureList feature_list_;
- bool is_idle_;
- ContentRendererClient renderer_client_;
- ContentRendererClient* old_client_;
-};
-
-TEST_F(ServiceWorkerContextClientTest, Ping) {
- ContextClientPipes pipes;
- MockWebServiceWorkerContextProxy mock_proxy;
- CreateContextClient(&pipes, &mock_proxy);
-
- bool is_called = false;
- pipes.service_worker->Ping(CreateCallbackWithCalledFlag(&is_called));
- task_runner()->RunUntilIdle();
- EXPECT_TRUE(is_called);
-}
-
-TEST_F(ServiceWorkerContextClientTest, DispatchFetchEvent) {
- ContextClientPipes pipes;
- MockWebServiceWorkerContextProxy mock_proxy;
- ServiceWorkerContextClient* context_client =
- CreateContextClient(&pipes, &mock_proxy);
- context_client->DidEvaluateScript(true /* success */);
- task_runner()->RunUntilIdle();
- EXPECT_TRUE(mock_proxy.fetch_events().empty());
-
- const GURL expected_url("https://example.com/expected");
- auto request = blink::mojom::FetchAPIRequest::New();
- request->url = expected_url;
- blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
- blink::mojom::ServiceWorkerFetchResponseCallbackRequest
- fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
- auto params = blink::mojom::DispatchFetchEventParams::New();
- params->request = std::move(request);
- pipes.service_worker->DispatchFetchEvent(
- std::move(params), std::move(fetch_callback_ptr),
- base::BindOnce([](blink::mojom::ServiceWorkerEventStatus) {}));
- task_runner()->RunUntilIdle();
-
- ASSERT_EQ(1u, mock_proxy.fetch_events().size());
- EXPECT_EQ(expected_url,
- static_cast<GURL>(mock_proxy.fetch_events()[0].second.Url()));
-}
-
-class HeaderContentRendererClient : public ContentRendererClient {
- bool IsExcludedHeaderForServiceWorkerFetchEvent(
- const std::string& header_name) override {
- return header_name == "x-bye-bye";
- }
-};
-
-TEST_F(ServiceWorkerContextClientTest, DispatchFetchEvent_Headers) {
- HeaderContentRendererClient header_client;
- auto* old_client = SetRendererClientForTesting(&header_client);
-
- ContextClientPipes pipes;
- MockWebServiceWorkerContextProxy mock_proxy;
- ServiceWorkerContextClient* context_client =
- CreateContextClient(&pipes, &mock_proxy);
- context_client->DidEvaluateScript(true /* success */);
- task_runner()->RunUntilIdle();
- EXPECT_TRUE(mock_proxy.fetch_events().empty());
-
- const GURL expected_url("https://example.com/expected");
- auto request = blink::mojom::FetchAPIRequest::New();
- request->url = expected_url;
- request->headers.emplace("x-bye-bye", "excluded");
- request->headers.emplace("x-hi-hi", "present");
- blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
- blink::mojom::ServiceWorkerFetchResponseCallbackRequest
- fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
- auto params = blink::mojom::DispatchFetchEventParams::New();
- params->request = std::move(request);
- pipes.service_worker->DispatchFetchEvent(
- std::move(params), std::move(fetch_callback_ptr),
- base::BindOnce([](blink::mojom::ServiceWorkerEventStatus) {}));
- task_runner()->RunUntilIdle();
-
- ASSERT_EQ(1u, mock_proxy.fetch_events().size());
- const blink::WebServiceWorkerRequest& received_request =
- mock_proxy.fetch_events()[0].second;
- blink::FetchAPIRequestHeadersMap header_map;
- GetServiceWorkerHeaderMapFromWebRequest(received_request, &header_map);
-
- EXPECT_EQ(expected_url, static_cast<GURL>(received_request.Url()));
- EXPECT_TRUE(header_map.find(std::string("x-bye-bye")) == header_map.end());
- auto iter = header_map.find(std::string("x-hi-hi"));
- ASSERT_TRUE(iter != header_map.end());
- EXPECT_EQ("present", iter->second);
-
- SetRendererClientForTesting(old_client);
-}
-
-TEST_F(ServiceWorkerContextClientTest,
- DispatchOrQueueFetchEvent_NotRequestedTermination) {
- EnableServicification();
- ContextClientPipes pipes;
- MockWebServiceWorkerContextProxy mock_proxy;
- ServiceWorkerContextClient* context_client =
- CreateContextClient(&pipes, &mock_proxy);
- context_client->DidEvaluateScript(true /* success */);
- task_runner()->RunUntilIdle();
- EXPECT_TRUE(mock_proxy.fetch_events().empty());
-
- bool is_idle = false;
- auto timer = std::make_unique<ServiceWorkerTimeoutTimer>(
- CreateCallbackWithCalledFlag(&is_idle),
- task_runner()->GetMockTickClock());
- timer->Start();
- context_client->SetTimeoutTimerForTesting(std::move(timer));
-
- // The dispatched fetch event should be recorded by |mock_proxy|.
- const GURL expected_url("https://example.com/expected");
- blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
- blink::mojom::ServiceWorkerFetchResponseCallbackRequest
- fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
- auto request = blink::mojom::FetchAPIRequest::New();
- request->url = expected_url;
- auto params = blink::mojom::DispatchFetchEventParams::New();
- params->request = std::move(request);
- context_client->DispatchOrQueueFetchEvent(
- std::move(params), std::move(fetch_callback_ptr),
- base::BindOnce([](blink::mojom::ServiceWorkerEventStatus) {}));
- task_runner()->RunUntilIdle();
-
- EXPECT_FALSE(context_client->RequestedTermination());
- ASSERT_EQ(1u, mock_proxy.fetch_events().size());
- EXPECT_EQ(expected_url,
- static_cast<GURL>(mock_proxy.fetch_events()[0].second.Url()));
-}
-
-TEST_F(ServiceWorkerContextClientTest,
- DispatchOrQueueFetchEvent_RequestedTerminationAndDie) {
- EnableServicification();
- ContextClientPipes pipes;
- MockWebServiceWorkerContextProxy mock_proxy;
- CreateIdleContextClient(&pipes, &mock_proxy);
-
- const GURL expected_url("https://example.com/expected");
-
- // FetchEvent dispatched directly from the controlled clients through
- // blink::mojom::ControllerServiceWorker should be queued in the idle state.
- {
- blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
- blink::mojom::ServiceWorkerFetchResponseCallbackRequest
- fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
- auto request = blink::mojom::FetchAPIRequest::New();
- request->url = expected_url;
- auto params = blink::mojom::DispatchFetchEventParams::New();
- params->request = std::move(request);
- pipes.controller->DispatchFetchEvent(
- std::move(params), std::move(fetch_callback_ptr),
- base::BindOnce([](blink::mojom::ServiceWorkerEventStatus) {}));
- task_runner()->RunUntilIdle();
- }
- EXPECT_TRUE(mock_proxy.fetch_events().empty());
-
- // Destruction of |context_client| should not hit any DCHECKs.
- pipes.embedded_worker_instance_client.reset();
- task_runner()->RunUntilIdle();
-}
-
-TEST_F(ServiceWorkerContextClientTest,
- DispatchOrQueueFetchEvent_RequestedTerminationAndWakeUp) {
- EnableServicification();
- ContextClientPipes pipes;
- MockWebServiceWorkerContextProxy mock_proxy;
- ServiceWorkerContextClient* context_client =
- CreateIdleContextClient(&pipes, &mock_proxy);
-
- const GURL expected_url_1("https://example.com/expected_1");
- const GURL expected_url_2("https://example.com/expected_2");
- blink::mojom::ServiceWorkerFetchResponseCallbackRequest
- fetch_callback_request_1;
- blink::mojom::ServiceWorkerFetchResponseCallbackRequest
- fetch_callback_request_2;
-
- // FetchEvent dispatched directly from the controlled clients through
- // blink::mojom::ControllerServiceWorker should be queued in the idle state.
- {
- blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
- fetch_callback_request_1 = mojo::MakeRequest(&fetch_callback_ptr);
- auto request = blink::mojom::FetchAPIRequest::New();
- request->url = expected_url_1;
- auto params = blink::mojom::DispatchFetchEventParams::New();
- params->request = std::move(request);
- pipes.controller->DispatchFetchEvent(
- std::move(params), std::move(fetch_callback_ptr),
- base::BindOnce([](blink::mojom::ServiceWorkerEventStatus) {}));
- task_runner()->RunUntilIdle();
- }
- EXPECT_TRUE(mock_proxy.fetch_events().empty());
-
- // Another event dispatched to blink::mojom::ServiceWorker wakes up
- // the context client.
- {
- blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
- fetch_callback_request_2 = mojo::MakeRequest(&fetch_callback_ptr);
- auto request = blink::mojom::FetchAPIRequest::New();
- request->url = expected_url_2;
- auto params = blink::mojom::DispatchFetchEventParams::New();
- params->request = std::move(request);
- pipes.service_worker->DispatchFetchEvent(
- std::move(params), std::move(fetch_callback_ptr),
- base::BindOnce([](blink::mojom::ServiceWorkerEventStatus) {}));
- task_runner()->RunUntilIdle();
- }
- EXPECT_FALSE(context_client->RequestedTermination());
-
- // All events should fire. The order of events should be kept.
- ASSERT_EQ(2u, mock_proxy.fetch_events().size());
- EXPECT_EQ(expected_url_1,
- static_cast<GURL>(mock_proxy.fetch_events()[0].second.Url()));
- EXPECT_EQ(expected_url_2,
- static_cast<GURL>(mock_proxy.fetch_events()[1].second.Url()));
-}
-
-TEST_F(ServiceWorkerContextClientTest, TaskInServiceWorker) {
- EnableServicification();
- ContextClientPipes pipes;
- MockWebServiceWorkerContextProxy mock_proxy;
- ServiceWorkerContextClient* context_client =
- CreateIdleContextClient(&pipes, &mock_proxy);
-
- int task_id = context_client->WillStartTask();
- EXPECT_FALSE(context_client->RequestedTermination());
- context_client->DidEndTask(task_id);
- EXPECT_FALSE(context_client->RequestedTermination());
-
- // Ensure the idle state.
- task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kIdleDelay +
- ServiceWorkerTimeoutTimer::kUpdateInterval +
- base::TimeDelta::FromSeconds(1));
- EXPECT_TRUE(context_client->RequestedTermination());
-}
-
-// Tests timing out a task created by WillStartTask().
-TEST_F(ServiceWorkerContextClientTest, AbortedTaskInServiceWorker) {
- EnableServicification();
- ContextClientPipes pipes;
- MockWebServiceWorkerContextProxy mock_proxy;
- ServiceWorkerContextClient* context_client =
- CreateIdleContextClient(&pipes, &mock_proxy);
-
- // Make a task that times out.
- int task_id = context_client->WillStartTask();
- task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kEventTimeout +
- ServiceWorkerTimeoutTimer::kUpdateInterval +
- base::TimeDelta::FromSeconds(1));
-
- // The event should have been aborted.
- ServiceWorkerTimeoutTimer* timeout_timer = GetTimeoutTimer(context_client);
- EXPECT_FALSE(timeout_timer->HasEvent(task_id));
-
- // Calling DidEndTask() shouldn't crash.
- context_client->DidEndTask(task_id);
-}
-
-TEST_F(ServiceWorkerContextClientTest, InstalledFetchEventHandler) {
- ContextClientPipes pipes;
- MockWebServiceWorkerContextProxy mock_proxy;
- CreateContextClient(&pipes, &mock_proxy, FetchHandlerExistence::EXISTS);
- EXPECT_EQ(FetchHandlerExistence::EXISTS,
- mock_proxy.fetch_handler_existence());
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc
index 56ff478199f..880bec633e0 100644
--- a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc
+++ b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -128,8 +128,6 @@ blink::WebURL ServiceWorkerFetchContextImpl::SiteForCookies() const {
base::Optional<blink::WebSecurityOrigin>
ServiceWorkerFetchContextImpl::TopFrameOrigin() const {
- // TODO(jkarlin): Determine what the top-frame-origin of a service worker is.
- // See https://crbug.com/918868.
return base::nullopt;
}
diff --git a/chromium/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc b/chromium/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc
index 6fc87a05d8c..d3b4dfc0314 100644
--- a/chromium/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc
+++ b/chromium/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc
@@ -22,8 +22,7 @@ namespace content {
ServiceWorkerNetworkProviderForServiceWorker::
ServiceWorkerNetworkProviderForServiceWorker(
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_info)
+ network::mojom::URLLoaderFactoryPtrInfo script_loader_factory_info)
: script_loader_factory_(std::move(script_loader_factory_info)) {}
ServiceWorkerNetworkProviderForServiceWorker::
diff --git a/chromium/content/renderer/service_worker/service_worker_network_provider_for_service_worker.h b/chromium/content/renderer/service_worker/service_worker_network_provider_for_service_worker.h
index 9f54c3eabbb..ed156c3c0cd 100644
--- a/chromium/content/renderer/service_worker/service_worker_network_provider_for_service_worker.h
+++ b/chromium/content/renderer/service_worker/service_worker_network_provider_for_service_worker.h
@@ -22,8 +22,7 @@ class ServiceWorkerNetworkProviderForServiceWorker final
: public blink::WebServiceWorkerNetworkProvider {
public:
explicit ServiceWorkerNetworkProviderForServiceWorker(
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_info);
+ network::mojom::URLLoaderFactoryPtrInfo script_loader_factory_info);
~ServiceWorkerNetworkProviderForServiceWorker() override;
// blink::WebServiceWorkerNetworkProvider:
@@ -43,7 +42,7 @@ class ServiceWorkerNetworkProviderForServiceWorker final
private:
// The URL loader factory for loading the service worker's scripts.
- network::mojom::URLLoaderFactoryAssociatedPtr script_loader_factory_;
+ network::mojom::URLLoaderFactoryPtr script_loader_factory_;
};
} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_provider_context.cc b/chromium/content/renderer/service_worker/service_worker_provider_context.cc
index 866096a77e7..b5d3875067b 100644
--- a/chromium/content/renderer/service_worker/service_worker_provider_context.cc
+++ b/chromium/content/renderer/service_worker/service_worker_provider_context.cc
@@ -277,8 +277,12 @@ void ServiceWorkerProviderContext::SetController(
state->client_id == controller_info->client_id);
state->client_id = controller_info->client_id;
- if (controller_info->fetch_request_window_id)
+ if (controller_info->fetch_request_window_id) {
+ DCHECK(state->controller);
state->fetch_request_window_id = *controller_info->fetch_request_window_id;
+ } else {
+ state->fetch_request_window_id = base::UnguessableToken();
+ }
DCHECK((controller_info->mode ==
blink::mojom::ControllerServiceWorkerMode::kNoController &&
diff --git a/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc b/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc
index 4d850381832..87de8668dfa 100644
--- a/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc
+++ b/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -35,7 +35,6 @@
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom.h"
#include "third_party/blink/public/platform/interface_provider.h"
-#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
#include "third_party/blink/public/platform/web_http_body.h"
#include "third_party/blink/public/platform/web_string.h"
#include "ui/base/page_transition_types.h"
@@ -97,9 +96,9 @@ class HeaderRewritingURLLoaderClient : public network::mojom::URLLoaderClient {
std::move(ack_callback));
}
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override {
DCHECK(url_loader_client_.is_bound());
- url_loader_client_->OnReceiveCachedMetadata(data);
+ url_loader_client_->OnReceiveCachedMetadata(std::move(data));
}
void OnTransferSizeUpdated(int32_t transfer_size_diff) override {
@@ -382,15 +381,17 @@ void ServiceWorkerSubresourceLoader::OnFallback(
// preflight logic is implemented in Blink. So we return a "fallback required"
// response to Blink.
// TODO(falken): Remove this mechanism after OOB-CORS ships.
- if ((resource_request_.fetch_request_mode ==
- network::mojom::FetchRequestMode::kCors ||
- resource_request_.fetch_request_mode ==
- network::mojom::FetchRequestMode::kCorsWithForcedPreflight) &&
- (!resource_request_.request_initiator.has_value() ||
- !resource_request_.request_initiator->IsSameOriginWith(
- url::Origin::Create(resource_request_.url)))) {
+ if (!network::features::ShouldEnableOutOfBlinkCors() &&
+ ((resource_request_.fetch_request_mode ==
+ network::mojom::FetchRequestMode::kCors ||
+ resource_request_.fetch_request_mode ==
+ network::mojom::FetchRequestMode::kCorsWithForcedPreflight) &&
+ (!resource_request_.request_initiator.has_value() ||
+ !resource_request_.request_initiator->IsSameOriginWith(
+ url::Origin::Create(resource_request_.url))))) {
TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker", "ServiceWorkerSubresourceLoader::OnFallback",
+ "ServiceWorker",
+ "ServiceWorkerSubresourceLoader::OnFallback - CORS workaround",
TRACE_ID_WITH_SCOPE(kServiceWorkerSubresourceLoaderScope,
TRACE_ID_LOCAL(request_id_)),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
@@ -512,9 +513,20 @@ void ServiceWorkerSubresourceLoader::StartResponse(
}
}
- body_as_blob_->ReadSideData(base::BindOnce(
- &ServiceWorkerSubresourceLoader::OnBlobSideDataReadingComplete,
- weak_factory_.GetWeakPtr(), std::move(data_pipe)));
+ // Read side data if necessary.
+ auto resource_type =
+ static_cast<content::ResourceType>(resource_request_.resource_type);
+ if (resource_type == content::ResourceType::kScript) {
+ body_as_blob_->ReadSideData(base::BindOnce(
+ &ServiceWorkerSubresourceLoader::OnBlobSideDataReadingComplete,
+ weak_factory_.GetWeakPtr(), std::move(data_pipe)));
+ } else {
+ // Bypass reading side data when the request isn't for script. Currently
+ // side data only exists for scripts (as cached metadata).
+ OnBlobSideDataReadingComplete(std::move(data_pipe),
+ base::Optional<mojo_base::BigBuffer>());
+ }
+
return;
}
@@ -717,7 +729,7 @@ int ServiceWorkerSubresourceLoader::StartBlobReading(
void ServiceWorkerSubresourceLoader::OnBlobSideDataReadingComplete(
mojo::ScopedDataPipeConsumerHandle data_pipe,
- const base::Optional<std::vector<uint8_t>>& metadata) {
+ base::Optional<mojo_base::BigBuffer> metadata) {
TRACE_EVENT_WITH_FLOW1(
"ServiceWorker",
"ServiceWorkerSubresourceLoader::OnBlobSideDataReadingComplete",
@@ -731,7 +743,7 @@ void ServiceWorkerSubresourceLoader::OnBlobSideDataReadingComplete(
side_data_reading_complete_ = true;
if (metadata.has_value())
- url_loader_client_->OnReceiveCachedMetadata(metadata.value());
+ url_loader_client_->OnReceiveCachedMetadata(std::move(metadata.value()));
// If parallel reading is disabled then we need to start reading the blob.
if (!data_pipe.is_valid()) {
diff --git a/chromium/content/renderer/service_worker/service_worker_subresource_loader.h b/chromium/content/renderer/service_worker/service_worker_subresource_loader.h
index 9ada5a1261e..08f3daa64ca 100644
--- a/chromium/content/renderer/service_worker/service_worker_subresource_loader.h
+++ b/chromium/content/renderer/service_worker/service_worker_subresource_loader.h
@@ -117,7 +117,7 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader
int StartBlobReading(mojo::ScopedDataPipeConsumerHandle* body_pipe);
void OnBlobSideDataReadingComplete(
mojo::ScopedDataPipeConsumerHandle data_pipe,
- const base::Optional<std::vector<uint8_t>>& metadata);
+ base::Optional<mojo_base::BigBuffer> metadata);
void OnBlobReadingComplete(int net_error);
// Calls url_loader_client_->OnReceiveResponse() with |response_head_|.
diff --git a/chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc b/chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
index 9b2a016d43b..a83e1b050b3 100644
--- a/chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
+++ b/chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
@@ -20,14 +20,13 @@
#include "content/public/common/resource_type.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/renderer/service_worker/controller_service_worker_connector.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "content/test/fake_network_url_loader_factory.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/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/features.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_data_pipe_getter.h"
#include "services/network/test/test_url_loader_client.h"
@@ -77,52 +76,6 @@ class FakeBlob final : public blink::mojom::Blob {
std::string body_;
};
-// A simple URLLoaderFactory that responds with status 200 to every request.
-// This is the default network loader factory for
-// ServiceWorkerSubresourceLoaderTest.
-class FakeNetworkURLLoaderFactory final
- : public network::mojom::URLLoaderFactory {
- public:
- FakeNetworkURLLoaderFactory() = 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 factory) override {
- NOTREACHED();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FakeNetworkURLLoaderFactory);
-};
-
class FakeControllerServiceWorker
: public blink::mojom::ControllerServiceWorker {
public:
@@ -231,8 +184,8 @@ class FakeControllerServiceWorker
base::RunLoop run_loop;
ptr->Read(
std::move(data_pipe.producer_handle),
- base::BindOnce([](const base::Closure& quit_closure, int32_t status,
- uint64_t size) { quit_closure.Run(); },
+ base::BindOnce([](base::OnceClosure quit_closure, int32_t status,
+ uint64_t size) { std::move(quit_closure).Run(); },
run_loop.QuitClosure()));
run_loop.Run();
// Copy the content to |out_string|.
@@ -463,8 +416,8 @@ std::unique_ptr<network::ResourceResponseHead>
CreateResponseInfoFromServiceWorker() {
auto head = std::make_unique<network::ResourceResponseHead>();
std::string headers = "HTTP/1.1 200 OK\n\n";
- head->headers = new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length()));
+ head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(headers));
head->was_fetched_via_service_worker = true;
head->was_fallback_required_by_service_worker = false;
head->url_list_via_service_worker = std::vector<GURL>();
@@ -603,6 +556,7 @@ class ServiceWorkerSubresourceLoaderTest : public ::testing::Test {
CreateSubresourceLoaderFactory();
network::ResourceRequest request =
CreateRequest(GURL("https://www.example.com/big-file"));
+ request.resource_type = static_cast<int>(content::ResourceType::kMedia);
request.headers.SetHeader("Range", range_header);
network::mojom::URLLoaderPtr loader;
std::unique_ptr<network::TestURLLoaderClient> client;
@@ -1011,7 +965,7 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponse) {
base::HistogramTester histogram_tester;
// Construct the Blob to respond with.
- const std::string kResponseBody = "Here is sample text for the Blob.";
+ const std::string kResponseBody = "/* Here is sample text for the Blob. */";
const std::vector<uint8_t> kMetadata = {0xE3, 0x81, 0x8F, 0xE3, 0x82,
0x8D, 0xE3, 0x81, 0xBF, 0xE3,
0x81, 0x86, 0xE3, 0x82, 0x80};
@@ -1024,7 +978,8 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponse) {
// Perform the request.
network::ResourceRequest request =
- CreateRequest(GURL("https://www.example.com/foo.png"));
+ CreateRequest(GURL("https://www.example.com/foo.js"));
+ request.resource_type = static_cast<int>(content::ResourceType::kScript);
network::mojom::URLLoaderPtr loader;
std::unique_ptr<network::TestURLLoaderClient> client;
StartRequest(factory, request, &loader, &client);
@@ -1037,7 +992,7 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponse) {
expected_info->is_in_cache_storage = true;
const network::ResourceResponseHead& info = client->response_head();
ExpectResponseInfo(info, *expected_info);
- EXPECT_EQ(33, info.content_length);
+ EXPECT_EQ(39, info.content_length);
// Test the cached metadata.
client->RunUntilCachedMetadataReceived();
@@ -1073,7 +1028,7 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponseWithoutMetadata) {
base::HistogramTester histogram_tester;
// Construct the Blob to respond with.
- const std::string kResponseBody = "Here is sample text for the Blob.";
+ const std::string kResponseBody = "/* Here is sample text for the Blob. */";
fake_controller_.RespondWithBlob(base::nullopt, kResponseBody);
network::mojom::URLLoaderFactoryPtr factory =
@@ -1081,7 +1036,8 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponseWithoutMetadata) {
// Perform the request.
network::ResourceRequest request =
- CreateRequest(GURL("https://www.example.com/foo.png"));
+ CreateRequest(GURL("https://www.example.com/foo.js"));
+ request.resource_type = static_cast<int>(content::ResourceType::kScript);
network::mojom::URLLoaderPtr loader;
std::unique_ptr<network::TestURLLoaderClient> client;
StartRequest(factory, request, &loader, &client);
@@ -1112,6 +1068,52 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponseWithoutMetadata) {
"ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2", 1);
}
+TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponseNonScript) {
+ // Construct the Blob to respond with.
+ const std::string kResponseBody = "Here is sample text for the Blob.";
+ const std::vector<uint8_t> kMetadata = {0xE3, 0x81, 0x8F, 0xE3, 0x82,
+ 0x8D, 0xE3, 0x81, 0xBF, 0xE3,
+ 0x81, 0x86, 0xE3, 0x82, 0x80};
+ fake_controller_.RespondWithBlob(kMetadata, kResponseBody);
+ fake_controller_.SetResponseSource(
+ network::mojom::FetchResponseSource::kCacheStorage);
+
+ network::mojom::URLLoaderFactoryPtr factory =
+ CreateSubresourceLoaderFactory();
+
+ // Perform the request.
+ network::ResourceRequest request =
+ CreateRequest(GURL("https://www.example.com/foo.txt"));
+ request.resource_type = static_cast<int>(content::ResourceType::kSubResource);
+ network::mojom::URLLoaderPtr loader;
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ StartRequest(factory, request, &loader, &client);
+ client->RunUntilResponseReceived();
+
+ std::unique_ptr<network::ResourceResponseHead> expected_info =
+ CreateResponseInfoFromServiceWorker();
+ // |is_in_cache_storage| should be true because |fake_controller_| sets the
+ // response source as CacheStorage.
+ expected_info->is_in_cache_storage = true;
+ const network::ResourceResponseHead& info = client->response_head();
+ ExpectResponseInfo(info, *expected_info);
+ EXPECT_EQ(33, info.content_length);
+
+ client->RunUntilComplete();
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
+
+ // Even though the blob has metadata, verify that the client didn't receive
+ // it because this is not a script resource.
+ EXPECT_TRUE(client->cached_metadata().empty());
+
+ // Test the body.
+ std::string response;
+ EXPECT_TRUE(client->response_body().is_valid());
+ EXPECT_TRUE(
+ mojo::BlockingCopyToString(client->response_body_release(), &response));
+ EXPECT_EQ(kResponseBody, response);
+}
+
// Test when the service worker responds with network fallback.
// i.e., does not call respondWith().
TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackResponse) {
@@ -1304,7 +1306,10 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, TooManyRedirects) {
}
// Test when the service worker responds with network fallback to CORS request.
-TEST_F(ServiceWorkerSubresourceLoaderTest, CorsFallbackResponse) {
+TEST_F(ServiceWorkerSubresourceLoaderTest, CorsFallbackResponseWithoutOORCors) {
+ base::test::ScopedFeatureList test_features;
+ test_features.InitAndDisableFeature(network::features::kOutOfBlinkCors);
+
fake_controller_.RespondWithFallback();
network::mojom::URLLoaderFactoryPtr factory =
diff --git a/chromium/content/renderer/service_worker/service_worker_timeout_timer.cc b/chromium/content/renderer/service_worker/service_worker_timeout_timer.cc
deleted file mode 100644
index 76293d254aa..00000000000
--- a/chromium/content/renderer/service_worker/service_worker_timeout_timer.cc
+++ /dev/null
@@ -1,217 +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/renderer/service_worker/service_worker_timeout_timer.h"
-
-#include "base/atomic_sequence_num.h"
-#include "base/bind.h"
-#include "base/stl_util.h"
-#include "base/time/default_tick_clock.h"
-#include "base/time/time.h"
-
-namespace content {
-
-namespace {
-
-int NextEventId() {
- // Event id should not start from zero since HashMap in Blink requires
- // non-zero keys.
- static base::AtomicSequenceNumber s_event_id_sequence;
- int next_event_id = s_event_id_sequence.GetNext() + 1;
- CHECK_LT(next_event_id, std::numeric_limits<int>::max());
- return next_event_id;
-}
-
-} // namespace
-
-// static
-constexpr base::TimeDelta ServiceWorkerTimeoutTimer::kIdleDelay;
-constexpr base::TimeDelta ServiceWorkerTimeoutTimer::kEventTimeout;
-constexpr base::TimeDelta ServiceWorkerTimeoutTimer::kUpdateInterval;
-
-ServiceWorkerTimeoutTimer::StayAwakeToken::StayAwakeToken(
- base::WeakPtr<ServiceWorkerTimeoutTimer> timer)
- : timer_(std::move(timer)) {
- DCHECK(timer_);
- timer_->num_of_stay_awake_tokens_++;
-}
-
-ServiceWorkerTimeoutTimer::StayAwakeToken::~StayAwakeToken() {
- // If |timer_| has already been destroyed, it means the worker thread has
- // already been killed.
- if (!timer_)
- return;
- DCHECK_GT(timer_->num_of_stay_awake_tokens_, 0);
- timer_->num_of_stay_awake_tokens_--;
-
- if (!timer_->HasInflightEvent())
- timer_->OnNoInflightEvent();
-}
-
-ServiceWorkerTimeoutTimer::ServiceWorkerTimeoutTimer(
- base::RepeatingClosure idle_callback)
- : ServiceWorkerTimeoutTimer(std::move(idle_callback),
- base::DefaultTickClock::GetInstance()) {}
-
-ServiceWorkerTimeoutTimer::ServiceWorkerTimeoutTimer(
- base::RepeatingClosure idle_callback,
- const base::TickClock* tick_clock)
- : idle_callback_(std::move(idle_callback)),
- tick_clock_(tick_clock),
- weak_factory_(this) {
-}
-
-ServiceWorkerTimeoutTimer::~ServiceWorkerTimeoutTimer() {
- in_dtor_ = true;
- // Abort all callbacks.
- for (auto& event : inflight_events_)
- std::move(event.abort_callback)
- .Run(blink::mojom::ServiceWorkerEventStatus::ABORTED);
-}
-
-void ServiceWorkerTimeoutTimer::Start() {
- DCHECK(!timer_.IsRunning());
- // |idle_callback_| will be invoked if no event happens in |kIdleDelay|.
- if (!HasInflightEvent() && idle_time_.is_null())
- idle_time_ = tick_clock_->NowTicks() + kIdleDelay;
- timer_.Start(FROM_HERE, kUpdateInterval,
- base::BindRepeating(&ServiceWorkerTimeoutTimer::UpdateStatus,
- base::Unretained(this)));
-}
-
-int ServiceWorkerTimeoutTimer::StartEvent(AbortCallback abort_callback) {
- return StartEventWithCustomTimeout(std::move(abort_callback), kEventTimeout);
-}
-
-int ServiceWorkerTimeoutTimer::StartEventWithCustomTimeout(
- AbortCallback abort_callback,
- base::TimeDelta timeout) {
- if (did_idle_timeout()) {
- DCHECK(!running_pending_tasks_);
- idle_time_ = base::TimeTicks();
- did_idle_timeout_ = false;
-
- running_pending_tasks_ = true;
- while (!pending_tasks_.empty()) {
- std::move(pending_tasks_.front()).Run();
- pending_tasks_.pop();
- }
- running_pending_tasks_ = false;
- }
-
- idle_time_ = base::TimeTicks();
- const int event_id = NextEventId();
- std::set<EventInfo>::iterator iter;
- bool is_inserted;
- std::tie(iter, is_inserted) = inflight_events_.emplace(
- event_id, tick_clock_->NowTicks() + timeout,
- base::BindOnce(std::move(abort_callback), event_id));
- DCHECK(is_inserted);
- id_event_map_.emplace(event_id, iter);
- return event_id;
-}
-
-void ServiceWorkerTimeoutTimer::EndEvent(int event_id) {
- DCHECK(HasEvent(event_id));
-
- auto iter = id_event_map_.find(event_id);
- inflight_events_.erase(iter->second);
- id_event_map_.erase(iter);
-
- if (!HasInflightEvent())
- OnNoInflightEvent();
-}
-
-bool ServiceWorkerTimeoutTimer::HasEvent(int event_id) const {
- return id_event_map_.find(event_id) != id_event_map_.end();
-}
-
-std::unique_ptr<ServiceWorkerTimeoutTimer::StayAwakeToken>
-ServiceWorkerTimeoutTimer::CreateStayAwakeToken() {
- return std::make_unique<ServiceWorkerTimeoutTimer::StayAwakeToken>(
- weak_factory_.GetWeakPtr());
-}
-
-void ServiceWorkerTimeoutTimer::PushPendingTask(
- base::OnceClosure pending_task) {
- DCHECK(did_idle_timeout());
- pending_tasks_.emplace(std::move(pending_task));
-}
-
-void ServiceWorkerTimeoutTimer::SetIdleTimerDelayToZero() {
- zero_idle_timer_delay_ = true;
- if (!HasInflightEvent())
- MaybeTriggerIdleTimer();
-}
-
-void ServiceWorkerTimeoutTimer::UpdateStatus() {
- base::TimeTicks now = tick_clock_->NowTicks();
-
- // Abort all events exceeding |kEventTimeout|.
- auto iter = inflight_events_.begin();
- while (iter != inflight_events_.end() && iter->expiration_time <= now) {
- int event_id = iter->id;
- base::OnceCallback<void(blink::mojom::ServiceWorkerEventStatus)> callback =
- std::move(iter->abort_callback);
- iter = inflight_events_.erase(iter);
- id_event_map_.erase(event_id);
- std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::TIMEOUT);
- // Shut down the worker as soon as possible since the worker may have gone
- // into bad state.
- zero_idle_timer_delay_ = true;
- }
-
- // If the worker is now idle, set the |idle_time_| and possibly trigger the
- // idle callback.
- if (!HasInflightEvent() && idle_time_.is_null()) {
- OnNoInflightEvent();
- return;
- }
-
- if (!idle_time_.is_null() && idle_time_ < now) {
- did_idle_timeout_ = true;
- idle_callback_.Run();
- }
-}
-
-bool ServiceWorkerTimeoutTimer::MaybeTriggerIdleTimer() {
- DCHECK(!HasInflightEvent());
- if (!zero_idle_timer_delay_)
- return false;
-
- did_idle_timeout_ = true;
- idle_callback_.Run();
- return true;
-}
-
-void ServiceWorkerTimeoutTimer::OnNoInflightEvent() {
- DCHECK(!HasInflightEvent());
- idle_time_ = tick_clock_->NowTicks() + kIdleDelay;
- MaybeTriggerIdleTimer();
-}
-
-bool ServiceWorkerTimeoutTimer::HasInflightEvent() const {
- return !inflight_events_.empty() || running_pending_tasks_ ||
- num_of_stay_awake_tokens_ > 0;
-}
-
-ServiceWorkerTimeoutTimer::EventInfo::EventInfo(
- int id,
- base::TimeTicks expiration_time,
- base::OnceCallback<void(blink::mojom::ServiceWorkerEventStatus)>
- abort_callback)
- : id(id),
- expiration_time(expiration_time),
- abort_callback(std::move(abort_callback)) {}
-
-ServiceWorkerTimeoutTimer::EventInfo::~EventInfo() = default;
-
-bool ServiceWorkerTimeoutTimer::EventInfo::operator<(
- const EventInfo& other) const {
- if (expiration_time == other.expiration_time)
- return id < other.id;
- return expiration_time < other.expiration_time;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_timeout_timer.h b/chromium/content/renderer/service_worker/service_worker_timeout_timer.h
deleted file mode 100644
index f16f2399684..00000000000
--- a/chromium/content/renderer/service_worker/service_worker_timeout_timer.h
+++ /dev/null
@@ -1,200 +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_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TIMEOUT_TIMER_H_
-#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TIMEOUT_TIMER_H_
-
-#include <map>
-#include <set>
-
-#include "base/callback.h"
-#include "base/containers/queue.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "content/common/content_export.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
-
-namespace base {
-
-class TickClock;
-
-} // namespace base
-
-namespace content {
-
-// ServiceWorkerTimeoutTimer manages two types of timeouts: the long standing
-// event timeout and the idle timeout.
-//
-// 1) Event timeout: when an event starts, StartEvent() records the expiration
-// time of the event (kEventTimeout). If EndEvent() has not been called within
-// the timeout time, |abort_callback| passed to StartEvent() is called with
-// status TIMEOUT. Also, |zero_idle_timer_delay_| is set to true to shut down
-// the worker as soon as possible since the worker may have gone into bad state.
-// 2) Idle timeout: when a certain time has passed (kIdleDelay) since all of
-// events have ended, ServiceWorkerTimeoutTimer calls the |idle_callback|.
-// |idle_callback| will be continuously called at a certain interval
-// (kUpdateInterval) until the next event starts.
-//
-// The lifetime of ServiceWorkerTimeoutTimer is the same with the worker
-// thread. If ServiceWorkerTimeoutTimer is destructed while there are inflight
-// events, all |abort_callback|s will be immediately called with status ABORTED.
-class CONTENT_EXPORT ServiceWorkerTimeoutTimer {
- public:
- // A token to keep the timeout timer from going into the idle state if any of
- // them are alive.
- class CONTENT_EXPORT StayAwakeToken {
- public:
- explicit StayAwakeToken(base::WeakPtr<ServiceWorkerTimeoutTimer> timer);
- ~StayAwakeToken();
-
- private:
- base::WeakPtr<ServiceWorkerTimeoutTimer> timer_;
- };
-
- using AbortCallback =
- base::OnceCallback<void(int /* event_id */,
- blink::mojom::ServiceWorkerEventStatus)>;
-
- explicit ServiceWorkerTimeoutTimer(base::RepeatingClosure idle_callback);
- // For testing.
- ServiceWorkerTimeoutTimer(base::RepeatingClosure idle_callback,
- const base::TickClock* tick_clock);
- ~ServiceWorkerTimeoutTimer();
-
- // Starts the timer. This may also update |idle_time_| if there was no
- // activities (i.e., StartEvent()/EndEvent() or StayAwakeToken creation)
- // on the timer before.
- void Start();
-
- // StartEvent() should be called at the beginning of an event. It returns an
- // event id, which is unique among threads in the same process.
- // The event id should be passed to EndEvent() when the event has finished.
- // If there are pending tasks queued by PushPendingTask(), they will
- // run in order synchronouslly in StartEvent().
- // See the class comment to know when |abort_callback| runs.
- int StartEvent(AbortCallback abort_callback);
- // This is basically the same as StartEvent, but you can customize the
- // timeout time until |abort_callback| runs by |timeout|.
- int StartEventWithCustomTimeout(AbortCallback abort_callback,
- base::TimeDelta timeout);
-
- void EndEvent(int event_id);
-
- // Returns true if |event_id| was started and hasn't ended.
- bool HasEvent(int event_id) const;
-
- // Creates a StayAwakeToken to ensure that the idle timer won't be triggered
- // while any of these are alive.
- std::unique_ptr<StayAwakeToken> CreateStayAwakeToken();
-
- // Pushes a task which is expected to run after any event starts again to a
- // pending task queue. The tasks will run at the next StartEvent() call.
- // PushPendingTask() should be called if the idle timeout occurred
- // (did_idle_timeout() returns true).
- void PushPendingTask(base::OnceClosure pending_task);
-
- // Sets the |zero_idle_timer_delay_| to true and triggers the idle callback if
- // there are not inflight events. If there are, the callback will be called
- // next time when the set of inflight events becomes empty in EndEvent().
- void SetIdleTimerDelayToZero();
-
- // Returns true if the timer thinks no events ran for a while, and has
- // triggered the |idle_callback| passed to the constructor. It'll be reset to
- // false again when StartEvent() is called.
- bool did_idle_timeout() const { return did_idle_timeout_; }
-
- // Idle timeout duration since the last event has finished.
- static constexpr base::TimeDelta kIdleDelay =
- base::TimeDelta::FromSeconds(30);
- // Duration of the long standing event timeout since StartEvent() has been
- // called.
- static constexpr base::TimeDelta kEventTimeout =
- base::TimeDelta::FromMinutes(5);
- // ServiceWorkerTimeoutTimer periodically updates the timeout state by
- // kUpdateInterval.
- static constexpr base::TimeDelta kUpdateInterval =
- base::TimeDelta::FromSeconds(30);
-
- private:
- // Updates the internal states and fires timeout callbacks if any.
- void UpdateStatus();
-
- // Triggers idle timer if |zero_idle_timer_delay_| is true. Returns true if
- // the idle callback is called.
- bool MaybeTriggerIdleTimer();
-
- // Sets the |idle_time_| and maybe calls |idle_callback_| immediately if the
- // timeout delay is set to zero.
- void OnNoInflightEvent();
-
- // Returns true if there are running events.
- bool HasInflightEvent() const;
-
- struct EventInfo {
- EventInfo(int id,
- base::TimeTicks expiration_time,
- base::OnceCallback<void(blink::mojom::ServiceWorkerEventStatus)>
- abort_callback);
- ~EventInfo();
- // Compares |expiration_time|, or |id| if |expiration_time| is the same.
- bool operator<(const EventInfo& other) const;
-
- const int id;
- const base::TimeTicks expiration_time;
- mutable base::OnceCallback<void(blink::mojom::ServiceWorkerEventStatus)>
- abort_callback;
- };
-
- // For long standing event timeouts. Ordered by expiration time.
- std::set<EventInfo> inflight_events_;
-
- // For long standing event timeouts. This is used to look up an event in
- // |inflight_events_| by its id.
- std::map<int /* event_id */, std::set<EventInfo>::iterator> id_event_map_;
-
- // For idle timeouts. The time the service worker started being considered
- // idle. This time is null if there are any inflight events.
- base::TimeTicks idle_time_;
-
- // Set to true if the idle callback should be fired immediately after all
- // inflight events finish.
- bool zero_idle_timer_delay_ = false;
-
- // For idle timeouts. Invoked when UpdateStatus() is called after
- // |idle_time_|.
- base::RepeatingClosure idle_callback_;
-
- // Set to true once |idle_callback_| has been invoked. Set to false when
- // StartEvent() is called.
- bool did_idle_timeout_ = false;
-
- // Tasks that are to be run after the next StartEvent() call. In practice, the
- // caller adds pending tasks after the service worker requested the browser to
- // terminate it due to idleness. These tasks run once StartEvent() is called
- // due to a new event from the browser, signalling that the browser decided
- // not to terminate the worker.
- base::queue<base::OnceClosure> pending_tasks_;
-
- // Set to true during running |pending_tasks_|. This is used for avoiding to
- // invoke |idle_callback_| when running |pending_tasks_|.
- bool running_pending_tasks_ = false;
-
- // The number of the living StayAwakeToken. See also class comments.
- int num_of_stay_awake_tokens_ = 0;
-
- // |timer_| invokes UpdateEventStatus() periodically.
- base::RepeatingTimer timer_;
-
- // |tick_clock_| outlives |this|.
- const base::TickClock* const tick_clock_;
-
- bool in_dtor_ = false;
-
- base::WeakPtrFactory<ServiceWorkerTimeoutTimer> weak_factory_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TIMEOUT_TIMER_H_
diff --git a/chromium/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc b/chromium/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc
deleted file mode 100644
index 68f602a546c..00000000000
--- a/chromium/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc
+++ /dev/null
@@ -1,419 +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/renderer/service_worker/service_worker_timeout_timer.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/location.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/optional.h"
-#include "base/test/test_mock_time_task_runner.h"
-#include "base/time/tick_clock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
-
-namespace content {
-
-namespace {
-
-class MockEvent {
- public:
- MockEvent() : weak_factory_(this) {}
-
- ServiceWorkerTimeoutTimer::AbortCallback CreateAbortCallback() {
- return base::BindOnce(&MockEvent::Abort, weak_factory_.GetWeakPtr());
- }
-
- int event_id() const { return event_id_; }
- void set_event_id(int event_id) { event_id_ = event_id; }
- const base::Optional<blink::mojom::ServiceWorkerEventStatus>& status() const {
- return status_;
- }
-
- private:
- void Abort(int event_id, blink::mojom::ServiceWorkerEventStatus status) {
- EXPECT_EQ(event_id_, event_id);
- EXPECT_FALSE(status_.has_value());
- status_ = status;
- }
-
- int event_id_ = 0;
- base::Optional<blink::mojom::ServiceWorkerEventStatus> status_;
- base::WeakPtrFactory<MockEvent> weak_factory_;
-};
-
-base::RepeatingClosure CreateReceiverWithCalledFlag(bool* out_is_called) {
- return base::BindRepeating([](bool* out_is_called) { *out_is_called = true; },
- out_is_called);
-}
-
-base::OnceClosure CreateDispatchingEventTask(
- ServiceWorkerTimeoutTimer* timer,
- std::string tag,
- std::vector<std::string>* out_tags) {
- return base::BindOnce(
- [](ServiceWorkerTimeoutTimer* timer, std::string tag,
- std::vector<std::string>* out_tags) {
- // Event dispatched inside of pending task should run successfully.
- MockEvent event;
- const int event_id = timer->StartEvent(event.CreateAbortCallback());
- event.set_event_id(event_id);
- EXPECT_FALSE(timer->did_idle_timeout());
- EXPECT_FALSE(event.status().has_value());
-
- out_tags->emplace_back(std::move(tag));
-
- timer->EndEvent(event_id);
- EXPECT_FALSE(event.status().has_value());
- },
- timer, std::move(tag), out_tags);
-}
-
-} // namespace
-
-using StayAwakeToken = ServiceWorkerTimeoutTimer::StayAwakeToken;
-
-class ServiceWorkerTimeoutTimerTest : public testing::Test {
- protected:
- void SetUp() override {
- task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
- base::Time::Now(), base::TimeTicks::Now());
- message_loop_.SetTaskRunner(task_runner_);
- }
-
- base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); }
-
- private:
- base::MessageLoop message_loop_;
- scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
-};
-
-TEST_F(ServiceWorkerTimeoutTimerTest, IdleTimer) {
- const base::TimeDelta kIdleInterval =
- ServiceWorkerTimeoutTimer::kIdleDelay +
- ServiceWorkerTimeoutTimer::kUpdateInterval +
- base::TimeDelta::FromSeconds(1);
-
- bool is_idle = false;
- ServiceWorkerTimeoutTimer timer(CreateReceiverWithCalledFlag(&is_idle),
- task_runner()->GetMockTickClock());
- task_runner()->FastForwardBy(kIdleInterval);
- // Nothing should happen since the timer has not started yet.
- EXPECT_FALSE(is_idle);
-
- timer.Start();
- task_runner()->FastForwardBy(kIdleInterval);
- // |idle_callback| should be fired since there is no event.
- EXPECT_TRUE(is_idle);
-
- is_idle = false;
- int event_id_1 = timer.StartEvent(base::DoNothing());
- task_runner()->FastForwardBy(kIdleInterval);
- // Nothing happens since there is an inflight event.
- EXPECT_FALSE(is_idle);
-
- int event_id_2 = timer.StartEvent(base::DoNothing());
- task_runner()->FastForwardBy(kIdleInterval);
- // Nothing happens since there are two inflight events.
- EXPECT_FALSE(is_idle);
-
- timer.EndEvent(event_id_2);
- task_runner()->FastForwardBy(kIdleInterval);
- // Nothing happens since there is an inflight event.
- EXPECT_FALSE(is_idle);
-
- timer.EndEvent(event_id_1);
- task_runner()->FastForwardBy(kIdleInterval);
- // |idle_callback| should be fired.
- EXPECT_TRUE(is_idle);
-
- is_idle = false;
- int event_id_3 = timer.StartEvent(base::DoNothing());
- task_runner()->FastForwardBy(kIdleInterval);
- // Nothing happens since there is an inflight event.
- EXPECT_FALSE(is_idle);
-
- std::unique_ptr<StayAwakeToken> token = timer.CreateStayAwakeToken();
- timer.EndEvent(event_id_3);
- task_runner()->FastForwardBy(kIdleInterval);
- // Nothing happens since there is a living StayAwakeToken.
- EXPECT_FALSE(is_idle);
-
- token.reset();
- // |idle_callback| isn't triggered immendiately.
- EXPECT_FALSE(is_idle);
- task_runner()->FastForwardBy(kIdleInterval);
- // |idle_callback| should be fired.
- EXPECT_TRUE(is_idle);
-}
-
-TEST_F(ServiceWorkerTimeoutTimerTest, InflightEventBeforeStart) {
- const base::TimeDelta kIdleInterval =
- ServiceWorkerTimeoutTimer::kIdleDelay +
- ServiceWorkerTimeoutTimer::kUpdateInterval +
- base::TimeDelta::FromSeconds(1);
-
- bool is_idle = false;
- ServiceWorkerTimeoutTimer timer(CreateReceiverWithCalledFlag(&is_idle),
- task_runner()->GetMockTickClock());
- timer.StartEvent(base::DoNothing());
- timer.Start();
- task_runner()->FastForwardBy(kIdleInterval);
- // Nothing happens since there is an inflight event.
- EXPECT_FALSE(is_idle);
-}
-
-// Tests whether idle_time_ won't be updated in Start() when there was an
-// event. The timeline is something like:
-// [StartEvent] [EndEvent]
-// +----------+
-// ^
-// +-- idle_time_ --+
-// v
-// [TimerStart] [UpdateStatus]
-// +-- kUpdateInterval --+
-// In the first UpdateStatus() the idle callback should be triggered.
-TEST_F(ServiceWorkerTimeoutTimerTest, EventFinishedBeforeStart) {
- bool is_idle = false;
- ServiceWorkerTimeoutTimer timer(CreateReceiverWithCalledFlag(&is_idle),
- task_runner()->GetMockTickClock());
- // Start and finish an event before starting the timer.
- int event_id = timer.StartEvent(base::DoNothing());
- task_runner()->FastForwardBy(base::TimeDelta::FromSeconds(1));
- timer.EndEvent(event_id);
-
- // Move the time ticks to almost before |idle_time_| so that |idle_callback|
- // will get called at the first update check.
- task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kIdleDelay -
- base::TimeDelta::FromSeconds(1));
-
- timer.Start();
-
- // Make sure the timer calls UpdateStatus().
- task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kUpdateInterval +
- base::TimeDelta::FromSeconds(1));
- // |idle_callback| should be fired because enough time passed since the last
- // event.
- EXPECT_TRUE(is_idle);
-}
-
-TEST_F(ServiceWorkerTimeoutTimerTest, EventTimer) {
- ServiceWorkerTimeoutTimer timer(base::DoNothing(),
- task_runner()->GetMockTickClock());
- timer.Start();
-
- MockEvent event1, event2;
- int event_id1 = timer.StartEvent(event1.CreateAbortCallback());
- int event_id2 = timer.StartEvent(event2.CreateAbortCallback());
- event1.set_event_id(event_id1);
- event2.set_event_id(event_id2);
- task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kUpdateInterval +
- base::TimeDelta::FromSeconds(1));
-
- EXPECT_FALSE(event1.status().has_value());
- EXPECT_FALSE(event2.status().has_value());
- timer.EndEvent(event1.event_id());
- task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kEventTimeout +
- base::TimeDelta::FromSeconds(1));
-
- EXPECT_FALSE(event1.status().has_value());
- EXPECT_TRUE(event2.status().has_value());
- EXPECT_EQ(blink::mojom::ServiceWorkerEventStatus::TIMEOUT,
- event2.status().value());
-}
-
-TEST_F(ServiceWorkerTimeoutTimerTest, CustomTimeouts) {
- ServiceWorkerTimeoutTimer timer(base::DoNothing(),
- task_runner()->GetMockTickClock());
- timer.Start();
- MockEvent event1, event2;
- int event_id1 = timer.StartEventWithCustomTimeout(
- event1.CreateAbortCallback(), ServiceWorkerTimeoutTimer::kUpdateInterval -
- base::TimeDelta::FromSeconds(1));
- int event_id2 = timer.StartEventWithCustomTimeout(
- event2.CreateAbortCallback(),
- ServiceWorkerTimeoutTimer::kUpdateInterval * 2 -
- base::TimeDelta::FromSeconds(1));
- event1.set_event_id(event_id1);
- event2.set_event_id(event_id2);
- task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kUpdateInterval +
- base::TimeDelta::FromSeconds(1));
-
- EXPECT_TRUE(event1.status().has_value());
- EXPECT_FALSE(event2.status().has_value());
- EXPECT_EQ(blink::mojom::ServiceWorkerEventStatus::TIMEOUT,
- event1.status().value());
- task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kUpdateInterval +
- base::TimeDelta::FromSeconds(1));
-
- EXPECT_TRUE(event1.status().has_value());
- EXPECT_TRUE(event2.status().has_value());
- EXPECT_EQ(blink::mojom::ServiceWorkerEventStatus::TIMEOUT,
- event2.status().value());
-}
-
-TEST_F(ServiceWorkerTimeoutTimerTest, BecomeIdleAfterAbort) {
- bool is_idle = false;
- ServiceWorkerTimeoutTimer timer(CreateReceiverWithCalledFlag(&is_idle),
- task_runner()->GetMockTickClock());
- timer.Start();
-
- MockEvent event;
- int event_id = timer.StartEvent(event.CreateAbortCallback());
- event.set_event_id(event_id);
- task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kEventTimeout +
- ServiceWorkerTimeoutTimer::kUpdateInterval +
- base::TimeDelta::FromSeconds(1));
-
- // |event| should have been aborted, and at the same time, the idle timeout
- // should also be fired since there has been an aborted event.
- EXPECT_TRUE(event.status().has_value());
- EXPECT_TRUE(is_idle);
-}
-
-TEST_F(ServiceWorkerTimeoutTimerTest, AbortAllOnDestruction) {
- MockEvent event1, event2;
- {
- ServiceWorkerTimeoutTimer timer(base::DoNothing(),
- task_runner()->GetMockTickClock());
- timer.Start();
-
- int event_id1 = timer.StartEvent(event1.CreateAbortCallback());
- int event_id2 = timer.StartEvent(event2.CreateAbortCallback());
- event1.set_event_id(event_id1);
- event2.set_event_id(event_id2);
- task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kUpdateInterval +
- base::TimeDelta::FromSeconds(1));
-
- EXPECT_FALSE(event1.status().has_value());
- EXPECT_FALSE(event2.status().has_value());
- }
-
- EXPECT_TRUE(event1.status().has_value());
- EXPECT_EQ(blink::mojom::ServiceWorkerEventStatus::ABORTED,
- event1.status().value());
- EXPECT_TRUE(event2.status().has_value());
- EXPECT_EQ(blink::mojom::ServiceWorkerEventStatus::ABORTED,
- event2.status().value());
-}
-
-TEST_F(ServiceWorkerTimeoutTimerTest, PushPendingTask) {
- ServiceWorkerTimeoutTimer timer(base::DoNothing(),
- task_runner()->GetMockTickClock());
- timer.Start();
- task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kIdleDelay +
- ServiceWorkerTimeoutTimer::kUpdateInterval +
- base::TimeDelta::FromSeconds(1));
- EXPECT_TRUE(timer.did_idle_timeout());
-
- bool did_task_run = false;
- timer.PushPendingTask(CreateReceiverWithCalledFlag(&did_task_run));
-
- // Start a new event. StartEvent() should run the pending tasks.
- MockEvent event;
- const int event_id = timer.StartEvent(event.CreateAbortCallback());
- event.set_event_id(event_id);
- EXPECT_FALSE(timer.did_idle_timeout());
- EXPECT_TRUE(did_task_run);
-}
-
-// Test that pending tasks are run when StartEvent() is called while there the
-// idle timer delay is zero. Regression test for https://crbug.com/878608.
-TEST_F(ServiceWorkerTimeoutTimerTest, RunPendingTasksWithZeroIdleTimerDelay) {
- ServiceWorkerTimeoutTimer timer(base::DoNothing(),
- task_runner()->GetMockTickClock());
- timer.Start();
- timer.SetIdleTimerDelayToZero();
- EXPECT_TRUE(timer.did_idle_timeout());
-
- std::vector<std::string> handled_tasks;
- timer.PushPendingTask(
- CreateDispatchingEventTask(&timer, "1", &handled_tasks));
- timer.PushPendingTask(
- CreateDispatchingEventTask(&timer, "2", &handled_tasks));
-
- // Start a new event. StartEvent() should run the pending tasks.
- MockEvent event;
- const int event_id = timer.StartEvent(event.CreateAbortCallback());
- event.set_event_id(event_id);
- EXPECT_FALSE(timer.did_idle_timeout());
- ASSERT_EQ(2u, handled_tasks.size());
- EXPECT_EQ("1", handled_tasks[0]);
- EXPECT_EQ("2", handled_tasks[1]);
-}
-
-TEST_F(ServiceWorkerTimeoutTimerTest, SetIdleTimerDelayToZero) {
- {
- bool is_idle = false;
- ServiceWorkerTimeoutTimer timer(CreateReceiverWithCalledFlag(&is_idle),
- task_runner()->GetMockTickClock());
- timer.Start();
- EXPECT_FALSE(is_idle);
-
- timer.SetIdleTimerDelayToZero();
- // |idle_callback| should be fired since there is no event.
- EXPECT_TRUE(is_idle);
- }
-
- {
- bool is_idle = false;
- ServiceWorkerTimeoutTimer timer(CreateReceiverWithCalledFlag(&is_idle),
- task_runner()->GetMockTickClock());
- timer.Start();
- int event_id = timer.StartEvent(base::DoNothing());
- timer.SetIdleTimerDelayToZero();
- // Nothing happens since there is an inflight event.
- EXPECT_FALSE(is_idle);
-
- timer.EndEvent(event_id);
- // EndEvent() immediately triggers the idle callback.
- EXPECT_TRUE(is_idle);
- }
-
- {
- bool is_idle = false;
- ServiceWorkerTimeoutTimer timer(CreateReceiverWithCalledFlag(&is_idle),
- task_runner()->GetMockTickClock());
- timer.Start();
- int event_id_1 = timer.StartEvent(base::DoNothing());
- int event_id_2 = timer.StartEvent(base::DoNothing());
- timer.SetIdleTimerDelayToZero();
- // Nothing happens since there are two inflight events.
- EXPECT_FALSE(is_idle);
-
- timer.EndEvent(event_id_1);
- // Nothing happens since there is an inflight event.
- EXPECT_FALSE(is_idle);
-
- timer.EndEvent(event_id_2);
- // EndEvent() immediately triggers the idle callback when no inflight events
- // exist.
- EXPECT_TRUE(is_idle);
- }
-
- {
- bool is_idle = false;
- ServiceWorkerTimeoutTimer timer(CreateReceiverWithCalledFlag(&is_idle),
- task_runner()->GetMockTickClock());
- timer.Start();
- std::unique_ptr<StayAwakeToken> token_1 = timer.CreateStayAwakeToken();
- std::unique_ptr<StayAwakeToken> token_2 = timer.CreateStayAwakeToken();
- timer.SetIdleTimerDelayToZero();
- // Nothing happens since there are two living tokens.
- EXPECT_FALSE(is_idle);
-
- token_1.reset();
- // Nothing happens since there is an living token.
- EXPECT_FALSE(is_idle);
-
- token_2.reset();
- // EndEvent() immediately triggers the idle callback when no tokens exist.
- EXPECT_TRUE(is_idle);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_type_converters.cc b/chromium/content/renderer/service_worker/service_worker_type_converters.cc
index 638620cd965..b7d30068d28 100644
--- a/chromium/content/renderer/service_worker/service_worker_type_converters.cc
+++ b/chromium/content/renderer/service_worker/service_worker_type_converters.cc
@@ -10,126 +10,6 @@
namespace mojo {
-blink::WebCanMakePaymentEventData
-TypeConverter<blink::WebCanMakePaymentEventData,
- payments::mojom::CanMakePaymentEventDataPtr>::
- Convert(const payments::mojom::CanMakePaymentEventDataPtr& input) {
- blink::WebCanMakePaymentEventData output;
-
- output.top_origin = blink::WebString::FromUTF8(input->top_origin.spec());
- output.payment_request_origin =
- blink::WebString::FromUTF8(input->payment_request_origin.spec());
-
- output.method_data =
- blink::WebVector<blink::WebPaymentMethodData>(input->method_data.size());
- for (size_t i = 0; i < input->method_data.size(); i++) {
- output.method_data[i] = mojo::ConvertTo<blink::WebPaymentMethodData>(
- std::move(input->method_data[i]));
- }
-
- output.modifiers = blink::WebVector<blink::WebPaymentDetailsModifier>(
- input->modifiers.size());
- for (size_t i = 0; i < input->modifiers.size(); i++) {
- output.modifiers[i] =
- mojo::ConvertTo<blink::WebPaymentDetailsModifier>(input->modifiers[i]);
- }
-
- return output;
-}
-
-blink::WebPaymentRequestEventData
-TypeConverter<blink::WebPaymentRequestEventData,
- payments::mojom::PaymentRequestEventDataPtr>::
- Convert(const payments::mojom::PaymentRequestEventDataPtr& input) {
- blink::WebPaymentRequestEventData output;
-
- output.top_origin = blink::WebString::FromUTF8(input->top_origin.spec());
- output.payment_request_origin =
- blink::WebString::FromUTF8(input->payment_request_origin.spec());
- output.payment_request_id =
- blink::WebString::FromUTF8(input->payment_request_id);
-
- output.method_data =
- blink::WebVector<blink::WebPaymentMethodData>(input->method_data.size());
- for (size_t i = 0; i < input->method_data.size(); i++) {
- output.method_data[i] = mojo::ConvertTo<blink::WebPaymentMethodData>(
- std::move(input->method_data[i]));
- }
-
- output.total = mojo::ConvertTo<blink::WebPaymentCurrencyAmount>(input->total);
-
- output.modifiers = blink::WebVector<blink::WebPaymentDetailsModifier>(
- input->modifiers.size());
- for (size_t i = 0; i < input->modifiers.size(); i++) {
- output.modifiers[i] =
- mojo::ConvertTo<blink::WebPaymentDetailsModifier>(input->modifiers[i]);
- }
-
- output.instrument_key = blink::WebString::FromUTF8(input->instrument_key);
-
- return output;
-}
-
-blink::WebPaymentMethodData
-TypeConverter<blink::WebPaymentMethodData,
- payments::mojom::PaymentMethodDataPtr>::
- Convert(const payments::mojom::PaymentMethodDataPtr& input) {
- DCHECK(!input->supported_method.empty());
- blink::WebPaymentMethodData output;
- output.supported_method = blink::WebString::FromUTF8(input->supported_method);
- output.stringified_data = blink::WebString::FromUTF8(input->stringified_data);
-
- return output;
-}
-
-blink::WebPaymentItem
-TypeConverter<blink::WebPaymentItem, payments::mojom::PaymentItemPtr>::Convert(
- const payments::mojom::PaymentItemPtr& input) {
- blink::WebPaymentItem output;
- output.label = blink::WebString::FromUTF8(input->label);
- output.amount =
- mojo::ConvertTo<blink::WebPaymentCurrencyAmount>(input->amount);
- output.pending = input->pending;
- return output;
-}
-
-blink::WebPaymentCurrencyAmount
-TypeConverter<blink::WebPaymentCurrencyAmount,
- payments::mojom::PaymentCurrencyAmountPtr>::
- Convert(const payments::mojom::PaymentCurrencyAmountPtr& input) {
- blink::WebPaymentCurrencyAmount output;
- output.currency = blink::WebString::FromUTF8(input->currency);
- output.value = blink::WebString::FromUTF8(input->value);
- return output;
-}
-
-blink::WebPaymentDetailsModifier
-TypeConverter<blink::WebPaymentDetailsModifier,
- payments::mojom::PaymentDetailsModifierPtr>::
- Convert(const payments::mojom::PaymentDetailsModifierPtr& input) {
- DCHECK(!input->method_data->supported_method.empty());
- blink::WebPaymentDetailsModifier output;
-
- output.supported_method =
- blink::WebString::FromUTF8(input->method_data->supported_method);
-
- // The total is optional in a modifier.
- if (input->total)
- output.total = mojo::ConvertTo<blink::WebPaymentItem>(input->total);
-
- output.additional_display_items = blink::WebVector<blink::WebPaymentItem>(
- input->additional_display_items.size());
- for (size_t i = 0; i < input->additional_display_items.size(); i++) {
- output.additional_display_items[i] = mojo::ConvertTo<blink::WebPaymentItem>(
- input->additional_display_items[i]);
- }
-
- output.stringified_data =
- blink::WebString::FromUTF8(input->method_data->stringified_data);
-
- return output;
-}
-
blink::WebServiceWorkerObjectInfo
TypeConverter<blink::WebServiceWorkerObjectInfo,
blink::mojom::ServiceWorkerObjectInfoPtr>::
diff --git a/chromium/content/renderer/service_worker/service_worker_type_converters.h b/chromium/content/renderer/service_worker/service_worker_type_converters.h
index aedfaeae556..2fbf6a9bc2b 100644
--- a/chromium/content/renderer/service_worker/service_worker_type_converters.h
+++ b/chromium/content/renderer/service_worker/service_worker_type_converters.h
@@ -5,13 +5,12 @@
#ifndef CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TYPE_CONVERTERS_H_
#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TYPE_CONVERTERS_H_
+#include <memory>
+
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
-#include "third_party/blink/public/mojom/payments/payment_app.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_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
-#include "third_party/blink/public/platform/modules/payments/web_can_make_payment_event_data.h"
-#include "third_party/blink/public/platform/modules/payments/web_payment_request_event_data.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_object_info.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration_object_info.h"
#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h"
@@ -19,47 +18,6 @@
namespace mojo {
template <>
-struct TypeConverter<blink::WebCanMakePaymentEventData,
- payments::mojom::CanMakePaymentEventDataPtr> {
- static blink::WebCanMakePaymentEventData Convert(
- const payments::mojom::CanMakePaymentEventDataPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::WebPaymentRequestEventData,
- payments::mojom::PaymentRequestEventDataPtr> {
- static blink::WebPaymentRequestEventData Convert(
- const payments::mojom::PaymentRequestEventDataPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::WebPaymentMethodData,
- payments::mojom::PaymentMethodDataPtr> {
- static blink::WebPaymentMethodData Convert(
- const payments::mojom::PaymentMethodDataPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::WebPaymentItem, payments::mojom::PaymentItemPtr> {
- static blink::WebPaymentItem Convert(
- const payments::mojom::PaymentItemPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::WebPaymentCurrencyAmount,
- payments::mojom::PaymentCurrencyAmountPtr> {
- static blink::WebPaymentCurrencyAmount Convert(
- const payments::mojom::PaymentCurrencyAmountPtr& input);
-};
-
-template <>
-struct TypeConverter<blink::WebPaymentDetailsModifier,
- payments::mojom::PaymentDetailsModifierPtr> {
- static blink::WebPaymentDetailsModifier Convert(
- const payments::mojom::PaymentDetailsModifierPtr& input);
-};
-
-template <>
struct TypeConverter<blink::WebServiceWorkerObjectInfo,
blink::mojom::ServiceWorkerObjectInfoPtr> {
static blink::WebServiceWorkerObjectInfo Convert(
diff --git a/chromium/content/renderer/service_worker/service_worker_type_util.cc b/chromium/content/renderer/service_worker/service_worker_type_util.cc
deleted file mode 100644
index 431355a36ec..00000000000
--- a/chromium/content/renderer/service_worker/service_worker_type_util.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/service_worker/service_worker_type_util.h"
-
-#include <memory>
-#include <string>
-
-#include "base/strings/utf_string_conversions.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "storage/common/blob_storage/blob_handle.h"
-#include "third_party/blink/public/common/fetch/fetch_api_request_headers_map.h"
-#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
-#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
-#include "third_party/blink/public/platform/web_http_header_visitor.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace content {
-
-namespace {
-
-template <typename T>
-class HeaderVisitor : public blink::WebHTTPHeaderVisitor {
- public:
- explicit HeaderVisitor(T* headers) : headers_(headers) {}
- ~HeaderVisitor() override {}
-
- void VisitHeader(const blink::WebString& name,
- const blink::WebString& value) override {
- // Headers are ISO Latin 1.
- const std::string& header_name = name.Latin1();
- const std::string& header_value = value.Latin1();
- CHECK(header_name.find('\0') == std::string::npos);
- CHECK(header_value.find('\0') == std::string::npos);
- headers_->insert(typename T::value_type(header_name, header_value));
- }
-
- private:
- T* const headers_;
-};
-
-template <typename T>
-std::unique_ptr<HeaderVisitor<T>> MakeHeaderVisitor(T* headers) {
- return std::make_unique<HeaderVisitor<T>>(headers);
-}
-
-std::vector<std::string> GetHeaderList(
- const blink::WebVector<blink::WebString>& web_headers) {
- auto result = std::vector<std::string>(web_headers.size());
- std::transform(web_headers.begin(), web_headers.end(), result.begin(),
- [](const blink::WebString& s) { return s.Latin1(); });
- return result;
-}
-
-std::vector<GURL> GetURLList(
- const blink::WebVector<blink::WebURL>& web_url_list) {
- std::vector<GURL> result = std::vector<GURL>(web_url_list.size());
- std::transform(web_url_list.begin(), web_url_list.end(), result.begin(),
- [](const blink::WebURL& url) { return url; });
- return result;
-}
-
-} // namespace
-
-void GetServiceWorkerHeaderMapFromWebRequest(
- const blink::WebServiceWorkerRequest& web_request,
- blink::FetchAPIRequestHeadersMap* headers) {
- DCHECK(headers);
- DCHECK(headers->empty());
- web_request.VisitHttpHeaderFields(MakeHeaderVisitor(headers).get());
-}
-
-blink::mojom::FetchAPIResponsePtr GetFetchAPIResponseFromWebResponse(
- const blink::WebServiceWorkerResponse& web_response) {
- blink::mojom::SerializedBlobPtr blob;
- if (!web_response.BlobUUID().IsEmpty()) {
- blob = blink::mojom::SerializedBlob::New();
- blob->uuid = web_response.BlobUUID().Utf8();
- blob->size = web_response.BlobSize();
- auto blob_pipe = web_response.CloneBlobPtr();
- DCHECK(blob_pipe.is_valid());
- blob->blob = blink::mojom::BlobPtrInfo(std::move(blob_pipe),
- blink::mojom::Blob::Version_);
- }
-
- blink::mojom::SerializedBlobPtr side_data_blob;
- if (web_response.SideDataBlobSize() != 0) {
- side_data_blob = blink::mojom::SerializedBlob::New();
- side_data_blob->uuid = web_response.SideDataBlobUUID().Utf8();
- side_data_blob->size = web_response.SideDataBlobSize();
- auto side_data_blob_pipe = web_response.CloneSideDataBlobPtr();
- DCHECK(side_data_blob_pipe.is_valid());
- side_data_blob->blob = blink::mojom::BlobPtrInfo(
- std::move(side_data_blob_pipe), blink::mojom::Blob::Version_);
- }
-
- base::flat_map<std::string, std::string> headers;
- web_response.VisitHttpHeaderFields(MakeHeaderVisitor(&headers).get());
-
- return blink::mojom::FetchAPIResponse::New(
- GetURLList(web_response.UrlList()), web_response.Status(),
- web_response.StatusText().Utf8(), web_response.ResponseType(),
- web_response.ResponseSource(), headers, std::move(blob),
- web_response.GetError(), web_response.ResponseTime(),
- web_response.CacheStorageCacheName().Utf8(),
- GetHeaderList(web_response.CorsExposedHeaderNames()),
- std::move(side_data_blob));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_type_util.h b/chromium/content/renderer/service_worker/service_worker_type_util.h
deleted file mode 100644
index 8d7c146706f..00000000000
--- a/chromium/content/renderer/service_worker/service_worker_type_util.h
+++ /dev/null
@@ -1,28 +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_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TYPE_UTIL_H_
-#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TYPE_UTIL_H_
-
-#include "content/common/service_worker/service_worker_types.h"
-#include "third_party/blink/public/common/fetch/fetch_api_request_headers_map.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
-
-namespace blink {
-class WebServiceWorkerRequest;
-class WebServiceWorkerResponse;
-}
-
-namespace content {
-
-void CONTENT_EXPORT GetServiceWorkerHeaderMapFromWebRequest(
- const blink::WebServiceWorkerRequest& web_request,
- blink::FetchAPIRequestHeadersMap* headers);
-
-blink::mojom::FetchAPIResponsePtr GetFetchAPIResponseFromWebResponse(
- const blink::WebServiceWorkerResponse& web_response);
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TYPE_UTIL_H_
diff --git a/chromium/content/renderer/v8_value_converter_impl.cc b/chromium/content/renderer/v8_value_converter_impl.cc
index c33074d77a7..2deb79ba006 100644
--- a/chromium/content/renderer/v8_value_converter_impl.cc
+++ b/chromium/content/renderer/v8_value_converter_impl.cc
@@ -23,19 +23,15 @@ namespace content {
// Default implementation of V8ValueConverter::Strategy
-bool V8ValueConverter::Strategy::FromV8Object(
- v8::Local<v8::Object> value,
- std::unique_ptr<base::Value>* out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback) {
+bool V8ValueConverter::Strategy::FromV8Object(v8::Local<v8::Object> value,
+ std::unique_ptr<base::Value>* out,
+ v8::Isolate* isolate) {
return false;
}
-bool V8ValueConverter::Strategy::FromV8Array(
- v8::Local<v8::Array> value,
- std::unique_ptr<base::Value>* out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback) {
+bool V8ValueConverter::Strategy::FromV8Array(v8::Local<v8::Array> value,
+ std::unique_ptr<base::Value>* out,
+ v8::Isolate* isolate) {
return false;
}
@@ -454,14 +450,8 @@ std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Array(
scope.reset(new v8::Context::Scope(val->CreationContext()));
if (strategy_) {
- // These base::Unretained's are safe, because Strategy::FromV8Value should
- // be synchronous, so this object can't be out of scope.
- V8ValueConverter::Strategy::FromV8ValueCallback callback =
- base::Bind(&V8ValueConverterImpl::FromV8ValueImpl,
- base::Unretained(this),
- base::Unretained(state));
std::unique_ptr<base::Value> out;
- if (strategy_->FromV8Array(val, &out, isolate, std::move(callback)))
+ if (strategy_->FromV8Array(val, &out, isolate))
return out;
}
@@ -537,14 +527,8 @@ std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Object(
scope.reset(new v8::Context::Scope(val->CreationContext()));
if (strategy_) {
- // These base::Unretained's are safe, because Strategy::FromV8Value should
- // be synchronous, so this object can't be out of scope.
- V8ValueConverter::Strategy::FromV8ValueCallback callback =
- base::Bind(&V8ValueConverterImpl::FromV8ValueImpl,
- base::Unretained(this),
- base::Unretained(state));
std::unique_ptr<base::Value> out;
- if (strategy_->FromV8Object(val, &out, isolate, std::move(callback)))
+ if (strategy_->FromV8Object(val, &out, isolate))
return out;
}
diff --git a/chromium/content/renderer/v8_value_converter_impl_unittest.cc b/chromium/content/renderer/v8_value_converter_impl_unittest.cc
index 2d3d67cca5f..694f5bfa45b 100644
--- a/chromium/content/renderer/v8_value_converter_impl_unittest.cc
+++ b/chromium/content/renderer/v8_value_converter_impl_unittest.cc
@@ -1084,15 +1084,13 @@ class V8ValueConverterOverridingStrategyForTesting
: reference_value_(NewReferenceValue()) {}
bool FromV8Object(v8::Local<v8::Object> value,
std::unique_ptr<base::Value>* out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback) override {
+ v8::Isolate* isolate) override {
*out = NewReferenceValue();
return true;
}
bool FromV8Array(v8::Local<v8::Array> value,
std::unique_ptr<base::Value>* out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback) override {
+ v8::Isolate* isolate) override {
*out = NewReferenceValue();
return true;
}
@@ -1173,14 +1171,12 @@ class V8ValueConverterBypassStrategyForTesting
public:
bool FromV8Object(v8::Local<v8::Object> value,
std::unique_ptr<base::Value>* out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback) override {
+ v8::Isolate* isolate) override {
return false;
}
bool FromV8Array(v8::Local<v8::Array> value,
std::unique_ptr<base::Value>* out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback) override {
+ v8::Isolate* isolate) override {
return false;
}
bool FromV8ArrayBuffer(v8::Local<v8::Object> value,
diff --git a/chromium/content/renderer/visual_state_browsertest.cc b/chromium/content/renderer/visual_state_browsertest.cc
index 3ad17d1b81e..bf81f601e73 100644
--- a/chromium/content/renderer/visual_state_browsertest.cc
+++ b/chromium/content/renderer/visual_state_browsertest.cc
@@ -4,6 +4,7 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/containers/flat_map.h"
#include "base/message_loop/message_loop_current.h"
#include "base/run_loop.h"
#include "content/public/browser/render_frame_host.h"
@@ -28,8 +29,8 @@ class CommitObserver : public RenderViewObserver {
void DidCommitCompositorFrame() override {
commit_count_++;
- for (base::Closure* closure : quit_closures_) {
- closure->Run();
+ for (const auto& pair : quit_closures_) {
+ pair.second.Run();
}
}
@@ -41,12 +42,11 @@ class CommitObserver : public RenderViewObserver {
void WaitForCommitNumber(int commit_number) {
if (commit_number > commit_count_) {
scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
- base::Closure quit_closure =
- base::Bind(&CommitObserver::QuitAfterCommit, base::Unretained(this),
- commit_number, runner);
- quit_closures_.insert(&quit_closure);
+ quit_closures_[commit_number] =
+ base::BindRepeating(&CommitObserver::QuitAfterCommit,
+ base::Unretained(this), commit_number, runner);
runner->Run();
- quit_closures_.erase(&quit_closure);
+ quit_closures_.erase(commit_number);
}
}
@@ -56,7 +56,7 @@ class CommitObserver : public RenderViewObserver {
// RenderViewObserver implementation.
void OnDestruct() override { delete this; }
- std::set<base::Closure*> quit_closures_;
+ base::flat_map<int, base::RepeatingClosure> quit_closures_;
int commit_count_;
};
@@ -109,12 +109,12 @@ IN_PROC_BROWSER_TEST_F(VisualStateTest, DISABLED_CallbackDoesNotDeadlock) {
// Wait for the commit corresponding to the load.
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&VisualStateTest::WaitForCommit, base::Unretained(this), &observer, 1));
// Try our best to check that there are no pending updates or commits.
PostTaskToInProcessRendererAndWait(
- base::Bind(&VisualStateTest::AssertIsIdle, base::Unretained(this)));
+ base::BindOnce(&VisualStateTest::AssertIsIdle, base::Unretained(this)));
// Insert a visual state callback.
shell()->web_contents()->GetMainFrame()->InsertVisualStateCallback(
@@ -122,7 +122,7 @@ IN_PROC_BROWSER_TEST_F(VisualStateTest, DISABLED_CallbackDoesNotDeadlock) {
base::Unretained(this)));
// Verify that the callback is invoked and a new commit completed.
- PostTaskToInProcessRendererAndWait(base::Bind(
+ PostTaskToInProcessRendererAndWait(base::BindOnce(
&VisualStateTest::WaitForCommit, base::Unretained(this), &observer, 2));
EXPECT_EQ(1, GetCallbackCount());
}
diff --git a/chromium/content/renderer/web_ui_extension.cc b/chromium/content/renderer/web_ui_extension.cc
index 5af8770399e..e39558faf3a 100644
--- a/chromium/content/renderer/web_ui_extension.cc
+++ b/chromium/content/renderer/web_ui_extension.cc
@@ -76,15 +76,15 @@ void WebUIExtension::Install(blink::WebLocalFrame* frame) {
v8::Local<v8::Object> chrome = GetOrCreateChromeObject(isolate, context);
chrome
->Set(context, gin::StringToSymbol(isolate, "send"),
- gin::CreateFunctionTemplate(isolate,
- base::Bind(&WebUIExtension::Send))
+ gin::CreateFunctionTemplate(
+ isolate, base::BindRepeating(&WebUIExtension::Send))
->GetFunction(context)
.ToLocalChecked())
.Check();
chrome
->Set(context, gin::StringToSymbol(isolate, "getVariableValue"),
gin::CreateFunctionTemplate(
- isolate, base::Bind(&WebUIExtension::GetVariableValue))
+ isolate, base::BindRepeating(&WebUIExtension::GetVariableValue))
->GetFunction(context)
.ToLocalChecked())
.Check();
diff --git a/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc b/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc
index b8282385f33..53468d41a5a 100644
--- a/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc
+++ b/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc
@@ -4,10 +4,15 @@
#include "content/renderer/webgraphicscontext3d_provider_impl.h"
+#include "base/command_line.h"
+#include "base/strings/string_number_conversions.h"
+#include "build/build_config.h"
#include "cc/paint/paint_image.h"
#include "cc/tiles/gpu_image_decode_cache.h"
#include "components/viz/common/gl_helper.h"
+#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/client/context_support.h"
+#include "gpu/config/gpu_feature_info.h"
#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/skia/include/gpu/GrContext.h"
@@ -53,6 +58,69 @@ const gpu::GpuFeatureInfo& WebGraphicsContext3DProviderImpl::GetGpuFeatureInfo()
return provider_->GetGpuFeatureInfo();
}
+const blink::WebglPreferences&
+WebGraphicsContext3DProviderImpl::GetWebglPreferences() const {
+ static bool initialized = false;
+ static blink::WebglPreferences prefs;
+ if (!initialized) {
+ initialized = true;
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ auto gpu_feature_info = GetGpuFeatureInfo();
+
+ if (gpu_feature_info.IsWorkaroundEnabled(MAX_MSAA_SAMPLE_COUNT_4)) {
+ prefs.msaa_sample_count = 4;
+ }
+ if (command_line->HasSwitch(switches::kWebglMSAASampleCount)) {
+ std::string sample_count =
+ command_line->GetSwitchValueASCII(switches::kWebglMSAASampleCount);
+ uint32_t count;
+ if (base::StringToUint(sample_count, &count)) {
+ prefs.msaa_sample_count = count;
+ }
+ }
+
+ if (command_line->HasSwitch(switches::kWebglAntialiasingMode)) {
+ std::string mode =
+ command_line->GetSwitchValueASCII(switches::kWebglAntialiasingMode);
+ if (mode == "none") {
+ prefs.anti_aliasing_mode = blink::kAntialiasingModeNone;
+ } else if (mode == "explicit") {
+ prefs.anti_aliasing_mode = blink::kAntialiasingModeMSAAExplicitResolve;
+ } else if (mode == "implicit") {
+ prefs.anti_aliasing_mode = blink::kAntialiasingModeMSAAImplicitResolve;
+ } else if (mode == "screenspace") {
+ prefs.anti_aliasing_mode =
+ blink::kAntialiasingModeScreenSpaceAntialiasing;
+ } else {
+ prefs.anti_aliasing_mode = blink::kAntialiasingModeUnspecified;
+ }
+ }
+
+ // Set default context limits for WebGL.
+#if defined(OS_ANDROID)
+ prefs.max_active_webgl_contexts = 8u;
+#else
+ prefs.max_active_webgl_contexts = 16u;
+#endif
+ prefs.max_active_webgl_contexts_on_worker = 4u;
+
+ if (command_line->HasSwitch(switches::kMaxActiveWebGLContexts)) {
+ std::string max_contexts =
+ command_line->GetSwitchValueASCII(switches::kMaxActiveWebGLContexts);
+ uint32_t max_val;
+ if (base::StringToUint(max_contexts, &max_val)) {
+ // It shouldn't be common for users to override this. If they do,
+ // just override both values.
+ prefs.max_active_webgl_contexts = max_val;
+ prefs.max_active_webgl_contexts_on_worker = max_val;
+ }
+ }
+ }
+
+ return prefs;
+}
+
viz::GLHelper* WebGraphicsContext3DProviderImpl::GetGLHelper() {
if (!gl_helper_) {
gl_helper_ = std::make_unique<viz::GLHelper>(provider_->ContextGL(),
@@ -77,11 +145,9 @@ void WebGraphicsContext3DProviderImpl::OnContextLost() {
}
cc::ImageDecodeCache* WebGraphicsContext3DProviderImpl::ImageDecodeCache(
- SkColorType color_type,
- sk_sp<SkColorSpace> color_space) {
+ SkColorType color_type) {
DCHECK(GetGrContext()->colorTypeSupportedAsImage(color_type));
- auto key = std::make_pair(color_type, color_space->hash());
- auto cache_iterator = image_decode_cache_map_.find(key);
+ auto cache_iterator = image_decode_cache_map_.find(color_type);
if (cache_iterator != image_decode_cache_map_.end())
return cache_iterator->second.get();
@@ -94,11 +160,11 @@ cc::ImageDecodeCache* WebGraphicsContext3DProviderImpl::ImageDecodeCache(
const bool use_transfer_cache = false;
auto insertion_result = image_decode_cache_map_.emplace(
- key,
+ color_type,
std::make_unique<cc::GpuImageDecodeCache>(
provider_.get(), use_transfer_cache, color_type, kMaxWorkingSetBytes,
provider_->ContextCapabilities().max_texture_size,
- cc::PaintImage::kDefaultGeneratorClientId, color_space));
+ cc::PaintImage::kDefaultGeneratorClientId));
DCHECK(insertion_result.second);
cache_iterator = insertion_result.first;
return cache_iterator->second.get();
diff --git a/chromium/content/renderer/webgraphicscontext3d_provider_impl.h b/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
index 354b16684c2..b6c629582d9 100644
--- a/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
+++ b/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
@@ -47,13 +47,12 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl
GrContext* GetGrContext() override;
const gpu::Capabilities& GetCapabilities() const override;
const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const override;
+ const blink::WebglPreferences& GetWebglPreferences() const override;
viz::GLHelper* GetGLHelper() override;
void SetLostContextCallback(base::RepeatingClosure) override;
void SetErrorMessageCallback(
base::RepeatingCallback<void(const char*, int32_t)>) override;
- cc::ImageDecodeCache* ImageDecodeCache(
- SkColorType color_type,
- sk_sp<SkColorSpace> color_space) override;
+ cc::ImageDecodeCache* ImageDecodeCache(SkColorType color_type) override;
gpu::SharedImageInterface* SharedImageInterface() override;
ws::ContextProviderCommandBuffer* context_provider() const {
@@ -67,8 +66,7 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl
scoped_refptr<ws::ContextProviderCommandBuffer> provider_;
std::unique_ptr<viz::GLHelper> gl_helper_;
base::RepeatingClosure context_lost_callback_;
- base::flat_map<std::pair<SkColorType, uint64_t>,
- std::unique_ptr<cc::ImageDecodeCache>>
+ base::flat_map<SkColorType, std::unique_ptr<cc::ImageDecodeCache>>
image_decode_cache_map_;
DISALLOW_COPY_AND_ASSIGN(WebGraphicsContext3DProviderImpl);
diff --git a/chromium/content/renderer/worker/application_cache_host_for_shared_worker.cc b/chromium/content/renderer/worker/application_cache_host_for_shared_worker.cc
deleted file mode 100644
index 2241b19a023..00000000000
--- a/chromium/content/renderer/worker/application_cache_host_for_shared_worker.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/worker/application_cache_host_for_shared_worker.h"
-
-namespace content {
-
-ApplicationCacheHostForSharedWorker::ApplicationCacheHostForSharedWorker(
- blink::WebApplicationCacheHostClient* client,
- int appcache_host_id,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : WebApplicationCacheHostImpl(client,
- appcache_host_id,
- MSG_ROUTING_NONE,
- std::move(task_runner)) {}
-
-ApplicationCacheHostForSharedWorker::~ApplicationCacheHostForSharedWorker() =
- default;
-
-void ApplicationCacheHostForSharedWorker::WillStartMainResourceRequest(
- const blink::WebURL& url,
- const blink::WebString& method,
- const WebApplicationCacheHost* spawning_host) {}
-
-void ApplicationCacheHostForSharedWorker::DidReceiveResponseForMainResource(
- const blink::WebURLResponse&) {}
-
-void ApplicationCacheHostForSharedWorker::SelectCacheWithoutManifest() {}
-
-bool ApplicationCacheHostForSharedWorker::SelectCacheWithManifest(
- const blink::WebURL& manifestURL) {
- return true;
-}
-
-void ApplicationCacheHostForSharedWorker::LogMessage(
- blink::mojom::ConsoleMessageLevel log_level,
- const std::string& message) {}
-
-void ApplicationCacheHostForSharedWorker::SetSubresourceFactory(
- network::mojom::URLLoaderFactoryPtr url_loader_factory) {}
-
-} // namespace content
diff --git a/chromium/content/renderer/worker/application_cache_host_for_shared_worker.h b/chromium/content/renderer/worker/application_cache_host_for_shared_worker.h
deleted file mode 100644
index 19ba479026e..00000000000
--- a/chromium/content/renderer/worker/application_cache_host_for_shared_worker.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_WORKER_APPLICATION_CACHE_HOST_FOR_SHARED_WORKER_H_
-#define CONTENT_RENDERER_WORKER_APPLICATION_CACHE_HOST_FOR_SHARED_WORKER_H_
-
-#include "content/renderer/appcache/web_application_cache_host_impl.h"
-
-namespace content {
-
-class ApplicationCacheHostForSharedWorker final
- : public WebApplicationCacheHostImpl {
- public:
- ApplicationCacheHostForSharedWorker(
- blink::WebApplicationCacheHostClient* client,
- int appcache_host_id,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- ~ApplicationCacheHostForSharedWorker() override;
-
- // Main resource loading is different for workers. The main resource is
- // loaded by the worker using WorkerClassicScriptLoader.
- // These overrides are stubbed out.
- void WillStartMainResourceRequest(
- const blink::WebURL& url,
- const blink::WebString& method,
- const WebApplicationCacheHost* spawning_host) override;
- void DidReceiveResponseForMainResource(const blink::WebURLResponse&) override;
-
- // Cache selection is also different for workers. We know at construction
- // time what cache to select and do so then.
- // These overrides are stubbed out.
- void SelectCacheWithoutManifest() override;
- bool SelectCacheWithManifest(const blink::WebURL& manifestURL) override;
-
- // blink::mojom::AppCacheFrontend:
- void LogMessage(blink::mojom::ConsoleMessageLevel log_level,
- const std::string& message) override;
- void SetSubresourceFactory(
- network::mojom::URLLoaderFactoryPtr url_loader_factory) override;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_WORKER_APPLICATION_CACHE_HOST_FOR_SHARED_WORKER_H_
diff --git a/chromium/content/renderer/worker/embedded_shared_worker_stub.cc b/chromium/content/renderer/worker/embedded_shared_worker_stub.cc
index 6899bc038c6..4a341980ea3 100644
--- a/chromium/content/renderer/worker/embedded_shared_worker_stub.cc
+++ b/chromium/content/renderer/worker/embedded_shared_worker_stub.cc
@@ -20,7 +20,6 @@
#include "content/renderer/loader/web_worker_fetch_context_impl.h"
#include "content/renderer/renderer_blink_platform_impl.h"
#include "content/renderer/service_worker/service_worker_provider_context.h"
-#include "content/renderer/worker/application_cache_host_for_shared_worker.h"
#include "content/renderer/worker/service_worker_network_provider_for_worker.h"
#include "ipc/ipc_message_macros.h"
#include "services/network/public/cpp/features.h"
@@ -38,6 +37,7 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_security_origin.h"
+#include "third_party/blink/public/web/web_application_cache_host.h"
#include "third_party/blink/public/web/web_shared_worker.h"
#include "third_party/blink/public/web/web_shared_worker_client.h"
#include "url/origin.h"
@@ -53,9 +53,8 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- int appcache_host_id,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ const base::UnguessableToken& appcache_host_id,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factory_bundle_info,
@@ -74,7 +73,7 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
// The ID of the precreated AppCacheHost can be valid only when the
// NetworkService is enabled.
DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService) ||
- appcache_host_id == blink::mojom::kAppCacheNoHostId);
+ appcache_host_id.is_empty());
if (main_script_load_params) {
response_override_ =
@@ -174,23 +173,28 @@ void EmbeddedSharedWorkerStub::WorkerContextDestroyed() {
delete this;
}
-void EmbeddedSharedWorkerStub::SelectAppCacheID(int64_t app_cache_id) {
+void EmbeddedSharedWorkerStub::SelectAppCacheID(
+ int64_t app_cache_id,
+ base::OnceClosure completion_callback) {
if (app_cache_host_) {
// app_cache_host_ could become stale as it's owned by blink's
// DocumentLoader. This method is assumed to be called while it's valid.
- app_cache_host_->SelectCacheForSharedWorker(app_cache_id);
+ app_cache_host_->SelectCacheForSharedWorker(app_cache_id,
+ std::move(completion_callback));
+ } else {
+ std::move(completion_callback).Run();
}
}
std::unique_ptr<blink::WebApplicationCacheHost>
EmbeddedSharedWorkerStub::CreateApplicationCacheHost(
blink::WebApplicationCacheHostClient* client) {
- std::unique_ptr<WebApplicationCacheHostImpl> host =
- std::make_unique<ApplicationCacheHostForSharedWorker>(
+ auto host = blink::WebApplicationCacheHost::
+ CreateWebApplicationCacheHostForSharedWorker(
client, appcache_host_id_,
impl_->GetTaskRunner(blink::TaskType::kNetworking));
app_cache_host_ = host.get();
- return std::move(host);
+ return host;
}
std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
diff --git a/chromium/content/renderer/worker/embedded_shared_worker_stub.h b/chromium/content/renderer/worker/embedded_shared_worker_stub.h
index 913ff0dd647..13794cb7ade 100644
--- a/chromium/content/renderer/worker/embedded_shared_worker_stub.h
+++ b/chromium/content/renderer/worker/embedded_shared_worker_stub.h
@@ -32,7 +32,6 @@
namespace blink {
class WebApplicationCacheHost;
-class WebApplicationCacheHostClient;
class WebSharedWorker;
} // namespace blink
@@ -44,7 +43,6 @@ class URLLoaderFactoryBundleInfo;
namespace content {
class ChildURLLoaderFactoryBundle;
-class WebApplicationCacheHostImpl;
struct NavigationResponseOverrideParameters;
// A stub class to receive IPC from browser process and talk to
@@ -65,9 +63,8 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient,
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- int appcache_host_id,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ const base::UnguessableToken& appcache_host_id,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factory_bundle_info,
@@ -85,7 +82,7 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient,
void WorkerScriptLoaded() override;
void WorkerScriptLoadFailed() override;
void WorkerScriptEvaluated(bool success) override;
- void SelectAppCacheID(int64_t) override;
+ void SelectAppCacheID(int64_t, base::OnceClosure) override;
std::unique_ptr<blink::WebApplicationCacheHost> CreateApplicationCacheHost(
blink::WebApplicationCacheHostClient*) override;
std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
@@ -124,8 +121,8 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient,
std::pair<int /* connection_request_id */, blink::MessagePortChannel>;
std::vector<PendingChannel> pending_channels_;
- const int appcache_host_id_;
- WebApplicationCacheHostImpl* app_cache_host_ = nullptr; // Not owned.
+ const base::UnguessableToken appcache_host_id_;
+ blink::WebApplicationCacheHost* app_cache_host_ = nullptr; // Not owned.
// The info needed to connect to the ServiceWorkerProviderHost on the browser.
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
@@ -133,7 +130,7 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient,
// NetworkService: The URLLoaderFactory used for loading the shared worker
// main script.
- network::mojom::URLLoaderFactoryAssociatedPtrInfo main_script_loader_factory_;
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory_;
// NetworkService:
blink::mojom::ControllerServiceWorkerInfoPtr controller_info_;
diff --git a/chromium/content/renderer/worker/service_worker_network_provider_for_worker.cc b/chromium/content/renderer/worker/service_worker_network_provider_for_worker.cc
index 631983f6f3b..c96e50a56fb 100644
--- a/chromium/content/renderer/worker/service_worker_network_provider_for_worker.cc
+++ b/chromium/content/renderer/worker/service_worker_network_provider_for_worker.cc
@@ -24,8 +24,7 @@ namespace content {
std::unique_ptr<ServiceWorkerNetworkProviderForWorker>
ServiceWorkerNetworkProviderForWorker::Create(
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_info,
+ network::mojom::URLLoaderFactoryPtr script_loader_factory,
blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory,
bool is_secure_context,
@@ -37,10 +36,9 @@ ServiceWorkerNetworkProviderForWorker::Create(
blink::mojom::ServiceWorkerProviderType::kForSharedWorker,
std::move(info->client_request), std::move(info->host_ptr_info),
std::move(controller_info), std::move(fallback_loader_factory));
- if (script_loader_factory_info.is_valid()) {
- provider->script_loader_factory_.Bind(
- std::move(script_loader_factory_info));
- }
+ if (script_loader_factory)
+ provider->script_loader_factory_ = std::move(script_loader_factory);
+
return provider;
}
diff --git a/chromium/content/renderer/worker/service_worker_network_provider_for_worker.h b/chromium/content/renderer/worker/service_worker_network_provider_for_worker.h
index 72cf03800dc..b9f75ad75d6 100644
--- a/chromium/content/renderer/worker/service_worker_network_provider_for_worker.h
+++ b/chromium/content/renderer/worker/service_worker_network_provider_for_worker.h
@@ -28,7 +28,7 @@ class ServiceWorkerNetworkProviderForWorker final
public:
// Creates a new instance.
// - |info|: provider info from the browser
- // - |script_loader_factory_info|: the factory for loading the worker's
+ // - |script_loader_factory|: the factory for loading the worker's
// scripts
// - |controller_info|: info about controller service worker
// - |fallback_loader_factory|: the factory to use when a service worker falls
@@ -38,8 +38,7 @@ class ServiceWorkerNetworkProviderForWorker final
// - |response_override|: the main script response
static std::unique_ptr<ServiceWorkerNetworkProviderForWorker> Create(
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_info,
+ network::mojom::URLLoaderFactoryPtr script_loader_factory,
blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory,
bool is_secure_context,
@@ -72,7 +71,7 @@ class ServiceWorkerNetworkProviderForWorker final
scoped_refptr<ServiceWorkerProviderContext> context_;
// The URL loader factory for loading the worker's scripts.
- network::mojom::URLLoaderFactoryAssociatedPtr script_loader_factory_;
+ network::mojom::URLLoaderFactoryPtr script_loader_factory_;
};
} // namespace content
diff --git a/chromium/content/renderer/worker/shared_worker_factory_impl.cc b/chromium/content/renderer/worker/shared_worker_factory_impl.cc
index 87fd36e2793..34ddb6949ec 100644
--- a/chromium/content/renderer/worker/shared_worker_factory_impl.cc
+++ b/chromium/content/renderer/worker/shared_worker_factory_impl.cc
@@ -30,9 +30,8 @@ void SharedWorkerFactoryImpl::CreateSharedWorker(
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- int appcache_host_id,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ const base::Optional<base::UnguessableToken>& appcache_host_id,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
@@ -45,8 +44,8 @@ void SharedWorkerFactoryImpl::CreateSharedWorker(
std::move(info), pause_on_start, devtools_worker_token,
*renderer_preferences, std::move(preference_watcher_request),
std::move(content_settings), std::move(service_worker_provider_info),
- appcache_host_id, std::move(main_script_loader_factory),
- std::move(main_script_load_params),
+ appcache_host_id.value_or(base::UnguessableToken()),
+ std::move(main_script_loader_factory), std::move(main_script_load_params),
std::move(subresource_loader_factories), std::move(controller_info),
std::move(host), std::move(request), std::move(interface_provider));
}
diff --git a/chromium/content/renderer/worker/shared_worker_factory_impl.h b/chromium/content/renderer/worker/shared_worker_factory_impl.h
index 41760c7908d..681001c77ad 100644
--- a/chromium/content/renderer/worker/shared_worker_factory_impl.h
+++ b/chromium/content/renderer/worker/shared_worker_factory_impl.h
@@ -33,9 +33,8 @@ class SharedWorkerFactoryImpl : public blink::mojom::SharedWorkerFactory {
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
service_worker_provider_info,
- int appcache_host_id,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- main_script_loader_factory,
+ const base::Optional<base::UnguessableToken>& appcache_host_id,
+ network::mojom::URLLoaderFactoryPtr main_script_loader_factory,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factories,
diff --git a/chromium/content/renderer/worker/worker_thread_registry.cc b/chromium/content/renderer/worker/worker_thread_registry.cc
index fcf2bee5d52..97dae12dca3 100644
--- a/chromium/content/renderer/worker/worker_thread_registry.cc
+++ b/chromium/content/renderer/worker/worker_thread_registry.cc
@@ -80,7 +80,8 @@ void WorkerThread::RemoveObserver(Observer* observer) {
WorkerThreadRegistry::WorkerThreadRegistry()
: task_runner_for_dead_worker_(new DoNothingTaskRunner()) {}
-int WorkerThreadRegistry::PostTaskToAllThreads(base::Closure closure) {
+int WorkerThreadRegistry::PostTaskToAllThreads(
+ const base::RepeatingClosure& closure) {
base::AutoLock locker(task_runner_map_lock_);
for (const auto& it : task_runner_map_)
it.second->PostTask(FROM_HERE, closure);
diff --git a/chromium/content/renderer/worker/worker_thread_registry.h b/chromium/content/renderer/worker/worker_thread_registry.h
index 4500691ba33..3b38c0d9152 100644
--- a/chromium/content/renderer/worker/worker_thread_registry.h
+++ b/chromium/content/renderer/worker/worker_thread_registry.h
@@ -24,7 +24,7 @@ class CONTENT_EXPORT WorkerThreadRegistry {
public:
WorkerThreadRegistry();
- int PostTaskToAllThreads(base::Closure task);
+ int PostTaskToAllThreads(const base::RepeatingClosure& task);
static WorkerThreadRegistry* Instance();
void DidStartCurrentWorkerThread();
diff --git a/chromium/content/shell/BUILD.gn b/chromium/content/shell/BUILD.gn
index 4e25263a74b..4be42018164 100644
--- a/chromium/content/shell/BUILD.gn
+++ b/chromium/content/shell/BUILD.gn
@@ -18,6 +18,7 @@ if (is_android) {
} else if (is_mac) {
import("//build/config/mac/rules.gni")
import("//build/mac/tweak_info_plist.gni")
+ import("//content/public/app/mac_helpers.gni")
import("//third_party/icu/config.gni")
import("//ui/gl/features.gni")
import("//v8/gni/v8.gni")
@@ -116,8 +117,6 @@ jumbo_static_library("content_shell_lib") {
"browser/shell_application_mac.mm",
"browser/shell_browser_context.cc",
"browser/shell_browser_context.h",
- "browser/shell_browser_main.cc",
- "browser/shell_browser_main.h",
"browser/shell_browser_main_parts.cc",
"browser/shell_browser_main_parts.h",
"browser/shell_browser_main_parts_mac.mm",
@@ -136,9 +135,6 @@ jumbo_static_library("content_shell_lib") {
"browser/shell_javascript_dialog_manager.cc",
"browser/shell_javascript_dialog_manager.h",
"browser/shell_javascript_dialog_win.cc",
- "browser/shell_login_dialog.cc",
- "browser/shell_login_dialog.h",
- "browser/shell_login_dialog_mac.mm",
"browser/shell_mac.mm",
"browser/shell_net_log.cc",
"browser/shell_net_log.h",
@@ -166,6 +162,10 @@ jumbo_static_library("content_shell_lib") {
"browser/web_test/devtools_protocol_test_bindings.h",
"browser/web_test/fake_bluetooth_chooser.cc",
"browser/web_test/fake_bluetooth_chooser.h",
+ "browser/web_test/fake_bluetooth_chooser_factory.cc",
+ "browser/web_test/fake_bluetooth_chooser_factory.h",
+ "browser/web_test/fake_bluetooth_scanning_prompt.cc",
+ "browser/web_test/fake_bluetooth_scanning_prompt.h",
"browser/web_test/leak_detector.cc",
"browser/web_test/leak_detector.h",
"browser/web_test/mojo_web_test_helper.cc",
@@ -261,6 +261,9 @@ jumbo_static_library("content_shell_lib") {
# #include'ed by renderer/web_test/blink_test_runner.h
":mojo_bindings",
+ # The generated mojom JS bindings are used by web tests.
+ ":mojo_bindings_js",
+
# This exposes all public content APIs.
"//content/public/app:both",
"//content/public/browser",
@@ -289,7 +292,6 @@ jumbo_static_library("content_shell_lib") {
"//components/download/public/background_service:public",
"//components/download/public/common:public",
"//components/keyed_service/content",
- "//components/keyed_service/core:test_support",
"//components/network_session_configurator/browser",
"//components/plugins/renderer",
"//components/url_formatter",
@@ -319,7 +321,7 @@ jumbo_static_library("content_shell_lib") {
"//net:test_support",
"//ppapi/buildflags",
"//sandbox",
- "//services/device/public/cpp/test:test_support",
+ "//services/device/public/cpp:test_support",
"//services/device/public/mojom",
"//services/network/public/cpp",
"//services/service_manager/embedder:embedder_result_codes",
@@ -403,10 +405,6 @@ jumbo_static_library("content_shell_lib") {
}
if (is_android) {
- sources += [
- "browser/web_test/scoped_android_configuration.cc",
- "browser/web_test/scoped_android_configuration.h",
- ]
deps += [
"//base/test:test_support",
"//components/embedder_support/android:view",
@@ -456,9 +454,6 @@ jumbo_static_library("content_shell_lib") {
if (is_chromeos) {
deps += [
"//chromeos/dbus",
- "//services/ws/test_ws:lib",
- "//services/ws/test_ws:manifest",
- "//services/ws/test_ws:mojom",
"//ui/wm:test_support",
]
}
@@ -659,27 +654,6 @@ if (is_android) {
}
if (is_mac) {
- bundle_data("content_shell_framework_helpers") {
- testonly = true
- sources = [
- "$root_out_dir/chrome_crashpad_handler",
- ]
- outputs = [
- "{{bundle_contents_dir}}/Helpers/{{source_file_part}}",
- ]
- public_deps = [
- "//components/crash/content/app:chrome_crashpad_handler",
- ]
- }
-
- mac_xib_bundle_data("content_shell_framework_xibs") {
- sources = [
- "app/English.lproj/HttpAuth.xib",
- "app/English.lproj/MainMenu.xib",
- ]
- output_path = "{{bundle_resources_dir}}/English.lproj"
- }
-
bundle_data("content_shell_framework_resources") {
testonly = true
sources = [
@@ -735,6 +709,25 @@ if (is_mac) {
content_shell_framework_name = "$content_shell_product_name Framework"
content_shell_helper_name = "$content_shell_product_name Helper"
+ bundle_data("content_shell_framework_helpers") {
+ testonly = true
+ sources = [
+ "$root_out_dir/chrome_crashpad_handler",
+ ]
+ outputs = [
+ "{{bundle_contents_dir}}/Helpers/{{source_file_part}}",
+ ]
+ public_deps = [
+ "//components/crash/content/app:chrome_crashpad_handler",
+ ]
+ foreach(helper_params, content_mac_helpers) {
+ sources += [
+ "$root_out_dir/${content_shell_helper_name}${helper_params[2]}.app",
+ ]
+ public_deps += [ ":content_shell_helper_app_${helper_params[0]}" ]
+ }
+ }
+
tweak_info_plist("content_shell_framework_plist") {
testonly = true
info_plist = "app/framework-Info.plist"
@@ -774,7 +767,6 @@ if (is_mac) {
":content_shell_angle_library",
":content_shell_framework_helpers",
":content_shell_framework_resources",
- ":content_shell_framework_xibs",
":content_shell_swiftshader_library",
"//third_party/icu:icudata",
]
@@ -817,40 +809,61 @@ if (is_mac) {
]
}
- mac_app_bundle("content_shell_helper_app") {
- testonly = true
- output_name = content_shell_helper_name
- sources = [
- "app/shell_main_mac.cc",
- ]
- defines = [
- "HELPER_EXECUTABLE",
- "SHELL_PRODUCT_NAME=\"$content_shell_product_name\"",
- ]
- deps = [
- "//sandbox/mac:seatbelt",
- ]
- ldflags = [
- # The helper is in Content Shell.app/Contents/Frameworks/Content Shell Helper.app/Contents/MacOS/
- # so set rpath up to the base.
- "-rpath",
- "@executable_path/../../../../../..",
- ]
- info_plist_target = ":content_shell_helper_plist"
+ template("content_shell_helper_app") {
+ mac_app_bundle(target_name) {
+ assert(defined(invoker.helper_name_suffix))
+ assert(defined(invoker.helper_bundle_id_suffix))
+
+ testonly = true
+
+ output_name = content_shell_helper_name + invoker.helper_name_suffix
+
+ sources = [
+ "app/shell_main_mac.cc",
+ ]
+ defines = [
+ "HELPER_EXECUTABLE",
+ "SHELL_PRODUCT_NAME=\"$content_shell_product_name\"",
+ ]
+ extra_substitutions = [
+ "CONTENT_SHELL_HELPER_SUFFIX=${invoker.helper_name_suffix}",
+ "CONTENT_SHELL_HELPER_BUNDLE_ID_SUFFIX=${invoker.helper_bundle_id_suffix}",
+ ]
+ deps = [
+ "//sandbox/mac:seatbelt",
+ ]
+ ldflags = [
+ # The helper is in Content Shell.app/Contents/Frameworks/
+ # Content Shell Framework.framework/Versions/C/Helpers/
+ # Content Shell Helper.app/Contents/MacOS/
+ # so set rpath up to the base.
+ "-rpath",
+ "@executable_path/../../../../../../../../../..",
+ ]
+ info_plist_target = ":content_shell_helper_plist"
+ }
+ }
+
+ foreach(helper_params, content_mac_helpers) {
+ _helper_target = helper_params[0]
+ _helper_bundle_id = helper_params[1]
+ _helper_suffix = helper_params[2]
+ content_shell_helper_app("content_shell_helper_app_${_helper_target}") {
+ helper_name_suffix = _helper_suffix
+ helper_bundle_id_suffix = _helper_bundle_id
+ }
}
bundle_data("content_shell_framework_bundle_data") {
testonly = true
sources = [
"$root_out_dir/$content_shell_framework_name.framework",
- "$root_out_dir/$content_shell_helper_name.app",
]
outputs = [
"{{bundle_contents_dir}}/Frameworks/{{source_file_part}}",
]
public_deps = [
":content_shell_framework",
- ":content_shell_helper_app",
]
}
@@ -923,6 +936,7 @@ mojom("mojo_bindings") {
"//skia/public/interfaces",
"//ui/gfx/geometry/mojo",
"//url/mojom:url_mojom_gurl",
+ "//url/mojom:url_mojom_origin",
]
}
@@ -947,18 +961,18 @@ group("content_shell_crash_test") {
if (is_win) {
data_deps += [ "//build/win:copy_cdb_to_output" ]
}
- if (is_posix && !is_android) {
+ if (is_posix) {
data_deps += [
- "//third_party/breakpad:dump_syms($host_toolchain)",
- "//third_party/breakpad:minidump_stackwalk($host_toolchain)",
+ "//third_party/breakpad:dump_syms",
+ "//third_party/breakpad:minidump_stackwalk",
]
}
if (is_android) {
data_deps += [
- "//third_party/breakpad:dump_syms",
+ "//build/android:devil_chromium_py",
+ "//build/android:test_runner_py",
"//third_party/breakpad:microdump_stackwalk",
"//third_party/breakpad:minidump_dump",
- "//third_party/breakpad:minidump_stackwalk",
"//third_party/breakpad:symupload",
"//tools/android/forwarder2",
]
diff --git a/chromium/content/shell/common/shell_content_client.cc b/chromium/content/shell/common/shell_content_client.cc
index c71325769b0..013978eca93 100644
--- a/chromium/content/shell/common/shell_content_client.cc
+++ b/chromium/content/shell/common/shell_content_client.cc
@@ -70,6 +70,10 @@ base::RefCountedMemory* ShellContentClient::GetDataResourceBytes(
resource_id);
}
+bool ShellContentClient::IsDataResourceGzipped(int resource_id) const {
+ return ui::ResourceBundle::GetSharedInstance().IsGzipped(resource_id);
+}
+
gfx::Image& ShellContentClient::GetNativeImageNamed(int resource_id) const {
return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
resource_id);
diff --git a/chromium/content/shell/common/shell_content_client.h b/chromium/content/shell/common/shell_content_client.h
index 3987340c1ce..f56224a5f9f 100644
--- a/chromium/content/shell/common/shell_content_client.h
+++ b/chromium/content/shell/common/shell_content_client.h
@@ -25,6 +25,7 @@ class ShellContentClient : public ContentClient {
ui::ScaleFactor scale_factor) const override;
base::RefCountedMemory* GetDataResourceBytes(
int resource_id) const override;
+ bool IsDataResourceGzipped(int resource_id) const override;
gfx::Image& GetNativeImageNamed(int resource_id) const override;
base::DictionaryValue GetNetLogConstants() const override;
blink::OriginTrialPolicy* GetOriginTrialPolicy() override;
diff --git a/chromium/content/shell/common/web_test/fake_bluetooth_chooser.mojom b/chromium/content/shell/common/web_test/fake_bluetooth_chooser.mojom
index d1b595816b2..a093ca91358 100644
--- a/chromium/content/shell/common/web_test/fake_bluetooth_chooser.mojom
+++ b/chromium/content/shell/common/web_test/fake_bluetooth_chooser.mojom
@@ -4,6 +4,8 @@
module content.mojom;
+import "url/mojom/origin.mojom";
+
// This interface is being developed to support Web Platform Tests for Web
// Bluetooth.
// https://docs.google.com/document/d/1Nhv_oVDCodd1pEH_jj9k8gF4rPGb_84VYaZ9IG8M_WY
@@ -24,34 +26,35 @@ module content.mojom;
// Indicates the types of Bluetooth chooser events.
enum ChooserEventType {
CHOOSER_OPENED,
- SCAN_STARTED,
- DEVICE_UPDATE,
+ CHOOSER_CLOSED,
ADAPTER_REMOVED,
ADAPTER_DISABLED,
ADAPTER_ENABLED,
DISCOVERY_FAILED_TO_START,
DISCOVERING,
DISCOVERY_IDLE,
- ADD_DEVICE,
+ ADD_OR_UPDATE_DEVICE,
};
// FakeBluetoothChooser allows clients to control the global state of the
// Bluetooth chooser during a web test.
interface FakeBluetoothChooser {
- // Waits until at least |num_of_events| have been recorded before returning
- // |num_of_events| FakeBluetoothChooserEvents.
- WaitForEvents(
- uint32 num_of_events) => (array<FakeBluetoothChooserEvent> events);
-
// Simulates a user selecting the given |peripheral_address| in the Bluetooth
// chooser.
- SelectPeripheral(string peripheral_address) => ();
+ SelectPeripheral(string peripheral_address);
// Calls the event handler function with the CANCELLED event.
- Cancel() => ();
+ Cancel();
// Calls the event handler function with the RESCAN event.
- Rescan() => ();
+ Rescan();
+};
+
+// FakeBluetoothChooserFactory ensures that FakeBluetoothChoosers are created
+// with an associated FakeBluetoothChooserClient.
+interface FakeBluetoothChooserFactory {
+ CreateFakeBluetoothChooser(FakeBluetoothChooser& fake_chooser,
+ associated FakeBluetoothChooserClient client);
};
// FakeBluetoothChooserEvent describes the type of chooser event that has been
@@ -61,8 +64,13 @@ struct FakeBluetoothChooserEvent {
// Describes the origin the chooser is currently displaying.
// This field will be used by the |CHOOSER_OPENED| event type.
- string? origin;
+ url.mojom.Origin? origin;
// Describes the MAC address of the Bluetooth device.
string? peripheral_address;
};
+
+// Classes that implement this interface will be notified of chooser events.
+interface FakeBluetoothChooserClient {
+ OnEvent(FakeBluetoothChooserEvent event);
+};
diff --git a/chromium/content/shell/common/web_test/web_test_switches.cc b/chromium/content/shell/common/web_test/web_test_switches.cc
index f585d2de381..9f10351a071 100644
--- a/chromium/content/shell/common/web_test/web_test_switches.cc
+++ b/chromium/content/shell/common/web_test/web_test_switches.cc
@@ -9,17 +9,6 @@ namespace switches {
// Allow access to external pages during web tests.
const char kAllowExternalPages[] = "allow-external-pages";
-#if defined(OS_ANDROID)
-// Redirect stderr to the given port. Only supported on Android.
-const char kAndroidStderrPort[] = "android-stderr-port";
-
-// Redirect stdin to the given port. Only supported on Android.
-const char kAndroidStdinPort[] = "android-stdin-port";
-
-// Redirect stdout to the given port. Only supported on Android.
-const char kAndroidStdoutPort[] = "android-stdout-port";
-#endif // defined(OS_ANDROID)
-
// When specified to "enable-leak-detection" command-line option,
// causes the leak detector to cause immediate crash when found leak.
const char kCrashOnFailure[] = "crash-on-failure";
diff --git a/chromium/content/shell/common/web_test/web_test_switches.h b/chromium/content/shell/common/web_test/web_test_switches.h
index abb8312d954..637305f883a 100644
--- a/chromium/content/shell/common/web_test/web_test_switches.h
+++ b/chromium/content/shell/common/web_test/web_test_switches.h
@@ -15,11 +15,6 @@
namespace switches {
extern const char kAllowExternalPages[];
-#if defined(OS_ANDROID)
-extern const char kAndroidStderrPort[];
-extern const char kAndroidStdinPort[];
-extern const char kAndroidStdoutPort[];
-#endif // defined(OS_ANDROID)
extern const char kCrashOnFailure[];
extern const char kCustomDevToolsFrontend[];
extern const char kDebugDevTools[];
diff --git a/chromium/content/test/BUILD.gn b/chromium/content/test/BUILD.gn
index 227fc59f387..08d057ccb17 100644
--- a/chromium/content/test/BUILD.gn
+++ b/chromium/content/test/BUILD.gn
@@ -48,12 +48,12 @@ jumbo_static_library("test_support") {
"../browser/background_fetch/background_fetch_test_service_worker.h",
"../browser/background_fetch/mock_background_fetch_delegate.cc",
"../browser/background_fetch/mock_background_fetch_delegate.h",
- "../browser/fileapi/file_system_chooser_test_helpers.cc",
- "../browser/fileapi/file_system_chooser_test_helpers.h",
"../browser/media/session/mock_media_session_player_observer.cc",
"../browser/media/session/mock_media_session_player_observer.h",
"../browser/media/session/mock_media_session_service_impl.cc",
"../browser/media/session/mock_media_session_service_impl.h",
+ "../browser/native_file_system/file_system_chooser_test_helpers.cc",
+ "../browser/native_file_system/file_system_chooser_test_helpers.h",
"../browser/renderer_host/input/mock_input_router.cc",
"../browser/renderer_host/input/mock_input_router.h",
"../browser/renderer_host/mock_render_widget_host.cc",
@@ -70,6 +70,7 @@ jumbo_static_library("test_support") {
"../browser/service_worker/test_service_worker_observer.h",
"../browser/web_package/mock_signed_exchange_handler.cc",
"../browser/web_package/mock_signed_exchange_handler.h",
+ "../browser/web_package/signed_exchange_test_utils.h",
"../public/test/audio_service_test_helper.cc",
"../public/test/audio_service_test_helper.h",
"../public/test/background_sync_test_util.cc",
@@ -233,6 +234,8 @@ jumbo_static_library("test_support") {
"fake_compositor_dependencies.h",
"fake_leveldb_database.cc",
"fake_leveldb_database.h",
+ "fake_network_url_loader_factory.cc",
+ "fake_network_url_loader_factory.h",
"fake_plugin_service.cc",
"fake_plugin_service.h",
"fake_renderer_compositor_frame_sink.cc",
@@ -750,6 +753,8 @@ test("content_browsertests") {
sources = [
"../app/mojo/mojo_browsertest.cc",
"../browser/accessibility/accessibility_action_browsertest.cc",
+ "../browser/accessibility/accessibility_content_browsertest.cc",
+ "../browser/accessibility/accessibility_content_browsertest.h",
"../browser/accessibility/accessibility_ipc_error_browsertest.cc",
"../browser/accessibility/accessibility_mode_browsertest.cc",
"../browser/accessibility/aom_browsertest.cc",
@@ -795,15 +800,11 @@ test("content_browsertests") {
"../browser/download/mhtml_generation_browsertest.cc",
"../browser/download/save_package_browsertest.cc",
"../browser/fileapi/file_system_browsertest.cc",
- "../browser/frame_host/back_forward_cache_metrics_browsertest.cc",
-
- # These tests have incorrect threading (https://crbug.com/860547).
- #"../browser/fileapi/file_system_url_loader_factory_browsertest.cc",
-
- "../browser/fileapi/file_system_chooser_browsertest.cc",
+ "../browser/fileapi/file_system_url_loader_factory_browsertest.cc",
"../browser/fileapi/fileapi_browsertest.cc",
"../browser/find_request_manager_browsertest.cc",
"../browser/font_unique_name_lookup/font_unique_name_browsertest.cc",
+ "../browser/frame_host/back_forward_cache_metrics_browsertest.cc",
"../browser/frame_host/blocked_scheme_navigation_browsertest.cc",
"../browser/frame_host/frame_tree_browsertest.cc",
"../browser/frame_host/interstitial_page_impl_browsertest.cc",
@@ -818,6 +819,7 @@ test("content_browsertests") {
"../browser/generic_sensor/generic_sensor_browsertest.cc",
"../browser/gpu/gpu_ipc_browsertests.cc",
"../browser/gpu/in_process_gpu_thread_browsertests.cc",
+ "../browser/idle/idle_browsertest.cc",
"../browser/indexed_db/indexed_db_browsertest.cc",
"../browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc",
"../browser/indexed_db/mock_browsertest_indexed_db_class_factory.h",
@@ -830,6 +832,8 @@ test("content_browsertests") {
"../browser/loader/cross_site_document_blocking_browsertest.cc",
"../browser/loader/loader_browsertest.cc",
"../browser/loader/prefetch_browsertest.cc",
+ "../browser/loader/prefetch_browsertest_base.cc",
+ "../browser/loader/prefetch_browsertest_base.h",
"../browser/loader/reload_cache_control_browsertest.cc",
"../browser/loader/resource_scheduler_browsertest.cc",
"../browser/manifest/manifest_browsertest.cc",
@@ -852,6 +856,7 @@ test("content_browsertests") {
"../browser/media/webaudio/audio_context_manager_browsertest.cc",
"../browser/message_port_provider_browsertest.cc",
"../browser/mojo_sandbox_browsertest.cc",
+ "../browser/native_file_system/file_system_chooser_browsertest.cc",
"../browser/navigation_browsertest.cc",
"../browser/net/accept_header_browsertest.cc",
"../browser/net/net_command_line_flags_browsertest.cc",
@@ -859,6 +864,7 @@ test("content_browsertests") {
"../browser/network_service_browsertest.cc",
"../browser/network_service_restart_browsertest.cc",
"../browser/oop_browsertest.cc",
+ "../browser/origin_trials/origin_trials_browsertest.cc",
"../browser/payments/payment_app_browsertest.cc",
"../browser/performance_memory_browsertest.cc",
"../browser/pointer_lock_browsertest.cc",
@@ -866,7 +872,6 @@ test("content_browsertests") {
"../browser/pointer_lock_browsertest_mac.mm",
"../browser/portal/portal_browsertest.cc",
"../browser/power_monitor_browsertest.cc",
- "../browser/presentation/presentation_browsertest.cc",
"../browser/renderer_host/input/autoscroll_browsertest.cc",
"../browser/renderer_host/input/composited_scrolling_browsertest.cc",
"../browser/renderer_host/input/compositor_event_ack_browsertest.cc",
@@ -908,6 +913,7 @@ test("content_browsertests") {
"../browser/site_per_process_hit_test_browsertest.cc",
"../browser/site_per_process_mac_browsertest.mm",
"../browser/site_per_process_unload_browsertest.cc",
+ "../browser/sms/sms_browsertest.cc",
"../browser/snapshot_browsertest.cc",
"../browser/storage_partition_impl_browsertest.cc",
"../browser/tracing/background_tracing_manager_browsertest.cc",
@@ -917,12 +923,12 @@ test("content_browsertests") {
"../browser/tracing/tracing_controller_browsertest.cc",
"../browser/utility_process_host_browsertest.cc",
"../browser/vibration_browsertest.cc",
- "../browser/wake_lock/wake_lock_browsertest.cc",
"../browser/web_contents/opened_by_dom_browsertest.cc",
"../browser/web_contents/web_contents_impl_browsertest.cc",
"../browser/web_contents/web_contents_view_aura_browsertest.cc",
"../browser/web_contents_binding_set_browsertest.cc",
"../browser/web_package/signed_exchange_request_handler_browsertest.cc",
+ "../browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc",
"../browser/webkit_browsertest.cc",
"../browser/webrtc/webrtc_audio_browsertest.cc",
"../browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc",
@@ -1031,8 +1037,8 @@ test("content_browsertests") {
"//services/content/public/cpp",
"//services/content/public/mojom",
"//services/device/public/cpp:device_features",
+ "//services/device/public/cpp:test_support",
"//services/device/public/cpp/generic_sensor",
- "//services/device/public/cpp/test:test_support",
"//services/device/public/mojom",
"//services/device/public/mojom:generic_sensor",
"//services/image_annotation/public/cpp:cpp",
@@ -1041,6 +1047,7 @@ test("content_browsertests") {
"//services/network:test_support",
"//services/service_manager/public/cpp",
"//services/test/echo/public/mojom",
+ "//services/tracing:privacy_check",
"//services/video_capture/public/cpp",
"//services/video_capture/public/cpp:mocks",
"//services/video_capture/public/mojom:constants",
@@ -1065,6 +1072,7 @@ test("content_browsertests") {
"//ui/events:test_support",
"//ui/events/blink:blink",
"//ui/gfx",
+ "//ui/gfx:gfx_switches",
"//ui/gfx/geometry",
"//ui/gl",
"//ui/gl:test_support",
@@ -1132,7 +1140,6 @@ test("content_browsertests") {
"//ppapi/tests/test_case.html",
"//ppapi/tests/test_page.css",
"//ppapi/tests/test_url_loader_data/",
- "//third_party/pyftpdlib/",
"//third_party/pywebsocket/src/mod_pywebsocket/",
"//third_party/tlslite/",
]
@@ -1148,6 +1155,8 @@ test("content_browsertests") {
"../browser/accessibility/accessibility_browsertest.cc",
"../browser/accessibility/accessibility_browsertest.h",
"../browser/accessibility/accessibility_win_browsertest.cc",
+ "../browser/accessibility/ax_platform_node_textprovider_win_browsertest.cc",
+ "../browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc",
"../browser/accessibility/ax_platform_node_win_browsertest.cc",
"../browser/renderer_host/accessibility_object_lifetime_win_browsertest.cc",
"../browser/renderer_host/accessibility_tree_linkage_win_browsertest.cc",
@@ -1223,6 +1232,7 @@ test("content_browsertests") {
"../browser/host_zoom_map_impl_browsertest.cc",
"../browser/serial/serial_browsertest.cc",
"../browser/speech/speech_recognition_browsertest.cc",
+ "../browser/speech/tts_ssml_browsertest.cc",
"../browser/zoom_browsertest.cc",
]
deps += [ "//content/browser/speech/proto" ]
@@ -1409,6 +1419,7 @@ test("content_unittests") {
"../browser/bluetooth/bluetooth_allowed_devices_unittest.cc",
"../browser/bluetooth/bluetooth_blocklist_unittest.cc",
"../browser/bluetooth/bluetooth_device_chooser_controller_unittest.cc",
+ "../browser/bluetooth/bluetooth_util_unittest.cc",
"../browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc",
"../browser/browser_associated_interface_unittest.cc",
"../browser/browser_main_loop_unittest.cc",
@@ -1430,9 +1441,8 @@ test("content_unittests") {
"../browser/cocoa/system_hotkey_map_unittest.mm",
"../browser/code_cache/generated_code_cache_unittest.cc",
"../browser/compositor/reflector_impl_unittest.cc",
- "../browser/compositor/software_browser_compositor_output_surface_unittest.cc",
"../browser/cookie_store/cookie_store_manager_unittest.cc",
- "../browser/devtools/devtools_background_services_context_unittest.cc",
+ "../browser/devtools/devtools_background_services_context_impl_unittest.cc",
"../browser/devtools/devtools_http_handler_unittest.cc",
"../browser/devtools/devtools_manager_unittest.cc",
"../browser/devtools/devtools_video_consumer_unittest.cc",
@@ -1462,7 +1472,6 @@ test("content_unittests") {
"../browser/download/download_request_core_unittest.cc",
"../browser/download/save_package_unittest.cc",
"../browser/fileapi/browser_file_system_helper_unittest.cc",
- "../browser/fileapi/file_system_chooser_unittest.cc",
"../browser/fileapi/file_system_operation_runner_unittest.cc",
"../browser/frame_host/ancestor_throttle_unittest.cc",
"../browser/frame_host/back_forward_cache_metrics_unittest.cc",
@@ -1523,10 +1532,12 @@ test("content_unittests") {
"../browser/indexed_db/mock_mojo_indexed_db_database_callbacks.cc",
"../browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h",
"../browser/indexed_db/scopes/disjoint_range_lock_manager_unittest.cc",
+ "../browser/indexed_db/scopes/leveldb_scope_unittest.cc",
"../browser/indexed_db/scopes/leveldb_scopes_coding_unittest.cc",
"../browser/indexed_db/scopes/leveldb_scopes_tasks_unittest.cc",
"../browser/indexed_db/scopes/leveldb_scopes_test_utils.cc",
"../browser/indexed_db/scopes/leveldb_scopes_test_utils.h",
+ "../browser/indexed_db/scopes/leveldb_scopes_unittest.cc",
"../browser/indexed_db/scopes/scopes_lock_manager_unittest.cc",
"../browser/loader/cross_site_document_resource_handler_unittest.cc",
"../browser/loader/data_pipe_to_source_stream_unittest.cc",
@@ -1560,6 +1571,7 @@ test("content_unittests") {
"../browser/media/flinging_renderer_unittest.cc",
"../browser/media/forwarding_audio_stream_factory_unittest.cc",
"../browser/media/media_devices_permission_checker_unittest.cc",
+ "../browser/media/media_experiment_manager_unittest.cc",
"../browser/media/media_internals_unittest.cc",
"../browser/media/midi_host_unittest.cc",
"../browser/media/session/media_session_controller_unittest.cc",
@@ -1574,6 +1586,8 @@ test("content_unittests") {
"../browser/memory/swap_metrics_driver_impl_unittest.cc",
"../browser/memory/test_memory_monitor.cc",
"../browser/memory/test_memory_monitor.h",
+ "../browser/native_file_system/file_system_chooser_unittest.cc",
+ "../browser/native_file_system/native_file_system_file_handle_impl_unittest.cc",
"../browser/net/network_quality_observer_impl_unittest.cc",
"../browser/net/quota_policy_cookie_store_unittest.cc",
"../browser/network_service_client_unittest.cc",
@@ -1665,7 +1679,9 @@ test("content_unittests") {
"../browser/renderer_host/web_database_host_impl_unittest.cc",
"../browser/resolve_proxy_msg_helper_unittest.cc",
"../browser/sandbox_mac_unittest.mm",
+ "../browser/scheduler/browser_io_task_environment_unittest.cc",
"../browser/scheduler/browser_task_executor_unittest.cc",
+ "../browser/scheduler/browser_task_queues_unittest.cc",
"../browser/scheduler/browser_ui_thread_scheduler_unittest.cc",
"../browser/scheduler/responsiveness/calculator_unittest.cc",
"../browser/scheduler/responsiveness/watcher_unittest.cc",
@@ -1694,6 +1710,8 @@ test("content_unittests") {
"../browser/service_worker/service_worker_version_unittest.cc",
"../browser/shareable_file_reference_unittest.cc",
"../browser/site_instance_impl_unittest.cc",
+ "../browser/sms/sms_parser_unittest.cc",
+ "../browser/sms/sms_service_impl_unittest.cc",
"../browser/speech/tts_controller_unittest.cc",
"../browser/startup_task_runner_unittest.cc",
"../browser/storage_partition_impl_map_unittest.cc",
@@ -1750,6 +1768,7 @@ test("content_unittests") {
"../common/content_switches_internal_unittest.cc",
"../common/cursors/webcursor_unittest.cc",
"../common/dom_storage/dom_storage_map_unittest.cc",
+ "../common/font_list_unittest.cc",
"../common/input/actions_parser_unittest.cc",
"../common/input/event_with_latency_info_unittest.cc",
"../common/input/gesture_event_stream_validator_unittest.cc",
@@ -1792,7 +1811,6 @@ test("content_unittests") {
"../renderer/loader/test_request_peer.cc",
"../renderer/loader/test_request_peer.h",
"../renderer/loader/url_loader_client_impl_unittest.cc",
- "../renderer/loader/web_data_consumer_handle_impl_unittest.cc",
"../renderer/loader/web_url_loader_impl_unittest.cc",
"../renderer/low_memory_mode_controller_unittest.cc",
"../renderer/media/audio/audio_output_ipc_factory_unittest.cc",
@@ -1841,7 +1859,6 @@ test("content_unittests") {
"../renderer/media/webrtc/rtc_rtp_transceiver_unittest.cc",
"../renderer/media/webrtc/rtc_stats_unittest.cc",
"../renderer/media/webrtc/rtc_video_decoder_adapter_unittest.cc",
- "../renderer/media/webrtc/rtc_video_decoder_unittest.cc",
"../renderer/media/webrtc/rtc_video_encoder_unittest.cc",
"../renderer/media/webrtc/stun_field_trial_unittest.cc",
"../renderer/media/webrtc/task_queue_factory_unittest.cc",
@@ -1854,9 +1871,7 @@ test("content_unittests") {
"../renderer/media/webrtc/webrtc_set_description_observer_unittest.cc",
"../renderer/media/webrtc/webrtc_video_track_source_unittest.cc",
"../renderer/media/webrtc_local_audio_source_provider_unittest.cc",
- "../renderer/media_capture_from_element/canvas_capture_handler_unittest.cc",
"../renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc",
- "../renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc",
"../renderer/media_recorder/audio_track_recorder_unittest.cc",
"../renderer/media_recorder/media_recorder_handler_unittest.cc",
"../renderer/media_recorder/video_track_recorder_unittest.cc",
@@ -1867,10 +1882,8 @@ test("content_unittests") {
"../renderer/render_frame_metadata_observer_impl_unittest.cc",
"../renderer/render_thread_impl_unittest.cc",
"../renderer/render_widget_unittest.cc",
- "../renderer/service_worker/service_worker_context_client_unittest.cc",
"../renderer/service_worker/service_worker_provider_context_unittest.cc",
"../renderer/service_worker/service_worker_subresource_loader_unittest.cc",
- "../renderer/service_worker/service_worker_timeout_timer_unittest.cc",
"../renderer/skia_benchmarking_extension_unittest.cc",
"../renderer/v8_value_converter_impl_unittest.cc",
"../renderer/worker/worker_thread_registry_unittest.cc",
@@ -1984,8 +1997,8 @@ test("content_unittests") {
"//printing",
"//services/audio/public/cpp:test_support",
"//services/audio/public/mojom",
+ "//services/device/public/cpp:test_support",
"//services/device/public/cpp/generic_sensor",
- "//services/device/public/cpp/test:test_support",
"//services/device/public/mojom",
"//services/file:lib",
"//services/file/public/mojom",
@@ -2104,6 +2117,7 @@ test("content_unittests") {
"../renderer/media_recorder/media_recorder_handler_unittest.cc",
"../renderer/media_recorder/video_track_recorder_unittest.cc",
]
+ defines += [ "IS_CHROMECAST" ]
}
# Screen capture unit tests.
@@ -2136,6 +2150,7 @@ test("content_unittests") {
"//third_party/blink/public/common",
"//third_party/blink/public/common:font_unique_name_table_proto",
"//third_party/iaccessible2",
+ "//ui/base/idle:test_support",
"//ui/base/win/system_media_controls:test_support",
]
libs = [
@@ -2218,6 +2233,7 @@ test("content_unittests") {
if (!is_linux_without_udev && !is_android) {
sources += [ "../browser/webauth/authenticator_impl_unittest.cc" ]
deps += [
+ "//components/autofill/content/browser/webauthn",
"//device/base",
"//device/fido",
"//device/fido:mocks",
@@ -2243,10 +2259,7 @@ test("content_unittests") {
deps += [ "//ui/events:test_support" ]
}
if (!use_aura && !is_mac) {
- sources -= [
- "../browser/compositor/reflector_impl_unittest.cc",
- "../browser/compositor/software_browser_compositor_output_surface_unittest.cc",
- ]
+ sources -= [ "../browser/compositor/reflector_impl_unittest.cc" ]
}
if (!is_win && !is_mac) {
@@ -2340,6 +2353,7 @@ group("test_buildbucket_api_gpu_use_cases") {
# The test runner and its dependencies.
"//testing/scripts/test_buildbucket_api_gpu_use_cases.py",
+ "//content/test/gpu/gather_power_measurement_results.py",
"//content/test/gpu/gather_swarming_json_results.py",
]
}
diff --git a/chromium/content/test/fuzzer/BUILD.gn b/chromium/content/test/fuzzer/BUILD.gn
index ef82ef83b0c..32652f080a3 100644
--- a/chromium/content/test/fuzzer/BUILD.gn
+++ b/chromium/content/test/fuzzer/BUILD.gn
@@ -112,6 +112,43 @@ fuzzer_test("signed_exchange_envelope_fuzzer") {
seed_corpus = "//content/test/data/sxg/"
}
+fuzzer_test("devtools_protocol_encoding_cbor_fuzzer") {
+ sources = [
+ "../../browser/devtools/devtools_protocol_encoding.cc",
+ "../../browser/devtools/devtools_protocol_encoding.h",
+ "../../browser/devtools/devtools_protocol_encoding_cbor_fuzzer.cc",
+ ]
+ deps = [
+ "//base",
+ "//third_party/inspector_protocol:encoding",
+ ]
+ seed_corpus =
+ "../../browser/devtools/devtools_protocol_encoding_cbor_fuzzer_corpus/"
+}
+
+fuzzer_test("devtools_protocol_encoding_json_fuzzer") {
+ sources = [
+ "../../browser/devtools/devtools_protocol_encoding.cc",
+ "../../browser/devtools/devtools_protocol_encoding.h",
+ "../../browser/devtools/devtools_protocol_encoding_json_fuzzer.cc",
+ ]
+ deps = [
+ "//base",
+ "//third_party/inspector_protocol:encoding",
+ ]
+ seed_corpus = "//third_party/grpc/src/test/core/json/corpus/"
+}
+
+fuzzer_test("inspector_fuzzer") {
+ sources = [
+ "../../browser/devtools/inspector_fuzzer.cc",
+ ]
+ deps = [
+ "//third_party/inspector_protocol:encoding",
+ ]
+ seed_corpus = "//components/cbor/reader_fuzzer_corpus/"
+}
+
fuzzer_test("http_structured_header_fuzzer") {
sources = [
"http_structured_header_fuzzer.cc",
@@ -224,3 +261,20 @@ if (is_win) {
]
}
}
+
+fuzzer_test("speech_audio_encoder_fuzzer") {
+ sources = [
+ "../../browser/speech/audio_buffer.cc",
+ "../../browser/speech/audio_buffer.h",
+ "../../browser/speech/audio_encoder.cc",
+ "../../browser/speech/audio_encoder.h",
+ "../../browser/speech/audio_encoder_fuzzer.cc",
+ "//base/test/fuzzed_data_provider.h",
+ "//content/common/content_export.h",
+ ]
+
+ deps = [
+ "//base",
+ "//third_party/flac",
+ ]
+}
diff --git a/chromium/content/utility/BUILD.gn b/chromium/content/utility/BUILD.gn
index 21dd715a6f8..992dde8da78 100644
--- a/chromium/content/utility/BUILD.gn
+++ b/chromium/content/utility/BUILD.gn
@@ -54,7 +54,6 @@ jumbo_source_set("utility") {
"//services/video_capture/public/mojom:constants",
"//services/viz:lib",
"//third_party/blink/public:blink_headers",
- "//third_party/blink/public:mojo_bindings",
"//url",
]
diff --git a/chromium/content/utility/utility_main.cc b/chromium/content/utility/utility_main.cc
index a66fd09cf67..d0795c0c160 100644
--- a/chromium/content/utility/utility_main.cc
+++ b/chromium/content/utility/utility_main.cc
@@ -5,10 +5,10 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/leak_annotations.h"
-#include "base/message_loop/message_loop.h"
#include "base/optional.h"
#include "base/power_monitor/power_monitor.h"
#include "base/run_loop.h"
+#include "base/task/single_thread_task_executor.h"
#include "base/threading/platform_thread.h"
#include "base/timer/hi_res_timer_manager.h"
#include "build/build_config.h"
@@ -45,10 +45,10 @@ namespace content {
// Mainline routine for running as the utility process.
int UtilityMain(const MainFunctionParams& parameters) {
- const base::MessageLoop::Type message_loop_type =
+ const base::MessagePump::Type message_pump_type =
parameters.command_line.HasSwitch(switches::kMessageLoopTypeUi)
- ? base::MessageLoop::TYPE_UI
- : base::MessageLoop::TYPE_DEFAULT;
+ ? base::MessagePump::Type::UI
+ : base::MessagePump::Type::DEFAULT;
#if defined(OS_MACOSX)
// On Mac, the TYPE_UI pump for the main thread is an NSApplication loop. In
@@ -57,14 +57,14 @@ int UtilityMain(const MainFunctionParams& parameters) {
// TYPE_UI pump generally just need a NS/CFRunLoop to pump system work
// sources, so choose that pump type instead. A NSRunLoop MessagePump is used
// for TYPE_UI MessageLoops on non-main threads.
- base::MessageLoop::InitMessagePumpForUIFactory(
+ base::MessagePump::OverrideMessagePumpForUIFactory(
[]() -> std::unique_ptr<base::MessagePump> {
return std::make_unique<base::MessagePumpNSRunLoop>();
});
#endif
// The main message loop of the utility process.
- base::MessageLoop main_message_loop(message_loop_type);
+ base::SingleThreadTaskExecutor main_thread_task_executor(message_pump_type);
base::PlatformThread::SetName("CrUtilityMain");
if (parameters.command_line.HasSwitch(switches::kUtilityStartupDialog))
diff --git a/chromium/content/utility/utility_service_factory.cc b/chromium/content/utility/utility_service_factory.cc
index 3a4a72dbbfe..2e098ff3c2d 100644
--- a/chromium/content/utility/utility_service_factory.cc
+++ b/chromium/content/utility/utility_service_factory.cc
@@ -129,8 +129,8 @@ void RunNetworkServiceOnIOThread(
UtilityServiceFactory::UtilityServiceFactory()
: network_registry_(std::make_unique<service_manager::BinderRegistry>()),
- audio_registry_(std::make_unique<service_manager::BinderRegistry>()) {
- GetContentClient()->utility()->RegisterAudioBinders(audio_registry_.get());
+ audio_binders_(std::make_unique<service_manager::BinderMap>()) {
+ GetContentClient()->utility()->RegisterAudioBinders(audio_binders_.get());
}
UtilityServiceFactory::~UtilityServiceFactory() {}
@@ -206,7 +206,7 @@ void UtilityServiceFactory::RunService(
std::unique_ptr<service_manager::Service>
UtilityServiceFactory::CreateAudioService(
- service_manager::mojom::ServiceRequest request) {
+ mojo::PendingReceiver<service_manager::mojom::Service> receiver) {
#if defined(OS_MACOSX)
// Don't connect to launch services when running sandboxed
// (https://crbug.com/874785).
@@ -238,8 +238,8 @@ UtilityServiceFactory::CreateAudioService(
#endif
- return audio::CreateStandaloneService(std::move(audio_registry_),
- std::move(request));
+ return audio::CreateStandaloneService(std::move(audio_binders_),
+ std::move(receiver));
}
} // namespace content
diff --git a/chromium/content/utility/utility_service_factory.h b/chromium/content/utility/utility_service_factory.h
index 1313ee5cff8..280ee0ee9ba 100644
--- a/chromium/content/utility/utility_service_factory.h
+++ b/chromium/content/utility/utility_service_factory.h
@@ -12,6 +12,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "services/service_manager/public/cpp/binder_map.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/service.h"
#include "services/service_manager/public/mojom/service.mojom.h"
@@ -30,12 +31,12 @@ class UtilityServiceFactory {
private:
std::unique_ptr<service_manager::Service> CreateAudioService(
- service_manager::mojom::ServiceRequest request);
+ mojo::PendingReceiver<service_manager::mojom::Service> receiver);
// Allows embedders to register their interface implementations before the
// network or audio services are created. Used for testing.
std::unique_ptr<service_manager::BinderRegistry> network_registry_;
- std::unique_ptr<service_manager::BinderRegistry> audio_registry_;
+ std::unique_ptr<service_manager::BinderMap> audio_binders_;
DISALLOW_COPY_AND_ASSIGN(UtilityServiceFactory);
};